1/*
2 * Copyright 2019-2022 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
30typedef 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 */
38static const char *cert_filename = NULL;
39
40static 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
51static 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 */
89static 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
101static 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
142static 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    while (dup_pk == NULL) {
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        if (!ret || !TEST_ptr(dup_pk = EVP_PKEY_dup(pk)))
259            goto err;
260
261        ret = TEST_int_eq(EVP_PKEY_eq(pk, dup_pk), 1);
262        EVP_PKEY_free(pk);
263        pk = dup_pk;
264        if (!ret)
265            goto err;
266    }
267
268 err:
269    RSA_free(rsa);
270    BN_free(bn1);
271    BN_free(bn2);
272    BN_free(bn3);
273    EVP_PKEY_free(pk);
274    EVP_KEYMGMT_free(km1);
275    EVP_KEYMGMT_free(km2);
276    EVP_KEYMGMT_free(km3);
277
278    return ret;
279}
280
281static int (*tests[])(FIXTURE *) = {
282    test_pass_rsa
283};
284
285static int test_pass_key(int n)
286{
287    SETUP_TEST_FIXTURE(FIXTURE, set_up);
288    EXECUTE_TEST(tests[n], tear_down);
289    return result;
290}
291
292static int test_evp_pkey_export_to_provider(int n)
293{
294    OSSL_LIB_CTX *libctx = NULL;
295    OSSL_PROVIDER *prov = NULL;
296    X509 *cert = NULL;
297    BIO *bio = NULL;
298    X509_PUBKEY *pubkey = NULL;
299    EVP_KEYMGMT *keymgmt = NULL;
300    EVP_PKEY *pkey = NULL;
301    void *keydata = NULL;
302    int ret = 0;
303
304    if (!TEST_ptr(libctx = OSSL_LIB_CTX_new())
305         || !TEST_ptr(prov = OSSL_PROVIDER_load(libctx, "default")))
306        goto end;
307
308    if ((bio = BIO_new_file(cert_filename, "r")) == NULL) {
309        TEST_error("Couldn't open '%s' for reading\n", cert_filename);
310        TEST_openssl_errors();
311        goto end;
312    }
313
314    if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
315        TEST_error("'%s' doesn't appear to be a X.509 certificate in PEM format\n",
316                   cert_filename);
317        TEST_openssl_errors();
318        goto end;
319    }
320
321    pubkey = X509_get_X509_PUBKEY(cert);
322    pkey = X509_PUBKEY_get0(pubkey);
323
324    if (n == 0) {
325        if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
326                                                            NULL, NULL)))
327            goto end;
328    } else if (n == 1) {
329        if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
330                                                            &keymgmt, NULL)))
331            goto end;
332    } else {
333        keymgmt = EVP_KEYMGMT_fetch(libctx, "RSA", NULL);
334
335        if (!TEST_ptr(keydata = evp_pkey_export_to_provider(pkey, NULL,
336                                                            &keymgmt, NULL)))
337            goto end;
338    }
339
340    ret = 1;
341 end:
342    BIO_free(bio);
343    X509_free(cert);
344    EVP_KEYMGMT_free(keymgmt);
345    OSSL_PROVIDER_unload(prov);
346    OSSL_LIB_CTX_free(libctx);
347    return ret;
348}
349
350int setup_tests(void)
351{
352    if (!TEST_ptr(cert_filename = test_get_argument(0)))
353        return 0;
354
355    ADD_ALL_TESTS(test_pass_key, 1);
356    ADD_ALL_TESTS(test_evp_pkey_export_to_provider, 3);
357    return 1;
358}
359