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