Add test to demonstrate the app's new engine key loading
authorRichard Levitte <levitte@openssl.org>
Mon, 30 Nov 2020 09:44:34 +0000 (10:44 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 2 Dec 2020 19:19:41 +0000 (20:19 +0100)
This adds a bit of functionality in ossltest, so it can now be used to
load PEM files.  It takes the file name as key ID, but just to make
sure faults aren't ignored, it requires all file names to be prefixed
with 'ot:'.

Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/13570)

engines/e_ossltest.c
test/recipes/90-test_store.t

index df2a3e14e83378197629477651103793a3ca6df2..15a7d75f1ef30cbaf715c5bad49ed89f2d6fe1f4 100644 (file)
 #include <openssl/aes.h>
 #include <openssl/rand.h>
 #include <openssl/crypto.h>
+#include <openssl/pem.h>
 
 #include "e_ossltest_err.c"
 
+#ifdef _WIN32
+# define strncasecmp _strnicmp
+#endif
+
 /* Engine Id and Name */
 static const char *engine_ossltest_id = "ossltest";
 static const char *engine_ossltest_name = "OpenSSL Test engine support";
@@ -317,6 +322,43 @@ static void destroy_ciphers(void)
     _hidden_aes_128_cbc = NULL;
 }
 
+/* Key loading */
+static EVP_PKEY *load_key(ENGINE *eng, const char *key_id, int pub,
+                          UI_METHOD *ui_method, void *ui_data)
+{
+    BIO *in;
+    EVP_PKEY *key;
+
+    if (strncasecmp(key_id, "ot:", 3) != 0)
+        return NULL;
+    key_id += 3;
+
+    fprintf(stderr, "[ossltest]Loading %s key %s\n",
+            pub ? "Public" : "Private", key_id);
+    in = BIO_new_file(key_id, "r");
+    if (!in)
+        return NULL;
+    if (pub)
+        key = PEM_read_bio_PUBKEY(in, NULL, 0, NULL);
+    else
+        key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
+    BIO_free(in);
+    return key;
+}
+
+static EVP_PKEY *ossltest_load_privkey(ENGINE *eng, const char *key_id,
+                                       UI_METHOD *ui_method, void *ui_data)
+{
+    return load_key(eng, key_id, 0, ui_method, ui_data);
+}
+
+static EVP_PKEY *ossltest_load_pubkey(ENGINE *eng, const char *key_id,
+                                      UI_METHOD *ui_method, void *ui_data)
+{
+    return load_key(eng, key_id, 1, ui_method, ui_data);
+}
+
+
 static int bind_ossltest(ENGINE *e)
 {
     /* Ensure the ossltest error handling is set up */
@@ -328,6 +370,8 @@ static int bind_ossltest(ENGINE *e)
         || !ENGINE_set_ciphers(e, ossltest_ciphers)
         || !ENGINE_set_RAND(e, ossltest_rand_method())
         || !ENGINE_set_destroy_function(e, ossltest_destroy)
+        || !ENGINE_set_load_privkey_function(e, ossltest_load_privkey)
+        || !ENGINE_set_load_pubkey_function(e, ossltest_load_pubkey)
         || !ENGINE_set_init_function(e, ossltest_init)
         || !ENGINE_set_finish_function(e, ossltest_finish)) {
         OSSLTESTerr(OSSLTEST_F_BIND_OSSLTEST, OSSLTEST_R_INIT_FAILED);
index 05e4b341f5213f0735483b1d24e71ac5aafd6515..a36a59fd8b42cdccbc31c4a95a7afda3174b4248 100644 (file)
@@ -9,7 +9,8 @@
 use File::Spec::Functions;
 use File::Copy;
 use MIME::Base64;
-use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_file data_file);
+use OpenSSL::Test qw(:DEFAULT srctop_file srctop_dir bldtop_file bldtop_dir
+                     data_file);
 use OpenSSL::Test::Utils;
 
 my $test_name = "test_store";
@@ -31,6 +32,9 @@ my @src_files =
       "test/testrsapub.pem",
       "test/testcrl.pem",
       "apps/server.pem" );
+my @src_rsa_files =
+    ( "test/testrsa.pem",
+      "test/testrsapub.pem" );
 my @generated_files =
     (
      ### generated from the source files
@@ -106,11 +110,46 @@ my $n = scalar @methods
         + 3
         + 11 );
 
+my $do_test_ossltest_store =
+    !(disabled("engine") || disabled("dynamic-engine"));
+
+if ($do_test_ossltest_store) {
+    # test loading with apps 'org.openssl.engine:' loader, using the
+    # ossltest engine.
+    $n += 4 * scalar @src_rsa_files;
+}
+
 plan skip_all => "No plan" if $n == 0;
 
 plan tests => $n;
 
 indir "store_$$" => sub {
+    if ($do_test_ossltest_store) {
+        # ossltest loads PEM files, with names prefixed with 'ot:'.
+        # This prefix ensures that the files are, in fact, loaded through
+        # that engine and not mistakenly going through the 'file:' loader.
+
+        my $engine_scheme = 'org.openssl.engine:';
+        $ENV{OPENSSL_ENGINES} = bldtop_dir("engines");
+
+        foreach (@src_rsa_files) {
+            my $file = srctop_file($_);
+            my $file_abs = to_abs_file($file);
+            my @pubin = $_ =~ m|pub\.pem$| ? ("-pubin") : ();
+
+            ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
+                        "-engine", "ossltest", "-inform", "engine",
+                        "-in", "ot:$file"])));
+            ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
+                        "-engine", "ossltest", "-inform", "engine",
+                        "-in", "ot:$file_abs"])));
+            ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
+                        "-in", "${engine_scheme}ossltest:ot:$file"])));
+            ok(run(app(["openssl", "rsa", "-text", "-noout", @pubin,
+                        "-in", "${engine_scheme}ossltest:ot:$file_abs"])));
+        }
+    }
+
  SKIP:
     {
         init() or die "init failed";