| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2020-04-23 20:55:52 +08:00
										 |  |  |  * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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 | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <openssl/bio.h>
 | 
					
						
							|  |  |  | #include <openssl/bn.h>
 | 
					
						
							|  |  |  | #include <openssl/rsa.h>
 | 
					
						
							|  |  |  | #include <openssl/evp.h>
 | 
					
						
							|  |  |  | #include <openssl/provider.h>
 | 
					
						
							|  |  |  | #include <openssl/core_names.h>
 | 
					
						
							| 
									
										
										
										
											2019-11-08 22:24:42 +08:00
										 |  |  | #include "internal/core.h"
 | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  | #include "internal/nelem.h"
 | 
					
						
							|  |  |  | #include "crypto/evp.h"          /* For the internal API */
 | 
					
						
							|  |  |  | #include "testutil.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     OPENSSL_CTX *ctx1; | 
					
						
							|  |  |  |     OSSL_PROVIDER *prov1; | 
					
						
							|  |  |  |     OPENSSL_CTX *ctx2; | 
					
						
							|  |  |  |     OSSL_PROVIDER *prov2; | 
					
						
							|  |  |  | } FIXTURE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void tear_down(FIXTURE *fixture) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (fixture != NULL) { | 
					
						
							|  |  |  |         OSSL_PROVIDER_unload(fixture->prov1); | 
					
						
							|  |  |  |         OSSL_PROVIDER_unload(fixture->prov2); | 
					
						
							|  |  |  |         OPENSSL_CTX_free(fixture->ctx1); | 
					
						
							|  |  |  |         OPENSSL_CTX_free(fixture->ctx2); | 
					
						
							|  |  |  |         OPENSSL_free(fixture); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static FIXTURE *set_up(const char *testcase_name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     FIXTURE *fixture; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture))) | 
					
						
							|  |  |  |         || !TEST_ptr(fixture->ctx1 = OPENSSL_CTX_new()) | 
					
						
							|  |  |  |         || !TEST_ptr(fixture->prov1 = OSSL_PROVIDER_load(fixture->ctx1, | 
					
						
							|  |  |  |                                                          "default")) | 
					
						
							|  |  |  |         || !TEST_ptr(fixture->ctx2 = OPENSSL_CTX_new()) | 
					
						
							|  |  |  |         || !TEST_ptr(fixture->prov2 = OSSL_PROVIDER_load(fixture->ctx2, | 
					
						
							|  |  |  |                                                          "default"))) { | 
					
						
							|  |  |  |         tear_down(fixture); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return fixture; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-08 22:24:42 +08:00
										 |  |  | /* Array indexes */ | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  | #define N       0
 | 
					
						
							|  |  |  | #define E       1
 | 
					
						
							|  |  |  | #define D       2
 | 
					
						
							|  |  |  | #define P       3
 | 
					
						
							|  |  |  | #define Q       4
 | 
					
						
							|  |  |  | #define F3      5                /* Extra factor */
 | 
					
						
							|  |  |  | #define DP      6
 | 
					
						
							|  |  |  | #define DQ      7
 | 
					
						
							|  |  |  | #define E3      8                /* Extra exponent */
 | 
					
						
							|  |  |  | #define QINV    9
 | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  | #define C2      10               /* Extra coefficient */
 | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-08 22:24:42 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * We have to do this because OSSL_PARAM_get_ulong() can't handle params | 
					
						
							|  |  |  |  * holding data that isn't exactly sizeof(uint32_t) or sizeof(uint64_t), | 
					
						
							|  |  |  |  * and because the other end deals with BIGNUM, the resulting param might | 
					
						
							|  |  |  |  * be any size.  In this particular test, we know that the expected data | 
					
						
							|  |  |  |  * fits within an unsigned long, and we want to get the data in that form | 
					
						
							|  |  |  |  * to make testing of values easier. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int get_ulong_via_BN(const OSSL_PARAM *p, unsigned long *goal) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BIGNUM *n = NULL; | 
					
						
							|  |  |  |     int ret = 1;                 /* Ever so hopeful */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_true(OSSL_PARAM_get_BN(p, &n)) | 
					
						
							|  |  |  |         || !TEST_true(BN_bn2nativepad(n, (unsigned char *)goal, sizeof(*goal)))) | 
					
						
							|  |  |  |         ret = 0; | 
					
						
							|  |  |  |     BN_free(n); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int export_cb(const OSSL_PARAM *params, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned long *keydata = arg; | 
					
						
							|  |  |  |     const OSSL_PARAM *p = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (keydata == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[N])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[E])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[D]))) | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-11-08 22:24:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[P])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[Q])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR3)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[F3]))) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT1)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[DP])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT2)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[DQ])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_EXPONENT3)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[E3]))) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT1)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[QINV])) | 
					
						
							|  |  |  |         || !TEST_ptr(p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_COEFFICIENT2)) | 
					
						
							|  |  |  |         || !TEST_true(get_ulong_via_BN(p, &keydata[C2]))) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2019-11-08 22:24:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int test_pass_rsa(FIXTURE *fixture) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |     size_t i; | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							|  |  |  |     RSA *rsa = NULL; | 
					
						
							|  |  |  |     BIGNUM *bn1 = NULL, *bn2 = NULL, *bn3 = NULL; | 
					
						
							|  |  |  |     EVP_PKEY *pk = NULL; | 
					
						
							|  |  |  |     EVP_KEYMGMT *km1 = NULL, *km2 = NULL; | 
					
						
							| 
									
										
										
										
											2020-02-03 22:36:15 +08:00
										 |  |  |     void *provkey = NULL; | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |     BIGNUM *bn_primes[1] = { NULL }; | 
					
						
							|  |  |  |     BIGNUM *bn_exps[1] = { NULL }; | 
					
						
							|  |  |  |     BIGNUM *bn_coeffs[1] = { NULL }; | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * 32-bit RSA key, extracted from this command, | 
					
						
							|  |  |  |      * executed with OpenSSL 1.0.2: | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |      * An extra factor was added just for testing purposes. | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * openssl genrsa 32 | openssl rsa -text | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     static BN_ULONG expected[] = { | 
					
						
							|  |  |  |         0xbc747fc5,              /* N */ | 
					
						
							|  |  |  |         0x10001,                 /* E */ | 
					
						
							|  |  |  |         0x7b133399,              /* D */ | 
					
						
							|  |  |  |         0xe963,                  /* P */ | 
					
						
							|  |  |  |         0xceb7,                  /* Q */ | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |         1,                       /* F3 */ | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |         0x8599,                  /* DP */ | 
					
						
							|  |  |  |         0xbd87,                  /* DQ */ | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |         2,                       /* E3 */ | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |         0xcc3b,                  /* QINV */ | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |         3,                       /* C3 */ | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |         0                        /* Extra, should remain zero */ | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     static unsigned long keydata[OSSL_NELEM(expected)] = { 0, }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(rsa = RSA_new())) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(bn1 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn1, expected[N])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn2 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn2, expected[E])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn3 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn3, expected[D])) | 
					
						
							|  |  |  |         || !TEST_true(RSA_set0_key(rsa, bn1, bn2, bn3))) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(bn1 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn1, expected[P])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn2 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn2, expected[Q])) | 
					
						
							|  |  |  |         || !TEST_true(RSA_set0_factors(rsa, bn1, bn2))) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(bn1 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn1, expected[DP])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn2 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn2, expected[DQ])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn3 = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn3, expected[QINV])) | 
					
						
							|  |  |  |         || !TEST_true(RSA_set0_crt_params(rsa, bn1, bn2, bn3))) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     bn1 = bn2 = bn3 = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 13:51:18 +08:00
										 |  |  |     if (!TEST_ptr(bn_primes[0] = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn_primes[0], expected[F3])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn_exps[0] = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn_exps[0], expected[E3])) | 
					
						
							|  |  |  |         || !TEST_ptr(bn_coeffs[0] = BN_new()) | 
					
						
							|  |  |  |         || !TEST_true(BN_set_word(bn_coeffs[0], expected[C2])) | 
					
						
							|  |  |  |         || !TEST_true(RSA_set0_multi_prime_params(rsa, bn_primes, bn_exps, | 
					
						
							|  |  |  |                                                   bn_coeffs, 1))) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |     if (!TEST_ptr(pk = EVP_PKEY_new()) | 
					
						
							|  |  |  |         || !TEST_true(EVP_PKEY_assign_RSA(pk, rsa))) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     rsa = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TEST_ptr(km1 = EVP_KEYMGMT_fetch(fixture->ctx1, "RSA", NULL)) | 
					
						
							|  |  |  |         || !TEST_ptr(km2 = EVP_KEYMGMT_fetch(fixture->ctx2, "RSA", NULL)) | 
					
						
							|  |  |  |         || !TEST_ptr_ne(km1, km2)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-21 13:21:26 +08:00
										 |  |  |     if (!TEST_ptr(provkey = evp_pkey_export_to_provider(pk, NULL, &km1, NULL)) | 
					
						
							|  |  |  |         || !TEST_true(evp_keymgmt_export(km2, provkey, | 
					
						
							|  |  |  |                                          OSSL_KEYMGMT_SELECT_KEYPAIR, | 
					
						
							|  |  |  |                                          &export_cb, keydata))) | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * At this point, the hope is that keydata will have all the numbers | 
					
						
							|  |  |  |      * from the key. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-08 22:24:42 +08:00
										 |  |  |     for (i = 0; i < OSSL_NELEM(expected); i++) { | 
					
						
							|  |  |  |         int rv = TEST_int_eq(expected[i], keydata[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!rv) | 
					
						
							|  |  |  |             TEST_info("i = %zu", i); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             ret++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-17 06:26:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ret = (ret == OSSL_NELEM(expected)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     RSA_free(rsa); | 
					
						
							|  |  |  |     BN_free(bn1); | 
					
						
							|  |  |  |     BN_free(bn2); | 
					
						
							|  |  |  |     BN_free(bn3); | 
					
						
							|  |  |  |     EVP_PKEY_free(pk); | 
					
						
							|  |  |  |     EVP_KEYMGMT_free(km1); | 
					
						
							|  |  |  |     EVP_KEYMGMT_free(km2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int (*tests[])(FIXTURE *) = { | 
					
						
							|  |  |  |     test_pass_rsa | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int test_pass_key(int n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SETUP_TEST_FIXTURE(FIXTURE, set_up); | 
					
						
							|  |  |  |     EXECUTE_TEST(tests[n], tear_down); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int setup_tests(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ADD_ALL_TESTS(test_pass_key, 1); | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } |