xref: /freebsd/crypto/openssl/providers/common/securitycheck.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery #include "internal/deprecated.h"
11*b077aed3SPierre Pronchery 
12*b077aed3SPierre Pronchery #include <openssl/rsa.h>
13*b077aed3SPierre Pronchery #include <openssl/dsa.h>
14*b077aed3SPierre Pronchery #include <openssl/dh.h>
15*b077aed3SPierre Pronchery #include <openssl/ec.h>
16*b077aed3SPierre Pronchery #include <openssl/evp.h>
17*b077aed3SPierre Pronchery #include <openssl/err.h>
18*b077aed3SPierre Pronchery #include <openssl/proverr.h>
19*b077aed3SPierre Pronchery #include <openssl/core_names.h>
20*b077aed3SPierre Pronchery #include <openssl/obj_mac.h>
21*b077aed3SPierre Pronchery #include "prov/securitycheck.h"
22*b077aed3SPierre Pronchery 
23*b077aed3SPierre Pronchery /*
24*b077aed3SPierre Pronchery  * FIPS requires a minimum security strength of 112 bits (for encryption or
25*b077aed3SPierre Pronchery  * signing), and for legacy purposes 80 bits (for decryption or verifying).
26*b077aed3SPierre Pronchery  * Set protect = 1 for encryption or signing operations, or 0 otherwise. See
27*b077aed3SPierre Pronchery  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf.
28*b077aed3SPierre Pronchery  */
29*b077aed3SPierre Pronchery int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation)
30*b077aed3SPierre Pronchery {
31*b077aed3SPierre Pronchery     int protect = 0;
32*b077aed3SPierre Pronchery 
33*b077aed3SPierre Pronchery     switch (operation) {
34*b077aed3SPierre Pronchery         case EVP_PKEY_OP_SIGN:
35*b077aed3SPierre Pronchery             protect = 1;
36*b077aed3SPierre Pronchery             /* fallthrough */
37*b077aed3SPierre Pronchery         case EVP_PKEY_OP_VERIFY:
38*b077aed3SPierre Pronchery             break;
39*b077aed3SPierre Pronchery         case EVP_PKEY_OP_ENCAPSULATE:
40*b077aed3SPierre Pronchery         case EVP_PKEY_OP_ENCRYPT:
41*b077aed3SPierre Pronchery             protect = 1;
42*b077aed3SPierre Pronchery             /* fallthrough */
43*b077aed3SPierre Pronchery         case EVP_PKEY_OP_VERIFYRECOVER:
44*b077aed3SPierre Pronchery         case EVP_PKEY_OP_DECAPSULATE:
45*b077aed3SPierre Pronchery         case EVP_PKEY_OP_DECRYPT:
46*b077aed3SPierre Pronchery             if (RSA_test_flags(rsa,
47*b077aed3SPierre Pronchery                                RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSASSAPSS) {
48*b077aed3SPierre Pronchery                 ERR_raise_data(ERR_LIB_PROV,
49*b077aed3SPierre Pronchery                                PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE,
50*b077aed3SPierre Pronchery                                "operation: %d", operation);
51*b077aed3SPierre Pronchery                 return 0;
52*b077aed3SPierre Pronchery             }
53*b077aed3SPierre Pronchery             break;
54*b077aed3SPierre Pronchery         default:
55*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
56*b077aed3SPierre Pronchery                            "invalid operation: %d", operation);
57*b077aed3SPierre Pronchery             return 0;
58*b077aed3SPierre Pronchery     }
59*b077aed3SPierre Pronchery 
60*b077aed3SPierre Pronchery #if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
61*b077aed3SPierre Pronchery     if (ossl_securitycheck_enabled(ctx)) {
62*b077aed3SPierre Pronchery         int sz = RSA_bits(rsa);
63*b077aed3SPierre Pronchery 
64*b077aed3SPierre Pronchery         if (protect ? (sz < 2048) : (sz < 1024)) {
65*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH,
66*b077aed3SPierre Pronchery                            "operation: %d", operation);
67*b077aed3SPierre Pronchery             return 0;
68*b077aed3SPierre Pronchery         }
69*b077aed3SPierre Pronchery     }
70*b077aed3SPierre Pronchery #else
71*b077aed3SPierre Pronchery     /* make protect used */
72*b077aed3SPierre Pronchery     (void)protect;
73*b077aed3SPierre Pronchery #endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
74*b077aed3SPierre Pronchery     return 1;
75*b077aed3SPierre Pronchery }
76*b077aed3SPierre Pronchery 
77*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_EC
78*b077aed3SPierre Pronchery /*
79*b077aed3SPierre Pronchery  * In FIPS mode:
80*b077aed3SPierre Pronchery  * protect should be 1 for any operations that need 112 bits of security
81*b077aed3SPierre Pronchery  * strength (such as signing, and key exchange), or 0 for operations that allow
82*b077aed3SPierre Pronchery  * a lower security strength (such as verify).
83*b077aed3SPierre Pronchery  *
84*b077aed3SPierre Pronchery  * For ECDH key agreement refer to SP800-56A
85*b077aed3SPierre Pronchery  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
86*b077aed3SPierre Pronchery  * "Appendix D"
87*b077aed3SPierre Pronchery  *
88*b077aed3SPierre Pronchery  * For ECDSA signatures refer to
89*b077aed3SPierre Pronchery  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
90*b077aed3SPierre Pronchery  * "Table 2"
91*b077aed3SPierre Pronchery  */
92*b077aed3SPierre Pronchery int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect)
93*b077aed3SPierre Pronchery {
94*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
95*b077aed3SPierre Pronchery     if (ossl_securitycheck_enabled(ctx)) {
96*b077aed3SPierre Pronchery         int nid, strength;
97*b077aed3SPierre Pronchery         const char *curve_name;
98*b077aed3SPierre Pronchery         const EC_GROUP *group = EC_KEY_get0_group(ec);
99*b077aed3SPierre Pronchery 
100*b077aed3SPierre Pronchery         if (group == NULL) {
101*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE, "No group");
102*b077aed3SPierre Pronchery             return 0;
103*b077aed3SPierre Pronchery         }
104*b077aed3SPierre Pronchery         nid = EC_GROUP_get_curve_name(group);
105*b077aed3SPierre Pronchery         if (nid == NID_undef) {
106*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE,
107*b077aed3SPierre Pronchery                            "Explicit curves are not allowed in fips mode");
108*b077aed3SPierre Pronchery             return 0;
109*b077aed3SPierre Pronchery         }
110*b077aed3SPierre Pronchery 
111*b077aed3SPierre Pronchery         curve_name = EC_curve_nid2nist(nid);
112*b077aed3SPierre Pronchery         if (curve_name == NULL) {
113*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE,
114*b077aed3SPierre Pronchery                            "Curve %s is not approved in FIPS mode", curve_name);
115*b077aed3SPierre Pronchery             return 0;
116*b077aed3SPierre Pronchery         }
117*b077aed3SPierre Pronchery 
118*b077aed3SPierre Pronchery         /*
119*b077aed3SPierre Pronchery          * For EC the security strength is the (order_bits / 2)
120*b077aed3SPierre Pronchery          * e.g. P-224 is 112 bits.
121*b077aed3SPierre Pronchery          */
122*b077aed3SPierre Pronchery         strength = EC_GROUP_order_bits(group) / 2;
123*b077aed3SPierre Pronchery         /* The min security strength allowed for legacy verification is 80 bits */
124*b077aed3SPierre Pronchery         if (strength < 80) {
125*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE);
126*b077aed3SPierre Pronchery             return 0;
127*b077aed3SPierre Pronchery         }
128*b077aed3SPierre Pronchery 
129*b077aed3SPierre Pronchery         /*
130*b077aed3SPierre Pronchery          * For signing or key agreement only allow curves with at least 112 bits of
131*b077aed3SPierre Pronchery          * security strength
132*b077aed3SPierre Pronchery          */
133*b077aed3SPierre Pronchery         if (protect && strength < 112) {
134*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE,
135*b077aed3SPierre Pronchery                            "Curve %s cannot be used for signing", curve_name);
136*b077aed3SPierre Pronchery             return 0;
137*b077aed3SPierre Pronchery         }
138*b077aed3SPierre Pronchery     }
139*b077aed3SPierre Pronchery # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
140*b077aed3SPierre Pronchery     return 1;
141*b077aed3SPierre Pronchery }
142*b077aed3SPierre Pronchery #endif /* OPENSSL_NO_EC */
143*b077aed3SPierre Pronchery 
144*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_DSA
145*b077aed3SPierre Pronchery /*
146*b077aed3SPierre Pronchery  * Check for valid key sizes if fips mode. Refer to
147*b077aed3SPierre Pronchery  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
148*b077aed3SPierre Pronchery  * "Table 2"
149*b077aed3SPierre Pronchery  */
150*b077aed3SPierre Pronchery int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign)
151*b077aed3SPierre Pronchery {
152*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
153*b077aed3SPierre Pronchery     if (ossl_securitycheck_enabled(ctx)) {
154*b077aed3SPierre Pronchery         size_t L, N;
155*b077aed3SPierre Pronchery         const BIGNUM *p, *q;
156*b077aed3SPierre Pronchery 
157*b077aed3SPierre Pronchery         if (dsa == NULL)
158*b077aed3SPierre Pronchery             return 0;
159*b077aed3SPierre Pronchery 
160*b077aed3SPierre Pronchery         p = DSA_get0_p(dsa);
161*b077aed3SPierre Pronchery         q = DSA_get0_q(dsa);
162*b077aed3SPierre Pronchery         if (p == NULL || q == NULL)
163*b077aed3SPierre Pronchery             return 0;
164*b077aed3SPierre Pronchery 
165*b077aed3SPierre Pronchery         L = BN_num_bits(p);
166*b077aed3SPierre Pronchery         N = BN_num_bits(q);
167*b077aed3SPierre Pronchery 
168*b077aed3SPierre Pronchery         /*
169*b077aed3SPierre Pronchery          * For Digital signature verification DSA keys with < 112 bits of
170*b077aed3SPierre Pronchery          * security strength (i.e L < 2048 bits), are still allowed for legacy
171*b077aed3SPierre Pronchery          * use. The bounds given in SP800 131Ar2 - Table 2 are
172*b077aed3SPierre Pronchery          * (512 <= L < 2048 and 160 <= N < 224)
173*b077aed3SPierre Pronchery          */
174*b077aed3SPierre Pronchery         if (!sign && L < 2048)
175*b077aed3SPierre Pronchery             return (L >= 512 && N >= 160 && N < 224);
176*b077aed3SPierre Pronchery 
177*b077aed3SPierre Pronchery          /* Valid sizes for both sign and verify */
178*b077aed3SPierre Pronchery         if (L == 2048 && (N == 224 || N == 256))
179*b077aed3SPierre Pronchery             return 1;
180*b077aed3SPierre Pronchery         return (L == 3072 && N == 256);
181*b077aed3SPierre Pronchery     }
182*b077aed3SPierre Pronchery # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
183*b077aed3SPierre Pronchery     return 1;
184*b077aed3SPierre Pronchery }
185*b077aed3SPierre Pronchery #endif /* OPENSSL_NO_DSA */
186*b077aed3SPierre Pronchery 
187*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_DH
188*b077aed3SPierre Pronchery /*
189*b077aed3SPierre Pronchery  * For DH key agreement refer to SP800-56A
190*b077aed3SPierre Pronchery  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
191*b077aed3SPierre Pronchery  * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and
192*b077aed3SPierre Pronchery  * "Appendix D" FFC Safe-prime Groups
193*b077aed3SPierre Pronchery  */
194*b077aed3SPierre Pronchery int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh)
195*b077aed3SPierre Pronchery {
196*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
197*b077aed3SPierre Pronchery     if (ossl_securitycheck_enabled(ctx)) {
198*b077aed3SPierre Pronchery         size_t L, N;
199*b077aed3SPierre Pronchery         const BIGNUM *p, *q;
200*b077aed3SPierre Pronchery 
201*b077aed3SPierre Pronchery         if (dh == NULL)
202*b077aed3SPierre Pronchery             return 0;
203*b077aed3SPierre Pronchery 
204*b077aed3SPierre Pronchery         p = DH_get0_p(dh);
205*b077aed3SPierre Pronchery         q = DH_get0_q(dh);
206*b077aed3SPierre Pronchery         if (p == NULL || q == NULL)
207*b077aed3SPierre Pronchery             return 0;
208*b077aed3SPierre Pronchery 
209*b077aed3SPierre Pronchery         L = BN_num_bits(p);
210*b077aed3SPierre Pronchery         if (L < 2048)
211*b077aed3SPierre Pronchery             return 0;
212*b077aed3SPierre Pronchery 
213*b077aed3SPierre Pronchery         /* If it is a safe prime group then it is ok */
214*b077aed3SPierre Pronchery         if (DH_get_nid(dh))
215*b077aed3SPierre Pronchery             return 1;
216*b077aed3SPierre Pronchery 
217*b077aed3SPierre Pronchery         /* If not then it must be FFC, which only allows certain sizes. */
218*b077aed3SPierre Pronchery         N = BN_num_bits(q);
219*b077aed3SPierre Pronchery 
220*b077aed3SPierre Pronchery         return (L == 2048 && (N == 224 || N == 256));
221*b077aed3SPierre Pronchery     }
222*b077aed3SPierre Pronchery # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
223*b077aed3SPierre Pronchery     return 1;
224*b077aed3SPierre Pronchery }
225*b077aed3SPierre Pronchery #endif /* OPENSSL_NO_DH */
226*b077aed3SPierre Pronchery 
227*b077aed3SPierre Pronchery int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
228*b077aed3SPierre Pronchery                                            int sha1_allowed)
229*b077aed3SPierre Pronchery {
230*b077aed3SPierre Pronchery     int mdnid = ossl_digest_get_approved_nid(md);
231*b077aed3SPierre Pronchery 
232*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
233*b077aed3SPierre Pronchery     if (ossl_securitycheck_enabled(ctx)) {
234*b077aed3SPierre Pronchery         if (mdnid == NID_undef || (mdnid == NID_sha1 && !sha1_allowed))
235*b077aed3SPierre Pronchery             mdnid = -1; /* disallowed by security checks */
236*b077aed3SPierre Pronchery     }
237*b077aed3SPierre Pronchery # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
238*b077aed3SPierre Pronchery     return mdnid;
239*b077aed3SPierre Pronchery }
240*b077aed3SPierre Pronchery 
241*b077aed3SPierre Pronchery int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md)
242*b077aed3SPierre Pronchery {
243*b077aed3SPierre Pronchery # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
244*b077aed3SPierre Pronchery     if (ossl_securitycheck_enabled(ctx))
245*b077aed3SPierre Pronchery         return ossl_digest_get_approved_nid(md) != NID_undef;
246*b077aed3SPierre Pronchery # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
247*b077aed3SPierre Pronchery     return 1;
248*b077aed3SPierre Pronchery }
249