Home | History | Annotate | Line # | Download | only in test
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos /*
     11      1.1  christos  * RSA low level APIs are deprecated for public use, but still ok for
     12      1.1  christos  * internal use.
     13      1.1  christos  */
     14      1.1  christos #include "internal/deprecated.h"
     15      1.1  christos 
     16      1.1  christos #include <string.h>
     17      1.1  christos 
     18      1.1  christos #include <openssl/bio.h>
     19      1.1  christos #include <openssl/bn.h>
     20      1.1  christos #include <openssl/rsa.h>
     21      1.1  christos #include <openssl/evp.h>
     22      1.1  christos #include <openssl/pem.h>
     23      1.1  christos #include <openssl/provider.h>
     24      1.1  christos #include <openssl/core_names.h>
     25      1.1  christos #include "internal/core.h"
     26      1.1  christos #include "internal/nelem.h"
     27  1.1.1.2  christos #include "crypto/evp.h" /* For the internal API */
     28      1.1  christos #include "testutil.h"
     29      1.1  christos 
     30      1.1  christos typedef struct {
     31      1.1  christos     OSSL_LIB_CTX *ctx1;
     32      1.1  christos     OSSL_PROVIDER *prov1;
     33      1.1  christos     OSSL_LIB_CTX *ctx2;
     34      1.1  christos     OSSL_PROVIDER *prov2;
     35      1.1  christos } FIXTURE;
     36      1.1  christos 
     37      1.1  christos /* Collected arguments */
     38      1.1  christos static const char *cert_filename = NULL;
     39      1.1  christos 
     40      1.1  christos static void tear_down(FIXTURE *fixture)
     41      1.1  christos {
     42      1.1  christos     if (fixture != NULL) {
     43      1.1  christos         OSSL_PROVIDER_unload(fixture->prov1);
     44      1.1  christos         OSSL_PROVIDER_unload(fixture->prov2);
     45      1.1  christos         OSSL_LIB_CTX_free(fixture->ctx1);
     46      1.1  christos         OSSL_LIB_CTX_free(fixture->ctx2);
     47      1.1  christos         OPENSSL_free(fixture);
     48      1.1  christos     }
     49      1.1  christos }
     50      1.1  christos 
     51      1.1  christos static FIXTURE *set_up(const char *testcase_name)
     52      1.1  christos {
     53      1.1  christos     FIXTURE *fixture;
     54      1.1  christos 
     55      1.1  christos     if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))
     56      1.1  christos         || !TEST_ptr(fixture->ctx1 = OSSL_LIB_CTX_new())
     57      1.1  christos         || !TEST_ptr(fixture->prov1 = OSSL_PROVIDER_load(fixture->ctx1,
     58  1.1.1.2  christos                          "default"))
     59      1.1  christos         || !TEST_ptr(fixture->ctx2 = OSSL_LIB_CTX_new())
     60      1.1  christos         || !TEST_ptr(fixture->prov2 = OSSL_PROVIDER_load(fixture->ctx2,
     61  1.1.1.2  christos                          "default"))) {
     62      1.1  christos         tear_down(fixture);
     63      1.1  christos         return NULL;
     64      1.1  christos     }
     65      1.1  christos     return fixture;
     66      1.1  christos }
     67      1.1  christos 
     68      1.1  christos /* Array indexes */
     69  1.1.1.2  christos #define N 0
     70  1.1.1.2  christos #define E 1
     71  1.1.1.2  christos #define D 2
     72  1.1.1.2  christos #define P 3
     73  1.1.1.2  christos #define Q 4
     74  1.1.1.2  christos #define F3 5 /* Extra factor */
     75  1.1.1.2  christos #define DP 6
     76  1.1.1.2  christos #define DQ 7
     77  1.1.1.2  christos #define E3 8 /* Extra exponent */
     78  1.1.1.2  christos #define QINV 9
     79  1.1.1.2  christos #define C2 10 /* Extra coefficient */
     80      1.1  christos 
     81      1.1  christos /*
     82      1.1  christos  * We have to do this because OSSL_PARAM_get_ulong() can't handle params
     83      1.1  christos  * holding data that isn't exactly sizeof(uint32_t) or sizeof(uint64_t),
     84      1.1  christos  * and because the other end deals with BIGNUM, the resulting param might
     85      1.1  christos  * be any size.  In this particular test, we know that the expected data
     86      1.1  christos  * fits within an unsigned long, and we want to get the data in that form
     87      1.1  christos  * to make testing of values easier.
     88      1.1  christos  */
     89      1.1  christos static int get_ulong_via_BN(const OSSL_PARAM *p, unsigned long *goal)
     90      1.1  christos {
     91      1.1  christos     BIGNUM *n = NULL;
     92  1.1.1.2  christos     int ret = 1; /* Ever so hopeful */
     93      1.1  christos 
     94      1.1  christos     if (!TEST_true(OSSL_PARAM_get_BN(p, &n))
     95      1.1  christos         || !TEST_int_ge(BN_bn2nativepad(n, (unsigned char *)goal, sizeof(*goal)), 0))
     96      1.1  christos         ret = 0;
     97      1.1  christos     BN_free(n);
     98      1.1  christos     return ret;
     99      1.1  christos }
    100      1.1  christos 
    101      1.1  christos static int export_cb(const OSSL_PARAM *params, void *arg)
    102      1.1  christos {
    103      1.1  christos     unsigned long *keydata = arg;
    104      1.1  christos     const OSSL_PARAM *p = NULL;
    105      1.1  christos 
    106      1.1  christos     if (keydata == NULL)
    107      1.1  christos         return 0;
    108      1.1  christos 
    109      1.1  christos     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N))
    110      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[N]))
    111      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E))
    112      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[E]))
    113      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D))
    114      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[D])))
    115      1.1  christos         return 0;
    116      1.1  christos 
    117      1.1  christos     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1))
    118      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[P]))
    119      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2))
    120      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[Q]))
    121      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR3))
    122      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[F3])))
    123      1.1  christos         return 0;
    124      1.1  christos 
    125      1.1  christos     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT1))
    126      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[DP]))
    127      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT2))
    128      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[DQ]))
    129      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT3))
    130      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[E3])))
    131      1.1  christos         return 0;
    132      1.1  christos 
    133      1.1  christos     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1))
    134      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[QINV]))
    135      1.1  christos         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT2))
    136      1.1  christos         || !TEST_true(get_ulong_via_BN(p, &keydata[C2])))
    137      1.1  christos         return 0;
    138      1.1  christos 
    139      1.1  christos     return 1;
    140      1.1  christos }
    141      1.1  christos 
    142      1.1  christos static int test_pass_rsa(FIXTURE *fixture)
    143      1.1  christos {
    144      1.1  christos     size_t i;
    145      1.1  christos     int ret = 0;
    146      1.1  christos     RSA *rsa = NULL;
    147      1.1  christos     BIGNUM *bn1 = NULL, *bn2 = NULL, *bn3 = NULL;
    148      1.1  christos     EVP_PKEY *pk = NULL, *dup_pk = NULL;
    149      1.1  christos     EVP_KEYMGMT *km = NULL, *km1 = NULL, *km2 = NULL, *km3 = NULL;
    150      1.1  christos     void *provkey = NULL, *provkey2 = NULL;
    151      1.1  christos     BIGNUM *bn_primes[1] = { NULL };
    152      1.1  christos     BIGNUM *bn_exps[1] = { NULL };
    153      1.1  christos     BIGNUM *bn_coeffs[1] = { NULL };
    154      1.1  christos     /*
    155      1.1  christos      * 32-bit RSA key, extracted from this command,
    156      1.1  christos      * executed with OpenSSL 1.0.2:
    157      1.1  christos      * An extra factor was added just for testing purposes.
    158      1.1  christos      *
    159      1.1  christos      * openssl genrsa 32 | openssl rsa -text
    160      1.1  christos      */
    161      1.1  christos     static BN_ULONG expected[] = {
    162  1.1.1.2  christos         0xbc747fc5, /* N */
    163  1.1.1.2  christos         0x10001, /* E */
    164  1.1.1.2  christos         0x7b133399, /* D */
    165  1.1.1.2  christos         0xe963, /* P */
    166  1.1.1.2  christos         0xceb7, /* Q */
    167  1.1.1.2  christos         1, /* F3 */
    168  1.1.1.2  christos         0x8599, /* DP */
    169  1.1.1.2  christos         0xbd87, /* DQ */
    170  1.1.1.2  christos         2, /* E3 */
    171  1.1.1.2  christos         0xcc3b, /* QINV */
    172  1.1.1.2  christos         3, /* C3 */
    173  1.1.1.2  christos         0 /* Extra, should remain zero */
    174  1.1.1.2  christos     };
    175  1.1.1.2  christos     static unsigned long keydata[OSSL_NELEM(expected)] = {
    176  1.1.1.2  christos         0,
    177      1.1  christos     };
    178      1.1  christos 
    179      1.1  christos     if (!TEST_ptr(rsa = RSA_new()))
    180      1.1  christos         goto err;
    181      1.1  christos 
    182      1.1  christos     if (!TEST_ptr(bn1 = BN_new())
    183      1.1  christos         || !TEST_true(BN_set_word(bn1, expected[N]))
    184      1.1  christos         || !TEST_ptr(bn2 = BN_new())
    185      1.1  christos         || !TEST_true(BN_set_word(bn2, expected[E]))
    186      1.1  christos         || !TEST_ptr(bn3 = BN_new())
    187      1.1  christos         || !TEST_true(BN_set_word(bn3, expected[D]))
    188      1.1  christos         || !TEST_true(RSA_set0_key(rsa, bn1, bn2, bn3)))
    189      1.1  christos         goto err;
    190      1.1  christos 
    191      1.1  christos     if (!TEST_ptr(bn1 = BN_new())
    192      1.1  christos         || !TEST_true(BN_set_word(bn1, expected[P]))
    193      1.1  christos         || !TEST_ptr(bn2 = BN_new())
    194      1.1  christos         || !TEST_true(BN_set_word(bn2, expected[Q]))
    195      1.1  christos         || !TEST_true(RSA_set0_factors(rsa, bn1, bn2)))
    196      1.1  christos         goto err;
    197      1.1  christos 
    198      1.1  christos     if (!TEST_ptr(bn1 = BN_new())
    199      1.1  christos         || !TEST_true(BN_set_word(bn1, expected[DP]))
    200      1.1  christos         || !TEST_ptr(bn2 = BN_new())
    201      1.1  christos         || !TEST_true(BN_set_word(bn2, expected[DQ]))
    202      1.1  christos         || !TEST_ptr(bn3 = BN_new())
    203      1.1  christos         || !TEST_true(BN_set_word(bn3, expected[QINV]))
    204      1.1  christos         || !TEST_true(RSA_set0_crt_params(rsa, bn1, bn2, bn3)))
    205      1.1  christos         goto err;
    206      1.1  christos     bn1 = bn2 = bn3 = NULL;
    207      1.1  christos 
    208      1.1  christos     if (!TEST_ptr(bn_primes[0] = BN_new())
    209      1.1  christos         || !TEST_true(BN_set_word(bn_primes[0], expected[F3]))
    210      1.1  christos         || !TEST_ptr(bn_exps[0] = BN_new())
    211      1.1  christos         || !TEST_true(BN_set_word(bn_exps[0], expected[E3]))
    212      1.1  christos         || !TEST_ptr(bn_coeffs[0] = BN_new())
    213      1.1  christos         || !TEST_true(BN_set_word(bn_coeffs[0], expected[C2]))
    214      1.1  christos         || !TEST_true(RSA_set0_multi_prime_params(rsa, bn_primes, bn_exps,
    215  1.1.1.2  christos             bn_coeffs, 1)))
    216      1.1  christos         goto err;
    217      1.1  christos 
    218      1.1  christos     if (!TEST_ptr(pk = EVP_PKEY_new())
    219      1.1  christos         || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa)))
    220      1.1  christos         goto err;
    221      1.1  christos     rsa = NULL;
    222      1.1  christos 
    223      1.1  christos     if (!TEST_ptr(km1 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA", NULL))
    224      1.1  christos         || !TEST_ptr(km2 = EVP_KEYMGMT_fetch(fixture->ctx2, "RSA", NULL))
    225      1.1  christos         || !TEST_ptr(km3 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA-PSS", NULL))
    226      1.1  christos         || !TEST_ptr_ne(km1, km2))
    227      1.1  christos         goto err;
    228      1.1  christos 
    229      1.1  christos     for (;;) {
    230      1.1  christos         ret = 0;
    231      1.1  christos         km = km3;
    232      1.1  christos         /* Check that we can't export an RSA key into an RSA-PSS keymanager */
    233      1.1  christos         if (!TEST_ptr_null(provkey2 = evp_pkey_export_to_provider(pk, NULL,
    234  1.1.1.2  christos                                &km,
    235  1.1.1.2  christos                                NULL)))
    236      1.1  christos             goto err;
    237      1.1  christos 
    238      1.1  christos         if (!TEST_ptr(provkey = evp_pkey_export_to_provider(pk, NULL, &km1,
    239  1.1.1.2  christos                           NULL))
    240      1.1  christos             || !TEST_true(evp_keymgmt_export(km2, provkey,
    241  1.1.1.2  christos                 OSSL_KEYMGMT_SELECT_KEYPAIR,
    242  1.1.1.2  christos                 &export_cb, keydata)))
    243      1.1  christos             goto err;
    244      1.1  christos 
    245      1.1  christos         /*
    246      1.1  christos          * At this point, the hope is that keydata will have all the numbers
    247      1.1  christos          * from the key.
    248      1.1  christos          */
    249      1.1  christos 
    250      1.1  christos         for (i = 0; i < OSSL_NELEM(expected); i++) {
    251      1.1  christos             int rv = TEST_int_eq(expected[i], keydata[i]);
    252      1.1  christos 
    253      1.1  christos             if (!rv)
    254      1.1  christos                 TEST_info("i = %zu", i);
    255      1.1  christos             else
    256      1.1  christos                 ret++;
    257      1.1  christos         }
    258      1.1  christos 
    259      1.1  christos         ret = (ret == OSSL_NELEM(expected));
    260      1.1  christos 
    261      1.1  christos         if (!ret || dup_pk != NULL)
    262      1.1  christos             break;
    263      1.1  christos 
    264      1.1  christos         if (!TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
    265      1.1  christos             goto err;
    266      1.1  christos 
    267      1.1  christos         ret = TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
    268      1.1  christos         EVP_PKEY_free(pk);
    269      1.1  christos         pk = dup_pk;
    270      1.1  christos         if (!ret)
    271      1.1  christos             goto err;
    272      1.1  christos     }
    273      1.1  christos 
    274  1.1.1.2  christos err:
    275      1.1  christos     RSA_free(rsa);
    276      1.1  christos     BN_free(bn1);
    277      1.1  christos     BN_free(bn2);
    278      1.1  christos     BN_free(bn3);
    279      1.1  christos     EVP_PKEY_free(pk);
    280      1.1  christos     EVP_KEYMGMT_free(km1);
    281      1.1  christos     EVP_KEYMGMT_free(km2);
    282      1.1  christos     EVP_KEYMGMT_free(km3);
    283      1.1  christos 
    284      1.1  christos     return ret;
    285      1.1  christos }
    286      1.1  christos 
    287      1.1  christos static int (*tests[])(FIXTURE *) = {
    288      1.1  christos     test_pass_rsa
    289      1.1  christos };
    290      1.1  christos 
    291      1.1  christos static int test_pass_key(int n)
    292      1.1  christos {
    293      1.1  christos     SETUP_TEST_FIXTURE(FIXTURE, set_up);
    294      1.1  christos     EXECUTE_TEST(tests[n], tear_down);
    295      1.1  christos     return result;
    296      1.1  christos }
    297      1.1  christos 
    298      1.1  christos static int test_evp_pkey_export_to_provider(int n)
    299      1.1  christos {
    300      1.1  christos     OSSL_LIB_CTX *libctx = NULL;
    301      1.1  christos     OSSL_PROVIDER *prov = NULL;
    302      1.1  christos     X509 *cert = NULL;
    303      1.1  christos     BIO *bio = NULL;
    304      1.1  christos     X509_PUBKEY *pubkey = NULL;
    305      1.1  christos     EVP_KEYMGMT *keymgmt = NULL;
    306      1.1  christos     EVP_PKEY *pkey = NULL;
    307      1.1  christos     void *keydata = NULL;
    308      1.1  christos     int ret = 0;
    309      1.1  christos 
    310      1.1  christos     if (!TEST_ptr(libctx = OSSL_LIB_CTX_new())
    311  1.1.1.2  christos         || !TEST_ptr(prov = OSSL_PROVIDER_load(libctx, "default")))
    312      1.1  christos         goto end;
    313      1.1  christos 
    314      1.1  christos     if ((bio = BIO_new_file(cert_filename, "r")) == NULL) {
    315      1.1  christos         TEST_error("Couldn't open '%s' for reading\n", cert_filename);
    316      1.1  christos         TEST_openssl_errors();
    317      1.1  christos         goto end;
    318      1.1  christos     }
    319      1.1  christos 
    320      1.1  christos     if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
    321      1.1  christos         TEST_error("'%s' doesn't appear to be a X.509 certificate in PEM format\n",
    322  1.1.1.2  christos             cert_filename);
    323      1.1  christos         TEST_openssl_errors();
    324      1.1  christos         goto end;
    325      1.1  christos     }
    326      1.1  christos 
    327      1.1  christos     pubkey = X509_get_X509_PUBKEY(cert);
    328      1.1  christos     pkey = X509_PUBKEY_get0(pubkey);
    329      1.1  christos 
    330      1.1  christos     if (n == 0) {
    331      1.1  christos         if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
    332  1.1.1.2  christos                           NULL, NULL)))
    333      1.1  christos             goto end;
    334      1.1  christos     } else if (n == 1) {
    335      1.1  christos         if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
    336  1.1.1.2  christos                           &keymgmt, NULL)))
    337      1.1  christos             goto end;
    338      1.1  christos     } else {
    339      1.1  christos         keymgmt = EVP_KEYMGMT_fetch(libctx, "RSA", NULL);
    340      1.1  christos 
    341      1.1  christos         if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
    342  1.1.1.2  christos                           &keymgmt, NULL)))
    343      1.1  christos             goto end;
    344      1.1  christos     }
    345      1.1  christos 
    346      1.1  christos     ret = 1;
    347  1.1.1.2  christos end:
    348      1.1  christos     BIO_free(bio);
    349      1.1  christos     X509_free(cert);
    350      1.1  christos     EVP_KEYMGMT_free(keymgmt);
    351      1.1  christos     OSSL_PROVIDER_unload(prov);
    352      1.1  christos     OSSL_LIB_CTX_free(libctx);
    353      1.1  christos     return ret;
    354      1.1  christos }
    355      1.1  christos 
    356      1.1  christos int setup_tests(void)
    357      1.1  christos {
    358      1.1  christos     if (!TEST_ptr(cert_filename = test_get_argument(0)))
    359      1.1  christos         return 0;
    360      1.1  christos 
    361      1.1  christos     ADD_ALL_TESTS(test_pass_key, 1);
    362      1.1  christos     ADD_ALL_TESTS(test_evp_pkey_export_to_provider, 3);
    363      1.1  christos     return 1;
    364      1.1  christos }
    365