File: securitycheck.c

package info (click to toggle)
openssl 3.6.0-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 148,104 kB
  • sloc: ansic: 612,658; perl: 248,939; asm: 6,332; sh: 1,755; pascal: 997; python: 648; makefile: 551; lisp: 35; ruby: 16; cpp: 10; sed: 6
file content (221 lines) | stat: -rw-r--r-- 6,133 bytes parent folder | download | duplicates (6)
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 */