1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
/*
* Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* 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 "internal/deprecated.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/proverr.h>
#include <openssl/core_names.h>
#include <openssl/obj_mac.h>
#include "prov/securitycheck.h"
#define OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS 112
int ossl_rsa_key_op_get_protect(const RSA *rsa, int operation, int *outprotect)
{
int protect = 0;
switch (operation) {
case EVP_PKEY_OP_SIGN:
case EVP_PKEY_OP_SIGNMSG:
protect = 1;
/* fallthrough */
case EVP_PKEY_OP_VERIFY:
case EVP_PKEY_OP_VERIFYMSG:
break;
case EVP_PKEY_OP_ENCAPSULATE:
case EVP_PKEY_OP_ENCRYPT:
protect = 1;
/* fallthrough */
case EVP_PKEY_OP_VERIFYRECOVER:
case EVP_PKEY_OP_DECAPSULATE:
case EVP_PKEY_OP_DECRYPT:
if (RSA_test_flags(rsa,
RSA_FLAG_TYPE_MASK) == RSA_FLAG_TYPE_RSASSAPSS) {
ERR_raise_data(ERR_LIB_PROV,
PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE,
"operation: %d", operation);
return 0;
}
break;
default:
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
"invalid operation: %d", operation);
return 0;
}
*outprotect = protect;
return 1;
}
/*
* FIPS requires a minimum security strength of 112 bits (for encryption or
* signing), and for legacy purposes 80 bits (for decryption or verifying).
* Set protect = 1 for encryption or signing operations, or 0 otherwise. See
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf.
*/
int ossl_rsa_check_key_size(const RSA *rsa, int protect)
{
int sz = RSA_bits(rsa);
if (protect ? (sz < 2048) : (sz < 1024))
return 0;
return 1;
}
/*
* FIPS requires a minimum security strength of 112 bits for key-derivation key.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf.
*/
int ossl_kdf_check_key_size(size_t keylen)
{
return (keylen * 8) >= OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS;
}
int ossl_mac_check_key_size(size_t keylen)
{
return ossl_kdf_check_key_size(keylen);
}
#ifndef OPENSSL_NO_EC
int ossl_ec_check_curve_allowed(const EC_GROUP *group)
{
const char *curve_name;
int nid = EC_GROUP_get_curve_name(group);
/* Explicit curves are not FIPS approved */
if (nid == NID_undef)
return 0;
/* Only NIST curves are FIPS approved */
curve_name = EC_curve_nid2nist(nid);
if (curve_name == NULL)
return 0;
return 1;
}
/*
* In FIPS mode:
* protect should be 1 for any operations that need 112 bits of security
* strength (such as signing, and key exchange), or 0 for operations that allow
* a lower security strength (such as verify).
*
* For ECDH key agreement refer to SP800-56A
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
* "Appendix D"
*
* For ECDSA signatures refer to
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
* "Table 2"
*/
int ossl_ec_check_security_strength(const EC_GROUP *group, int protect)
{
/*
* For EC the security strength is the (order_bits / 2)
* e.g. P-224 is 112 bits.
*/
int strength = EC_GROUP_order_bits(group) / 2;
/* The min security strength allowed for legacy verification is 80 bits */
if (strength < 80)
return 0;
/*
* For signing or key agreement only allow curves with at least 112 bits of
* security strength
*/
if (protect && strength < OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS)
return 0;
return 1;
}
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_DSA
/*
* Check for valid key sizes if fips mode. Refer to
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
* "Table 2"
*/
int ossl_dsa_check_key(const DSA *dsa, int sign)
{
size_t L, N;
const BIGNUM *p, *q;
if (dsa == NULL)
return 0;
p = DSA_get0_p(dsa);
q = DSA_get0_q(dsa);
if (p == NULL || q == NULL)
return 0;
L = BN_num_bits(p);
N = BN_num_bits(q);
/*
* For Digital signature verification DSA keys with < 112 bits of
* security strength, are still allowed for legacy
* use. The bounds given in SP 800-131Ar2 - Table 2 are
* (512 <= L < 2048 or 160 <= N < 224).
*
* We are a little stricter and insist that both minimums are met.
* For example a L = 256, N = 160 key *would* be allowed by SP 800-131Ar2
* but we don't.
*/
if (!sign) {
if (L < 512 || N < 160)
return 0;
if (L < 2048 || N < 224)
return 1;
}
/* Valid sizes for both sign and verify */
if (L == 2048 && (N == 224 || N == 256)) /* 112 bits */
return 1;
return (L == 3072 && N == 256); /* 128 bits */
}
#endif /* OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_DH
/*
* For DH key agreement refer to SP800-56A
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf
* "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and
* "Appendix D" FFC Safe-prime Groups
*/
int ossl_dh_check_key(const DH *dh)
{
size_t L, N;
const BIGNUM *p, *q;
if (dh == NULL)
return 0;
p = DH_get0_p(dh);
q = DH_get0_q(dh);
if (p == NULL || q == NULL)
return 0;
L = BN_num_bits(p);
if (L < 2048)
return 0;
/* If it is a safe prime group then it is ok */
if (DH_get_nid(dh))
return 1;
/* If not then it must be FFC, which only allows certain sizes. */
N = BN_num_bits(q);
return (L == 2048 && (N == 224 || N == 256));
}
#endif /* OPENSSL_NO_DH */
|