Fix alignment errors in hashtable fuzzer
[openssl.git] / test / provider_pkey_test.c
index d360c0cf3047e14f07b959f406d6d2ecc51fc04b..4abbdd33ec4d6a1077c0bc05fe839abbf974481d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #include <openssl/params.h>
 #include <openssl/core_names.h>
 #include <openssl/evp.h>
+#include <openssl/store.h>
+#include <openssl/ui.h>
 #include "testutil.h"
 #include "fake_rsaprov.h"
 
 static OSSL_LIB_CTX *libctx = NULL;
+extern int key_deleted; /* From fake_rsaprov.c */
 
 /* Fetch SIGNATURE method using a libctx and propq */
 static int fetch_sig(OSSL_LIB_CTX *ctx, const char *alg, const char *propq,
@@ -92,7 +95,7 @@ static int test_pkey_sig(void)
         /*
          * If this picks the wrong signature without realizing it
          * we can get a segfault or some internal error. At least watch
-         * whether fake-rsa sign_init is is exercised by calling sign.
+         * whether fake-rsa sign_init is exercised by calling sign.
          */
         if (!TEST_int_eq(EVP_PKEY_sign_init(ctx), 1))
             goto end;
@@ -115,6 +118,312 @@ end:
     return ret;
 }
 
+static int test_alternative_keygen_init(void)
+{
+    EVP_PKEY_CTX *ctx = NULL;
+    OSSL_PROVIDER *deflt = NULL;
+    OSSL_PROVIDER *fake_rsa = NULL;
+    const OSSL_PROVIDER *provider;
+    const char *provname;
+    int ret = 0;
+
+    if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
+        goto end;
+
+    /* first try without the fake RSA provider loaded */
+    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL)))
+        goto end;
+
+    if (!TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0))
+        goto end;
+
+    if (!TEST_ptr(provider = EVP_PKEY_CTX_get0_provider(ctx)))
+        goto end;
+
+    if (!TEST_ptr(provname = OSSL_PROVIDER_get0_name(provider)))
+        goto end;
+
+    if (!TEST_str_eq(provname, "default"))
+        goto end;
+
+    EVP_PKEY_CTX_free(ctx);
+    ctx = NULL;
+
+    /* now load fake RSA and try again */
+    if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
+        return 0;
+
+    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
+                                                   "?provider=fake-rsa")))
+        goto end;
+
+    if (!TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0))
+        goto end;
+
+    if (!TEST_ptr(provider = EVP_PKEY_CTX_get0_provider(ctx)))
+        goto end;
+
+    if (!TEST_ptr(provname = OSSL_PROVIDER_get0_name(provider)))
+        goto end;
+
+    if (!TEST_str_eq(provname, "fake-rsa"))
+        goto end;
+
+    ret = 1;
+
+end:
+    fake_rsa_finish(fake_rsa);
+    OSSL_PROVIDER_unload(deflt);
+    EVP_PKEY_CTX_free(ctx);
+    return ret;
+}
+
+static int test_pkey_eq(void)
+{
+    OSSL_PROVIDER *deflt = NULL;
+    OSSL_PROVIDER *fake_rsa = NULL;
+    EVP_PKEY *pkey_fake = NULL;
+    EVP_PKEY *pkey_dflt = NULL;
+    EVP_PKEY_CTX *ctx = NULL;
+    OSSL_PARAM *params = NULL;
+    int ret = 0;
+
+    if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
+        return 0;
+
+    if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
+        goto end;
+
+    /* Construct a public key for fake-rsa */
+    if (!TEST_ptr(params = fake_rsa_key_params(0))
+        || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
+                                                      "provider=fake-rsa"))
+        || !TEST_true(EVP_PKEY_fromdata_init(ctx))
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_fake, EVP_PKEY_PUBLIC_KEY,
+                                        params))
+        || !TEST_ptr(pkey_fake))
+        goto end;
+
+    EVP_PKEY_CTX_free(ctx);
+    ctx = NULL;
+    OSSL_PARAM_free(params);
+    params = NULL;
+
+    /* Construct a public key for default */
+    if (!TEST_ptr(params = fake_rsa_key_params(0))
+        || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA",
+                                                      "provider=default"))
+        || !TEST_true(EVP_PKEY_fromdata_init(ctx))
+        || !TEST_true(EVP_PKEY_fromdata(ctx, &pkey_dflt, EVP_PKEY_PUBLIC_KEY,
+                                        params))
+        || !TEST_ptr(pkey_dflt))
+        goto end;
+
+    EVP_PKEY_CTX_free(ctx);
+    ctx = NULL;
+    OSSL_PARAM_free(params);
+    params = NULL;
+
+    /* now test for equality */
+    if (!TEST_int_eq(EVP_PKEY_eq(pkey_fake, pkey_dflt), 1))
+        goto end;
+
+    ret = 1;
+end:
+    fake_rsa_finish(fake_rsa);
+    OSSL_PROVIDER_unload(deflt);
+    EVP_PKEY_CTX_free(ctx);
+    EVP_PKEY_free(pkey_fake);
+    EVP_PKEY_free(pkey_dflt);
+    OSSL_PARAM_free(params);
+    return ret;
+}
+
+static int test_pkey_store(int idx)
+{
+    OSSL_PROVIDER *deflt = NULL;
+    OSSL_PROVIDER *fake_rsa = NULL;
+    int ret = 0;
+    EVP_PKEY *pkey = NULL;
+    OSSL_STORE_LOADER *loader = NULL;
+    OSSL_STORE_CTX *ctx = NULL;
+    OSSL_STORE_INFO *info;
+    const char *propq = idx == 0 ? "?provider=fake-rsa"
+                                 : "?provider=default";
+
+    /* It's important to load the default provider first for this test */
+    if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
+        goto end;
+
+    if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
+        goto end;
+
+    if (!TEST_ptr(loader = OSSL_STORE_LOADER_fetch(libctx, "fake_rsa",
+                                                   propq)))
+        goto end;
+
+    OSSL_STORE_LOADER_free(loader);
+
+    if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:test", libctx, propq,
+                                           NULL, NULL, NULL, NULL, NULL)))
+        goto end;
+
+    while (!OSSL_STORE_eof(ctx)
+           && (info = OSSL_STORE_load(ctx)) != NULL
+           && pkey == NULL) {
+        if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY)
+            pkey = OSSL_STORE_INFO_get1_PKEY(info);
+        OSSL_STORE_INFO_free(info);
+        info = NULL;
+    }
+
+    if (!TEST_ptr(pkey) || !TEST_int_eq(EVP_PKEY_is_a(pkey, "RSA"), 1))
+        goto end;
+
+    ret = 1;
+
+end:
+    fake_rsa_finish(fake_rsa);
+    OSSL_PROVIDER_unload(deflt);
+    OSSL_STORE_close(ctx);
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
+static int test_pkey_delete(void)
+{
+    OSSL_PROVIDER *deflt = NULL;
+    OSSL_PROVIDER *fake_rsa = NULL;
+    int ret = 0;
+    EVP_PKEY *pkey = NULL;
+    OSSL_STORE_LOADER *loader = NULL;
+    OSSL_STORE_CTX *ctx = NULL;
+    OSSL_STORE_INFO *info;
+    const char *propq = "?provider=fake-rsa";
+
+    /* It's important to load the default provider first for this test */
+    if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
+        goto end;
+
+    if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
+        goto end;
+
+    if (!TEST_ptr(loader = OSSL_STORE_LOADER_fetch(libctx, "fake_rsa",
+                                                   propq)))
+        goto end;
+
+    OSSL_STORE_LOADER_free(loader);
+
+    /* First iteration: load key, check it, delete it */
+    if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:test", libctx, propq,
+                                           NULL, NULL, NULL, NULL, NULL)))
+        goto end;
+
+    while (!OSSL_STORE_eof(ctx)
+           && (info = OSSL_STORE_load(ctx)) != NULL
+           && pkey == NULL) {
+        if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY)
+            pkey = OSSL_STORE_INFO_get1_PKEY(info);
+        OSSL_STORE_INFO_free(info);
+        info = NULL;
+    }
+
+    if (!TEST_ptr(pkey) || !TEST_int_eq(EVP_PKEY_is_a(pkey, "RSA"), 1))
+        goto end;
+    EVP_PKEY_free(pkey);
+    pkey = NULL;
+
+    if (!TEST_int_eq(OSSL_STORE_delete("fake_rsa:test", libctx, propq,
+                                       NULL, NULL, NULL), 1))
+        goto end;
+    if (!TEST_int_eq(OSSL_STORE_close(ctx), 1))
+        goto end;
+
+    /* Second iteration: load key should fail */
+    if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:test", libctx, propq,
+                                           NULL, NULL, NULL, NULL, NULL)))
+        goto end;
+
+    while (!OSSL_STORE_eof(ctx)) {
+           info = OSSL_STORE_load(ctx);
+          if (!TEST_ptr_null(info))
+               goto end;
+    }
+
+    ret = 1;
+
+end:
+    fake_rsa_finish(fake_rsa);
+    OSSL_PROVIDER_unload(deflt);
+    OSSL_STORE_close(ctx);
+    fake_rsa_restore_store_state();
+    return ret;
+}
+
+static int fake_pw_read_string(UI *ui, UI_STRING *uis)
+{
+    const char *passphrase = FAKE_PASSPHRASE;
+
+    if (UI_get_string_type(uis) == UIT_PROMPT) {
+        UI_set_result(ui, uis, passphrase);
+        return 1;
+    }
+
+    return 0;
+}
+
+static int test_pkey_store_open_ex(void)
+{
+    OSSL_PROVIDER *deflt = NULL;
+    OSSL_PROVIDER *fake_rsa = NULL;
+    int ret = 0;
+    EVP_PKEY *pkey = NULL;
+    OSSL_STORE_LOADER *loader = NULL;
+    OSSL_STORE_CTX *ctx = NULL;
+    const char *propq = "?provider=fake-rsa";
+    UI_METHOD *ui_method = NULL;
+
+    /* It's important to load the default provider first for this test */
+    if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default")))
+        goto end;
+
+    if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx)))
+        goto end;
+
+    if (!TEST_ptr(loader = OSSL_STORE_LOADER_fetch(libctx, "fake_rsa",
+                                                   propq)))
+        goto end;
+
+    OSSL_STORE_LOADER_free(loader);
+
+    if (!TEST_ptr(ui_method= UI_create_method("PW Callbacks")))
+        goto end;
+
+    if (UI_method_set_reader(ui_method, fake_pw_read_string))
+        goto end;
+
+    if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:openpwtest", libctx, propq,
+                                           ui_method, NULL, NULL, NULL, NULL)))
+        goto end;
+
+    /* retry w/o ui_method to ensure we actually enter pw checks and fail */
+    OSSL_STORE_close(ctx);
+    if (!TEST_ptr_null(ctx = OSSL_STORE_open_ex("fake_rsa:openpwtest", libctx,
+                                                propq, NULL, NULL, NULL, NULL,
+                                                NULL)))
+        goto end;
+
+    ret = 1;
+
+end:
+    UI_destroy_method(ui_method);
+    fake_rsa_finish(fake_rsa);
+    OSSL_PROVIDER_unload(deflt);
+    OSSL_STORE_close(ctx);
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
 int setup_tests(void)
 {
     libctx = OSSL_LIB_CTX_new();
@@ -122,6 +431,11 @@ int setup_tests(void)
         return 0;
 
     ADD_TEST(test_pkey_sig);
+    ADD_TEST(test_alternative_keygen_init);
+    ADD_TEST(test_pkey_eq);
+    ADD_ALL_TESTS(test_pkey_store, 2);
+    ADD_TEST(test_pkey_delete);
+    ADD_TEST(test_pkey_store_open_ex);
 
     return 1;
 }