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