1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci * Copyright (c) 2018-2019, Oracle and/or its affiliates.  All rights reserved.
4e1051a39Sopenharmony_ci *
5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
6e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
9e1051a39Sopenharmony_ci */
10e1051a39Sopenharmony_ci
11e1051a39Sopenharmony_ci#include <openssl/err.h>
12e1051a39Sopenharmony_ci#include <openssl/bn.h>
13e1051a39Sopenharmony_ci#include "crypto/bn.h"
14e1051a39Sopenharmony_ci#include "rsa_local.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci/*
17e1051a39Sopenharmony_ci * Part of the RSA keypair test.
18e1051a39Sopenharmony_ci * Check the Chinese Remainder Theorem components are valid.
19e1051a39Sopenharmony_ci *
20e1051a39Sopenharmony_ci * See SP800-5bBr1
21e1051a39Sopenharmony_ci *   6.4.1.2.3: rsakpv1-crt Step 7
22e1051a39Sopenharmony_ci *   6.4.1.3.3: rsakpv2-crt Step 7
23e1051a39Sopenharmony_ci */
24e1051a39Sopenharmony_ciint ossl_rsa_check_crt_components(const RSA *rsa, BN_CTX *ctx)
25e1051a39Sopenharmony_ci{
26e1051a39Sopenharmony_ci    int ret = 0;
27e1051a39Sopenharmony_ci    BIGNUM *r = NULL, *p1 = NULL, *q1 = NULL;
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_ci    /* check if only some of the crt components are set */
30e1051a39Sopenharmony_ci    if (rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL) {
31e1051a39Sopenharmony_ci        if (rsa->dmp1 != NULL || rsa->dmq1 != NULL || rsa->iqmp != NULL)
32e1051a39Sopenharmony_ci            return 0;
33e1051a39Sopenharmony_ci        return 1; /* return ok if all components are NULL */
34e1051a39Sopenharmony_ci    }
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
37e1051a39Sopenharmony_ci    r = BN_CTX_get(ctx);
38e1051a39Sopenharmony_ci    p1 = BN_CTX_get(ctx);
39e1051a39Sopenharmony_ci    q1 = BN_CTX_get(ctx);
40e1051a39Sopenharmony_ci    if (q1 != NULL) {
41e1051a39Sopenharmony_ci        BN_set_flags(r, BN_FLG_CONSTTIME);
42e1051a39Sopenharmony_ci        BN_set_flags(p1, BN_FLG_CONSTTIME);
43e1051a39Sopenharmony_ci        BN_set_flags(q1, BN_FLG_CONSTTIME);
44e1051a39Sopenharmony_ci        ret = 1;
45e1051a39Sopenharmony_ci    } else {
46e1051a39Sopenharmony_ci        ret = 0;
47e1051a39Sopenharmony_ci    }
48e1051a39Sopenharmony_ci    ret = ret
49e1051a39Sopenharmony_ci          /* p1 = p -1 */
50e1051a39Sopenharmony_ci          && (BN_copy(p1, rsa->p) != NULL)
51e1051a39Sopenharmony_ci          && BN_sub_word(p1, 1)
52e1051a39Sopenharmony_ci          /* q1 = q - 1 */
53e1051a39Sopenharmony_ci          && (BN_copy(q1, rsa->q) != NULL)
54e1051a39Sopenharmony_ci          && BN_sub_word(q1, 1)
55e1051a39Sopenharmony_ci          /* (a) 1 < dP < (p – 1). */
56e1051a39Sopenharmony_ci          && (BN_cmp(rsa->dmp1, BN_value_one()) > 0)
57e1051a39Sopenharmony_ci          && (BN_cmp(rsa->dmp1, p1) < 0)
58e1051a39Sopenharmony_ci          /* (b) 1 < dQ < (q - 1). */
59e1051a39Sopenharmony_ci          && (BN_cmp(rsa->dmq1, BN_value_one()) > 0)
60e1051a39Sopenharmony_ci          && (BN_cmp(rsa->dmq1, q1) < 0)
61e1051a39Sopenharmony_ci          /* (c) 1 < qInv < p */
62e1051a39Sopenharmony_ci          && (BN_cmp(rsa->iqmp, BN_value_one()) > 0)
63e1051a39Sopenharmony_ci          && (BN_cmp(rsa->iqmp, rsa->p) < 0)
64e1051a39Sopenharmony_ci          /* (d) 1 = (dP . e) mod (p - 1)*/
65e1051a39Sopenharmony_ci          && BN_mod_mul(r, rsa->dmp1, rsa->e, p1, ctx)
66e1051a39Sopenharmony_ci          && BN_is_one(r)
67e1051a39Sopenharmony_ci          /* (e) 1 = (dQ . e) mod (q - 1) */
68e1051a39Sopenharmony_ci          && BN_mod_mul(r, rsa->dmq1, rsa->e, q1, ctx)
69e1051a39Sopenharmony_ci          && BN_is_one(r)
70e1051a39Sopenharmony_ci          /* (f) 1 = (qInv . q) mod p */
71e1051a39Sopenharmony_ci          && BN_mod_mul(r, rsa->iqmp, rsa->q, rsa->p, ctx)
72e1051a39Sopenharmony_ci          && BN_is_one(r);
73e1051a39Sopenharmony_ci    BN_clear(r);
74e1051a39Sopenharmony_ci    BN_clear(p1);
75e1051a39Sopenharmony_ci    BN_clear(q1);
76e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
77e1051a39Sopenharmony_ci    return ret;
78e1051a39Sopenharmony_ci}
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci/*
81e1051a39Sopenharmony_ci * Part of the RSA keypair test.
82e1051a39Sopenharmony_ci * Check that (√2)(2^(nbits/2 - 1) <= p <= 2^(nbits/2) - 1
83e1051a39Sopenharmony_ci *
84e1051a39Sopenharmony_ci * See SP800-5bBr1 6.4.1.2.1 Part 5 (c) & (g) - used for both p and q.
85e1051a39Sopenharmony_ci *
86e1051a39Sopenharmony_ci * (√2)(2^(nbits/2 - 1) = (√2/2)(2^(nbits/2))
87e1051a39Sopenharmony_ci */
88e1051a39Sopenharmony_ciint ossl_rsa_check_prime_factor_range(const BIGNUM *p, int nbits, BN_CTX *ctx)
89e1051a39Sopenharmony_ci{
90e1051a39Sopenharmony_ci    int ret = 0;
91e1051a39Sopenharmony_ci    BIGNUM *low;
92e1051a39Sopenharmony_ci    int shift;
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci    nbits >>= 1;
95e1051a39Sopenharmony_ci    shift = nbits - BN_num_bits(&ossl_bn_inv_sqrt_2);
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci    /* Upper bound check */
98e1051a39Sopenharmony_ci    if (BN_num_bits(p) != nbits)
99e1051a39Sopenharmony_ci        return 0;
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
102e1051a39Sopenharmony_ci    low = BN_CTX_get(ctx);
103e1051a39Sopenharmony_ci    if (low == NULL)
104e1051a39Sopenharmony_ci        goto err;
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci    /* set low = (√2)(2^(nbits/2 - 1) */
107e1051a39Sopenharmony_ci    if (!BN_copy(low, &ossl_bn_inv_sqrt_2))
108e1051a39Sopenharmony_ci        goto err;
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ci    if (shift >= 0) {
111e1051a39Sopenharmony_ci        /*
112e1051a39Sopenharmony_ci         * We don't have all the bits. ossl_bn_inv_sqrt_2 contains a rounded up
113e1051a39Sopenharmony_ci         * value, so there is a very low probability that we'll reject a valid
114e1051a39Sopenharmony_ci         * value.
115e1051a39Sopenharmony_ci         */
116e1051a39Sopenharmony_ci        if (!BN_lshift(low, low, shift))
117e1051a39Sopenharmony_ci            goto err;
118e1051a39Sopenharmony_ci    } else if (!BN_rshift(low, low, -shift)) {
119e1051a39Sopenharmony_ci        goto err;
120e1051a39Sopenharmony_ci    }
121e1051a39Sopenharmony_ci    if (BN_cmp(p, low) <= 0)
122e1051a39Sopenharmony_ci        goto err;
123e1051a39Sopenharmony_ci    ret = 1;
124e1051a39Sopenharmony_cierr:
125e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
126e1051a39Sopenharmony_ci    return ret;
127e1051a39Sopenharmony_ci}
128e1051a39Sopenharmony_ci
129e1051a39Sopenharmony_ci/*
130e1051a39Sopenharmony_ci * Part of the RSA keypair test.
131e1051a39Sopenharmony_ci * Check the prime factor (for either p or q)
132e1051a39Sopenharmony_ci * i.e: p is prime AND GCD(p - 1, e) = 1
133e1051a39Sopenharmony_ci *
134e1051a39Sopenharmony_ci * See SP800-56Br1 6.4.1.2.3 Step 5 (a to d) & (e to h).
135e1051a39Sopenharmony_ci */
136e1051a39Sopenharmony_ciint ossl_rsa_check_prime_factor(BIGNUM *p, BIGNUM *e, int nbits, BN_CTX *ctx)
137e1051a39Sopenharmony_ci{
138e1051a39Sopenharmony_ci    int ret = 0;
139e1051a39Sopenharmony_ci    BIGNUM *p1 = NULL, *gcd = NULL;
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci    /* (Steps 5 a-b) prime test */
142e1051a39Sopenharmony_ci    if (BN_check_prime(p, ctx, NULL) != 1
143e1051a39Sopenharmony_ci            /* (Step 5c) (√2)(2^(nbits/2 - 1) <= p <= 2^(nbits/2 - 1) */
144e1051a39Sopenharmony_ci            || ossl_rsa_check_prime_factor_range(p, nbits, ctx) != 1)
145e1051a39Sopenharmony_ci        return 0;
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
148e1051a39Sopenharmony_ci    p1 = BN_CTX_get(ctx);
149e1051a39Sopenharmony_ci    gcd = BN_CTX_get(ctx);
150e1051a39Sopenharmony_ci    if (gcd != NULL) {
151e1051a39Sopenharmony_ci        BN_set_flags(p1, BN_FLG_CONSTTIME);
152e1051a39Sopenharmony_ci        BN_set_flags(gcd, BN_FLG_CONSTTIME);
153e1051a39Sopenharmony_ci        ret = 1;
154e1051a39Sopenharmony_ci    } else {
155e1051a39Sopenharmony_ci        ret = 0;
156e1051a39Sopenharmony_ci    }
157e1051a39Sopenharmony_ci    ret = ret
158e1051a39Sopenharmony_ci          /* (Step 5d) GCD(p-1, e) = 1 */
159e1051a39Sopenharmony_ci          && (BN_copy(p1, p) != NULL)
160e1051a39Sopenharmony_ci          && BN_sub_word(p1, 1)
161e1051a39Sopenharmony_ci          && BN_gcd(gcd, p1, e, ctx)
162e1051a39Sopenharmony_ci          && BN_is_one(gcd);
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci    BN_clear(p1);
165e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
166e1051a39Sopenharmony_ci    return ret;
167e1051a39Sopenharmony_ci}
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci/*
170e1051a39Sopenharmony_ci * See SP800-56Br1 6.4.1.2.3 Part 6(a-b) Check the private exponent d
171e1051a39Sopenharmony_ci * satisfies:
172e1051a39Sopenharmony_ci *     (Step 6a) 2^(nBit/2) < d < LCM(p–1, q–1).
173e1051a39Sopenharmony_ci *     (Step 6b) 1 = (d*e) mod LCM(p–1, q–1)
174e1051a39Sopenharmony_ci */
175e1051a39Sopenharmony_ciint ossl_rsa_check_private_exponent(const RSA *rsa, int nbits, BN_CTX *ctx)
176e1051a39Sopenharmony_ci{
177e1051a39Sopenharmony_ci    int ret;
178e1051a39Sopenharmony_ci    BIGNUM *r, *p1, *q1, *lcm, *p1q1, *gcd;
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_ci    /* (Step 6a) 2^(nbits/2) < d */
181e1051a39Sopenharmony_ci    if (BN_num_bits(rsa->d) <= (nbits >> 1))
182e1051a39Sopenharmony_ci        return 0;
183e1051a39Sopenharmony_ci
184e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
185e1051a39Sopenharmony_ci    r = BN_CTX_get(ctx);
186e1051a39Sopenharmony_ci    p1 = BN_CTX_get(ctx);
187e1051a39Sopenharmony_ci    q1 = BN_CTX_get(ctx);
188e1051a39Sopenharmony_ci    lcm = BN_CTX_get(ctx);
189e1051a39Sopenharmony_ci    p1q1 = BN_CTX_get(ctx);
190e1051a39Sopenharmony_ci    gcd = BN_CTX_get(ctx);
191e1051a39Sopenharmony_ci    if (gcd != NULL) {
192e1051a39Sopenharmony_ci        BN_set_flags(r, BN_FLG_CONSTTIME);
193e1051a39Sopenharmony_ci        BN_set_flags(p1, BN_FLG_CONSTTIME);
194e1051a39Sopenharmony_ci        BN_set_flags(q1, BN_FLG_CONSTTIME);
195e1051a39Sopenharmony_ci        BN_set_flags(lcm, BN_FLG_CONSTTIME);
196e1051a39Sopenharmony_ci        BN_set_flags(p1q1, BN_FLG_CONSTTIME);
197e1051a39Sopenharmony_ci        BN_set_flags(gcd, BN_FLG_CONSTTIME);
198e1051a39Sopenharmony_ci        ret = 1;
199e1051a39Sopenharmony_ci    } else {
200e1051a39Sopenharmony_ci        ret = 0;
201e1051a39Sopenharmony_ci    }
202e1051a39Sopenharmony_ci    ret = (ret
203e1051a39Sopenharmony_ci          /* LCM(p - 1, q - 1) */
204e1051a39Sopenharmony_ci          && (ossl_rsa_get_lcm(ctx, rsa->p, rsa->q, lcm, gcd, p1, q1,
205e1051a39Sopenharmony_ci                               p1q1) == 1)
206e1051a39Sopenharmony_ci          /* (Step 6a) d < LCM(p - 1, q - 1) */
207e1051a39Sopenharmony_ci          && (BN_cmp(rsa->d, lcm) < 0)
208e1051a39Sopenharmony_ci          /* (Step 6b) 1 = (e . d) mod LCM(p - 1, q - 1) */
209e1051a39Sopenharmony_ci          && BN_mod_mul(r, rsa->e, rsa->d, lcm, ctx)
210e1051a39Sopenharmony_ci          && BN_is_one(r));
211e1051a39Sopenharmony_ci
212e1051a39Sopenharmony_ci    BN_clear(r);
213e1051a39Sopenharmony_ci    BN_clear(p1);
214e1051a39Sopenharmony_ci    BN_clear(q1);
215e1051a39Sopenharmony_ci    BN_clear(lcm);
216e1051a39Sopenharmony_ci    BN_clear(gcd);
217e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
218e1051a39Sopenharmony_ci    return ret;
219e1051a39Sopenharmony_ci}
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ci/*
222e1051a39Sopenharmony_ci * Check exponent is odd.
223e1051a39Sopenharmony_ci * For FIPS also check the bit length is in the range [17..256]
224e1051a39Sopenharmony_ci */
225e1051a39Sopenharmony_ciint ossl_rsa_check_public_exponent(const BIGNUM *e)
226e1051a39Sopenharmony_ci{
227e1051a39Sopenharmony_ci#ifdef FIPS_MODULE
228e1051a39Sopenharmony_ci    int bitlen;
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci    bitlen = BN_num_bits(e);
231e1051a39Sopenharmony_ci    return (BN_is_odd(e) && bitlen > 16 && bitlen < 257);
232e1051a39Sopenharmony_ci#else
233e1051a39Sopenharmony_ci    /* Allow small exponents larger than 1 for legacy purposes */
234e1051a39Sopenharmony_ci    return BN_is_odd(e) && BN_cmp(e, BN_value_one()) > 0;
235e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci/*
239e1051a39Sopenharmony_ci * SP800-56Br1 6.4.1.2.1 (Step 5i): |p - q| > 2^(nbits/2 - 100)
240e1051a39Sopenharmony_ci * i.e- numbits(p-q-1) > (nbits/2 -100)
241e1051a39Sopenharmony_ci */
242e1051a39Sopenharmony_ciint ossl_rsa_check_pminusq_diff(BIGNUM *diff, const BIGNUM *p, const BIGNUM *q,
243e1051a39Sopenharmony_ci                           int nbits)
244e1051a39Sopenharmony_ci{
245e1051a39Sopenharmony_ci    int bitlen = (nbits >> 1) - 100;
246e1051a39Sopenharmony_ci
247e1051a39Sopenharmony_ci    if (!BN_sub(diff, p, q))
248e1051a39Sopenharmony_ci        return -1;
249e1051a39Sopenharmony_ci    BN_set_negative(diff, 0);
250e1051a39Sopenharmony_ci
251e1051a39Sopenharmony_ci    if (BN_is_zero(diff))
252e1051a39Sopenharmony_ci        return 0;
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_ci    if (!BN_sub_word(diff, 1))
255e1051a39Sopenharmony_ci        return -1;
256e1051a39Sopenharmony_ci    return (BN_num_bits(diff) > bitlen);
257e1051a39Sopenharmony_ci}
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_ci/*
260e1051a39Sopenharmony_ci * return LCM(p-1, q-1)
261e1051a39Sopenharmony_ci *
262e1051a39Sopenharmony_ci * Caller should ensure that lcm, gcd, p1, q1, p1q1 are flagged with
263e1051a39Sopenharmony_ci * BN_FLG_CONSTTIME.
264e1051a39Sopenharmony_ci */
265e1051a39Sopenharmony_ciint ossl_rsa_get_lcm(BN_CTX *ctx, const BIGNUM *p, const BIGNUM *q,
266e1051a39Sopenharmony_ci                     BIGNUM *lcm, BIGNUM *gcd, BIGNUM *p1, BIGNUM *q1,
267e1051a39Sopenharmony_ci                     BIGNUM *p1q1)
268e1051a39Sopenharmony_ci{
269e1051a39Sopenharmony_ci    return BN_sub(p1, p, BN_value_one())    /* p-1 */
270e1051a39Sopenharmony_ci           && BN_sub(q1, q, BN_value_one()) /* q-1 */
271e1051a39Sopenharmony_ci           && BN_mul(p1q1, p1, q1, ctx)     /* (p-1)(q-1) */
272e1051a39Sopenharmony_ci           && BN_gcd(gcd, p1, q1, ctx)
273e1051a39Sopenharmony_ci           && BN_div(lcm, NULL, p1q1, gcd, ctx); /* LCM((p-1, q-1)) */
274e1051a39Sopenharmony_ci}
275e1051a39Sopenharmony_ci
276e1051a39Sopenharmony_ci/*
277e1051a39Sopenharmony_ci * SP800-56Br1 6.4.2.2 Partial Public Key Validation for RSA refers to
278e1051a39Sopenharmony_ci * SP800-89 5.3.3 (Explicit) Partial Public Key Validation for RSA
279e1051a39Sopenharmony_ci * caveat is that the modulus must be as specified in SP800-56Br1
280e1051a39Sopenharmony_ci */
281e1051a39Sopenharmony_ciint ossl_rsa_sp800_56b_check_public(const RSA *rsa)
282e1051a39Sopenharmony_ci{
283e1051a39Sopenharmony_ci    int ret = 0, status;
284e1051a39Sopenharmony_ci    int nbits;
285e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
286e1051a39Sopenharmony_ci    BIGNUM *gcd = NULL;
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ci    if (rsa->n == NULL || rsa->e == NULL)
289e1051a39Sopenharmony_ci        return 0;
290e1051a39Sopenharmony_ci
291e1051a39Sopenharmony_ci    nbits = BN_num_bits(rsa->n);
292e1051a39Sopenharmony_ci    if (nbits > OPENSSL_RSA_MAX_MODULUS_BITS) {
293e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_MODULUS_TOO_LARGE);
294e1051a39Sopenharmony_ci        return 0;
295e1051a39Sopenharmony_ci    }
296e1051a39Sopenharmony_ci
297e1051a39Sopenharmony_ci#ifdef FIPS_MODULE
298e1051a39Sopenharmony_ci    /*
299e1051a39Sopenharmony_ci     * (Step a): modulus must be 2048 or 3072 (caveat from SP800-56Br1)
300e1051a39Sopenharmony_ci     * NOTE: changed to allow keys >= 2048
301e1051a39Sopenharmony_ci     */
302e1051a39Sopenharmony_ci    if (!ossl_rsa_sp800_56b_validate_strength(nbits, -1)) {
303e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEY_LENGTH);
304e1051a39Sopenharmony_ci        return 0;
305e1051a39Sopenharmony_ci    }
306e1051a39Sopenharmony_ci#endif
307e1051a39Sopenharmony_ci    if (!BN_is_odd(rsa->n)) {
308e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
309e1051a39Sopenharmony_ci        return 0;
310e1051a39Sopenharmony_ci    }
311e1051a39Sopenharmony_ci    /* (Steps b-c): 2^16 < e < 2^256, n and e must be odd */
312e1051a39Sopenharmony_ci    if (!ossl_rsa_check_public_exponent(rsa->e)) {
313e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
314e1051a39Sopenharmony_ci        return 0;
315e1051a39Sopenharmony_ci    }
316e1051a39Sopenharmony_ci
317e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(rsa->libctx);
318e1051a39Sopenharmony_ci    gcd = BN_new();
319e1051a39Sopenharmony_ci    if (ctx == NULL || gcd == NULL)
320e1051a39Sopenharmony_ci        goto err;
321e1051a39Sopenharmony_ci
322e1051a39Sopenharmony_ci    /* (Steps d-f):
323e1051a39Sopenharmony_ci     * The modulus is composite, but not a power of a prime.
324e1051a39Sopenharmony_ci     * The modulus has no factors smaller than 752.
325e1051a39Sopenharmony_ci     */
326e1051a39Sopenharmony_ci    if (!BN_gcd(gcd, rsa->n, ossl_bn_get0_small_factors(), ctx)
327e1051a39Sopenharmony_ci        || !BN_is_one(gcd)) {
328e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
329e1051a39Sopenharmony_ci        goto err;
330e1051a39Sopenharmony_ci    }
331e1051a39Sopenharmony_ci
332e1051a39Sopenharmony_ci    /* Highest number of MR rounds from FIPS 186-5 Section B.3 Table B.1 */
333e1051a39Sopenharmony_ci    ret = ossl_bn_miller_rabin_is_prime(rsa->n, 5, ctx, NULL, 1, &status);
334e1051a39Sopenharmony_ci#ifdef FIPS_MODULE
335e1051a39Sopenharmony_ci    if (ret != 1 || status != BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME) {
336e1051a39Sopenharmony_ci#else
337e1051a39Sopenharmony_ci    if (ret != 1 || (status != BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME
338e1051a39Sopenharmony_ci                     && (nbits >= RSA_MIN_MODULUS_BITS
339e1051a39Sopenharmony_ci                         || status != BN_PRIMETEST_COMPOSITE_WITH_FACTOR))) {
340e1051a39Sopenharmony_ci#endif
341e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MODULUS);
342e1051a39Sopenharmony_ci        ret = 0;
343e1051a39Sopenharmony_ci        goto err;
344e1051a39Sopenharmony_ci    }
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_ci    ret = 1;
347e1051a39Sopenharmony_cierr:
348e1051a39Sopenharmony_ci    BN_free(gcd);
349e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
350e1051a39Sopenharmony_ci    return ret;
351e1051a39Sopenharmony_ci}
352e1051a39Sopenharmony_ci
353e1051a39Sopenharmony_ci/*
354e1051a39Sopenharmony_ci * Perform validation of the RSA private key to check that 0 < D < N.
355e1051a39Sopenharmony_ci */
356e1051a39Sopenharmony_ciint ossl_rsa_sp800_56b_check_private(const RSA *rsa)
357e1051a39Sopenharmony_ci{
358e1051a39Sopenharmony_ci    if (rsa->d == NULL || rsa->n == NULL)
359e1051a39Sopenharmony_ci        return 0;
360e1051a39Sopenharmony_ci    return BN_cmp(rsa->d, BN_value_one()) >= 0 && BN_cmp(rsa->d, rsa->n) < 0;
361e1051a39Sopenharmony_ci}
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_ci/*
364e1051a39Sopenharmony_ci * RSA key pair validation.
365e1051a39Sopenharmony_ci *
366e1051a39Sopenharmony_ci * SP800-56Br1.
367e1051a39Sopenharmony_ci *    6.4.1.2 "RSAKPV1 Family: RSA Key - Pair Validation with a Fixed Exponent"
368e1051a39Sopenharmony_ci *    6.4.1.3 "RSAKPV2 Family: RSA Key - Pair Validation with a Random Exponent"
369e1051a39Sopenharmony_ci *
370e1051a39Sopenharmony_ci * It uses:
371e1051a39Sopenharmony_ci *     6.4.1.2.3 "rsakpv1 - crt"
372e1051a39Sopenharmony_ci *     6.4.1.3.3 "rsakpv2 - crt"
373e1051a39Sopenharmony_ci */
374e1051a39Sopenharmony_ciint ossl_rsa_sp800_56b_check_keypair(const RSA *rsa, const BIGNUM *efixed,
375e1051a39Sopenharmony_ci                                     int strength, int nbits)
376e1051a39Sopenharmony_ci{
377e1051a39Sopenharmony_ci    int ret = 0;
378e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
379e1051a39Sopenharmony_ci    BIGNUM *r = NULL;
380e1051a39Sopenharmony_ci
381e1051a39Sopenharmony_ci    if (rsa->p == NULL
382e1051a39Sopenharmony_ci            || rsa->q == NULL
383e1051a39Sopenharmony_ci            || rsa->e == NULL
384e1051a39Sopenharmony_ci            || rsa->d == NULL
385e1051a39Sopenharmony_ci            || rsa->n == NULL) {
386e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_REQUEST);
387e1051a39Sopenharmony_ci        return 0;
388e1051a39Sopenharmony_ci    }
389e1051a39Sopenharmony_ci    /* (Step 1): Check Ranges */
390e1051a39Sopenharmony_ci    if (!ossl_rsa_sp800_56b_validate_strength(nbits, strength))
391e1051a39Sopenharmony_ci        return 0;
392e1051a39Sopenharmony_ci
393e1051a39Sopenharmony_ci    /* If the exponent is known */
394e1051a39Sopenharmony_ci    if (efixed != NULL) {
395e1051a39Sopenharmony_ci        /* (2): Check fixed exponent matches public exponent. */
396e1051a39Sopenharmony_ci        if (BN_cmp(efixed, rsa->e) != 0) {
397e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_REQUEST);
398e1051a39Sopenharmony_ci            return 0;
399e1051a39Sopenharmony_ci        }
400e1051a39Sopenharmony_ci    }
401e1051a39Sopenharmony_ci    /* (Step 1.c): e is odd integer 65537 <= e < 2^256 */
402e1051a39Sopenharmony_ci    if (!ossl_rsa_check_public_exponent(rsa->e)) {
403e1051a39Sopenharmony_ci        /* exponent out of range */
404e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE);
405e1051a39Sopenharmony_ci        return 0;
406e1051a39Sopenharmony_ci    }
407e1051a39Sopenharmony_ci    /* (Step 3.b): check the modulus */
408e1051a39Sopenharmony_ci    if (nbits != BN_num_bits(rsa->n)) {
409e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR);
410e1051a39Sopenharmony_ci        return 0;
411e1051a39Sopenharmony_ci    }
412e1051a39Sopenharmony_ci
413e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(rsa->libctx);
414e1051a39Sopenharmony_ci    if (ctx == NULL)
415e1051a39Sopenharmony_ci        return 0;
416e1051a39Sopenharmony_ci
417e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
418e1051a39Sopenharmony_ci    r = BN_CTX_get(ctx);
419e1051a39Sopenharmony_ci    if (r == NULL || !BN_mul(r, rsa->p, rsa->q, ctx))
420e1051a39Sopenharmony_ci        goto err;
421e1051a39Sopenharmony_ci    /* (Step 4.c): Check n = pq */
422e1051a39Sopenharmony_ci    if (BN_cmp(rsa->n, r) != 0) {
423e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_REQUEST);
424e1051a39Sopenharmony_ci        goto err;
425e1051a39Sopenharmony_ci    }
426e1051a39Sopenharmony_ci
427e1051a39Sopenharmony_ci    /* (Step 5): check prime factors p & q */
428e1051a39Sopenharmony_ci    ret = ossl_rsa_check_prime_factor(rsa->p, rsa->e, nbits, ctx)
429e1051a39Sopenharmony_ci          && ossl_rsa_check_prime_factor(rsa->q, rsa->e, nbits, ctx)
430e1051a39Sopenharmony_ci          && (ossl_rsa_check_pminusq_diff(r, rsa->p, rsa->q, nbits) > 0)
431e1051a39Sopenharmony_ci          /* (Step 6): Check the private exponent d */
432e1051a39Sopenharmony_ci          && ossl_rsa_check_private_exponent(rsa, nbits, ctx)
433e1051a39Sopenharmony_ci          /* 6.4.1.2.3 (Step 7): Check the CRT components */
434e1051a39Sopenharmony_ci          && ossl_rsa_check_crt_components(rsa, ctx);
435e1051a39Sopenharmony_ci    if (ret != 1)
436e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR);
437e1051a39Sopenharmony_ci
438e1051a39Sopenharmony_cierr:
439e1051a39Sopenharmony_ci    BN_clear(r);
440e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
441e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
442e1051a39Sopenharmony_ci    return ret;
443e1051a39Sopenharmony_ci}
444