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)] = { 176 0, 177 }; 178 179 if (!TEST_ptr(rsa = RSA_new())) 180 goto err; 181 182 if (!TEST_ptr(bn1 = BN_new()) 183 || !TEST_true(BN_set_word(bn1, expected[N])) 184 || !TEST_ptr(bn2 = BN_new()) 185 || !TEST_true(BN_set_word(bn2, expected[E])) 186 || !TEST_ptr(bn3 = BN_new()) 187 || !TEST_true(BN_set_word(bn3, expected[D])) 188 || !TEST_true(RSA_set0_key(rsa, bn1, bn2, bn3))) 189 goto err; 190 191 if (!TEST_ptr(bn1 = BN_new()) 192 || !TEST_true(BN_set_word(bn1, expected[P])) 193 || !TEST_ptr(bn2 = BN_new()) 194 || !TEST_true(BN_set_word(bn2, expected[Q])) 195 || !TEST_true(RSA_set0_factors(rsa, bn1, bn2))) 196 goto err; 197 198 if (!TEST_ptr(bn1 = BN_new()) 199 || !TEST_true(BN_set_word(bn1, expected[DP])) 200 || !TEST_ptr(bn2 = BN_new()) 201 || !TEST_true(BN_set_word(bn2, expected[DQ])) 202 || !TEST_ptr(bn3 = BN_new()) 203 || !TEST_true(BN_set_word(bn3, expected[QINV])) 204 || !TEST_true(RSA_set0_crt_params(rsa, bn1, bn2, bn3))) 205 goto err; 206 bn1 = bn2 = bn3 = NULL; 207 208 if (!TEST_ptr(bn_primes[0] = BN_new()) 209 || !TEST_true(BN_set_word(bn_primes[0], expected[F3])) 210 || !TEST_ptr(bn_exps[0] = BN_new()) 211 || !TEST_true(BN_set_word(bn_exps[0], expected[E3])) 212 || !TEST_ptr(bn_coeffs[0] = BN_new()) 213 || !TEST_true(BN_set_word(bn_coeffs[0], expected[C2])) 214 || !TEST_true(RSA_set0_multi_prime_params(rsa, bn_primes, bn_exps, 215 bn_coeffs, 1))) 216 goto err; 217 218 if (!TEST_ptr(pk = EVP_PKEY_new()) 219 || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa))) 220 goto err; 221 rsa = NULL; 222 223 if (!TEST_ptr(km1 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA", NULL)) 224 || !TEST_ptr(km2 = EVP_KEYMGMT_fetch(fixture->ctx2, "RSA", NULL)) 225 || !TEST_ptr(km3 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA-PSS", NULL)) 226 || !TEST_ptr_ne(km1, km2)) 227 goto err; 228 229 for (;;) { 230 ret = 0; 231 km = km3; 232 /* Check that we can't export an RSA key into an RSA-PSS keymanager */ 233 if (!TEST_ptr_null(provkey2 = evp_pkey_export_to_provider(pk, NULL, 234 &km, 235 NULL))) 236 goto err; 237 238 if (!TEST_ptr(provkey = evp_pkey_export_to_provider(pk, NULL, &km1, 239 NULL)) 240 || !TEST_true(evp_keymgmt_export(km2, provkey, 241 OSSL_KEYMGMT_SELECT_KEYPAIR, 242 &export_cb, keydata))) 243 goto err; 244 245 /* 246 * At this point, the hope is that keydata will have all the numbers 247 * from the key. 248 */ 249 250 for (i = 0; i < OSSL_NELEM(expected); i++) { 251 int rv = TEST_int_eq(expected[i], keydata[i]); 252 253 if (!rv) 254 TEST_info("i = %zu", i); 255 else 256 ret++; 257 } 258 259 ret = (ret == OSSL_NELEM(expected)); 260 261 if (!ret || dup_pk != NULL) 262 break; 263 264 if (!TEST_ptr(dup_pk = EVP_PKEY_dup(pk))) 265 goto err; 266 267 ret = TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1); 268 EVP_PKEY_free(pk); 269 pk = dup_pk; 270 if (!ret) 271 goto err; 272 } 273 274 err: 275 RSA_free(rsa); 276 BN_free(bn1); 277 BN_free(bn2); 278 BN_free(bn3); 279 EVP_PKEY_free(pk); 280 EVP_KEYMGMT_free(km1); 281 EVP_KEYMGMT_free(km2); 282 EVP_KEYMGMT_free(km3); 283 284 return ret; 285 } 286 287 static int (*tests[])(FIXTURE *) = { 288 test_pass_rsa 289 }; 290 291 static int test_pass_key(int n) 292 { 293 SETUP_TEST_FIXTURE(FIXTURE, set_up); 294 EXECUTE_TEST(tests[n], tear_down); 295 return result; 296 } 297 298 static int test_evp_pkey_export_to_provider(int n) 299 { 300 OSSL_LIB_CTX *libctx = NULL; 301 OSSL_PROVIDER *prov = NULL; 302 X509 *cert = NULL; 303 BIO *bio = NULL; 304 X509_PUBKEY *pubkey = NULL; 305 EVP_KEYMGMT *keymgmt = NULL; 306 EVP_PKEY *pkey = NULL; 307 void *keydata = NULL; 308 int ret = 0; 309 310 if (!TEST_ptr(libctx = OSSL_LIB_CTX_new()) 311 || !TEST_ptr(prov = OSSL_PROVIDER_load(libctx, "default"))) 312 goto end; 313 314 if ((bio = BIO_new_file(cert_filename, "r")) == NULL) { 315 TEST_error("Couldn't open '%s' for reading\n", cert_filename); 316 TEST_openssl_errors(); 317 goto end; 318 } 319 320 if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { 321 TEST_error("'%s' doesn't appear to be a X.509 certificate in PEM format\n", 322 cert_filename); 323 TEST_openssl_errors(); 324 goto end; 325 } 326 327 pubkey = X509_get_X509_PUBKEY(cert); 328 pkey = X509_PUBKEY_get0(pubkey); 329 330 if (n == 0) { 331 if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL, 332 NULL, NULL))) 333 goto end; 334 } else if (n == 1) { 335 if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL, 336 &keymgmt, NULL))) 337 goto end; 338 } else { 339 keymgmt = EVP_KEYMGMT_fetch(libctx, "RSA", NULL); 340 341 if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL, 342 &keymgmt, NULL))) 343 goto end; 344 } 345 346 ret = 1; 347 end: 348 BIO_free(bio); 349 X509_free(cert); 350 EVP_KEYMGMT_free(keymgmt); 351 OSSL_PROVIDER_unload(prov); 352 OSSL_LIB_CTX_free(libctx); 353 return ret; 354 } 355 356 int setup_tests(void) 357 { 358 if (!TEST_ptr(cert_filename = test_get_argument(0))) 359 return 0; 360 361 ADD_ALL_TESTS(test_pass_key, 1); 362 ADD_ALL_TESTS(test_evp_pkey_export_to_provider, 3); 363 return 1; 364 } 365