xref: /freebsd/crypto/openssl/doc/designs/fips_indicator.md (revision dece5b05f577fc4c6b89af7ad48dfbdf7cc4945c)
1OpenSSL FIPS Indicators
2=======================
3
4The following document refers to behaviour required by the OpenSSL FIPS provider,
5the changes should not affect the default provider.
6
7Every algorithm implementation advertised with `fips=yes` by the FIPS provider
8must advertise `OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR` as a gettable context
9parameter and its getter must return 1 for an approved operation.  Missing
10indicator support is not an implicit indication of approval.  Implementations
11advertised with `fips=no` return 0 when they expose the indicator.  The default
12provider may omit the parameter; if it exposes the parameter, it returns 0.
13
14References
15----------
16
17- [1] FIPS 140-3 Standards: <https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-standards>
18- [2] Approved Security Functions: <https://csrc.nist.gov/projects/cryptographic-module-validation-program/sp-800-140-series-supplemental-information/sp800-140c>
19- [3] Approved SSP generation and Establishment methods: <https://csrc.nist.gov/projects/cryptographic-module-validation-program/sp-800-140-series-supplemental-information/sp800-140d>
20- [4] Key transitions: <https://csrc.nist.gov/pubs/sp/800/131/a/r2/final>
21- [5] FIPS 140-3 Implementation Guidance: <https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips 140-3/FIPS 140-3 IG.pdf>
22
23Requirements
24------------
25
26The following information was extracted from the FIPS 140-3 IG [5] “2.4.C Approved Security Service Indicator”
27
28- A module must have an approved mode of operation that requires at least one service to use an approved security function (defined by [2] and [3]).
29- A FIPS 140-3 compliant module requires a built-in service indicator capable of indicating the use of approved security services
30- If a module only supports approved services in an approved manner an implicit indicator can be used (e.g. successful completion of a service is an indicator).
31- An approved algorithm is not considered to be an approved implementation if it does not have a CAVP certificate or does not include its required self-tests. (i.e. My interpretation of this is that if the CAVP certificate lists an algorithm with only a subset of key sizes, digests, and/or ciphers compared to the implementation, the differences ARE NOT APPROVED. In many places we have no restrictions on the digest or cipher selected).
32- Documentation is required to demonstrate how to use indicators for each approved cryptographic algorithm.
33- Testing is required to execute all services and verify that the indicator provides an unambiguous indication of whether the service utilizes an approved cryptographic algorithm, security function or process in an approved manner or not.
34- The Security Policy may require updates related to indicators. AWS/google have added a table in their security policy called ‘Non-Approved Algorithms not allowed in the approved mode of operation’. An example is RSA with a keysize of < 2048 bits (which has been enforced by [4]).
35
36Since any new FIPS restrictions added could possibly break existing applications
37the following additional OpenSSL requirements are also needed:
38
39- The FIPS restrictions should be able to be disabled using Configuration file options (This results in unapproved mode and requires an indicator).
40- A mechanism for logging the details of any unapproved mode operations that have been triggered (e.g. DSA Signing)
41- The FIPS restrictions should be able to be enabled/disabled per algorithm context.
42- If the per algorithm context value is not set, then the  Configuration file option is used.
43
44Solution
45--------
46
47In OpenSSL most of the existing code in the FIPS provider is using
48implicit indicators i.e. An error occurs if existing FIPS rules are violated.
49
50The following rules will apply to any code that currently is not FIPS approved,
51but needs to be.
52
53- The fipsinstall application will have a configurable item added for each algorithm that requires a change. These options will be passed to the FIPS provider in a manner similar to existing code.
54
55- A user defined callback similar to OSSL_SELF_TEST will be added. This callback will be triggered whenever an approved mode test fails.
56
57It may be set up by the user using
58
59```c
60typedef int (OSSL_INDICATOR_CALLBACK)(const char *type,
61                                      const char *desc,
62                                      const OSSL_PARAM params[]);
63
64void OSSL_INDICATOR_set_callback(OSSL_LIB_CTX *libctx,
65                                 OSSL_INDICATOR_CALLBACK *cb);
66```
67
68The callback can be changed at any time.
69
70- A getter is also supplied (which is also used internally)
71
72```c
73void OSSL_INDICATOR_get_callback(OSSL_LIB_CTX *libctx,
74                                 OSSL_INDICATOR_CALLBACK **cb);
75```
76
77An application's indicator OSSL_INDICATOR_CALLBACK can be used to log that an
78indicator was triggered. The callback should normally return non zero.
79Returning 0 allows the algorithm to fail, in the same way that a strict check
80would fail.
81
82- To control an algorithm context's checks via code requires a setter for each individual check e.g OSSL_PKEY_PARAM_FIPS_KEY_CHECK.
83
84```c
85    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FIPS_KEY_CHECK);
86    if (p != NULL
87        && !OSSL_PARAM_get_int(p, &ctx->key_check))
88        return 0;
89```
90
91The setter is initially -1 (unknown) and can be set to 0 or 1 via a set_ctx call.
92If the setter is needed it must be set BEFORE the FIPS related check is done.
93
94If the FIPS related approved mode check fails and either the ctx setter is zero
95OR the related FIPS configuration option is zero then the callback is triggered.
96If neither the setter of config option are zero then the algorithm should fail.
97If the callback is triggered a flag is set in the algorithm ctx that indicates
98that this algorithm is unapproved. Once the context is unapproved it will
99remain in this state.
100
101- To access the indicator via code requires a getter
102
103```c
104    p = OSSL_PARAM_locate(params, OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR);
105    if (p != NULL && !OSSL_PARAM_set_int(p, ctx->approved))
106        return 0;
107```
108
109This initially has a value of 1, and may be set to 0 if the algorithm is
110unapproved. The getter allows you to access the indicator value after the
111operation has completed (e.g. Final or Derive related functions)
112
113An implementation that is always approved still supplies the gettable
114parameter and getter.  Such a getter returns 1 without requiring an approval
115flag in its context.  This makes approval explicit instead of relying on the
116absence of an indicator.
117
118- Example Algorithm Check
119
120```c
121void alg_init(ALG_CTX *ctx)
122{
123    ctx->strict_checks = -1;
124    ctx->approved = 1;
125}
126
127void alg_set_params(ALG_CTX *ctx, OSSL_PARAMS params[])
128{
129    p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_STRICT_CHECKS);
130    if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->strict_checks))
131        return 0;
132}
133
134int alg_check_approved(ALG_CTX *ctx)
135{
136    int approved;
137
138    approved = some_fips_test_passes(ctx->libctx); // Check FIPS restriction for alg
139    if (!approved) {
140        ctx->approved = 0;
141        if (ctx->strict_checks == 0
142                || fips_config_get(ctx->libctx, op) == 0) {
143            if (!indicator_cb(ctx->libctx, "ALG NAME", "ALG DESC"))
144                return 0;
145        }
146    }
147    return 1;
148}
149```
150
151- Existing security check changes
152
153OpenSSL already uses FIPS configuration options to perform security_checks, but
154the existing code needs to change to work with indicators.
155
156e.g. existing code
157
158```c
159    if (ossl_securitycheck_enabled(ctx)) {
160       pass = do_some_alg_test(ctx);
161       if (!pass)
162        return 0; /* Produce an error */
163    }
164```
165
166In updated code for indicators the test always runs.. i.e.
167
168```c
169    pass = do_some_alg_test(ctx);
170    // Do code similar to alg_check_approved() above
171    // which will conditionally decide whether to return an error
172    // or trigger the indicator callback.
173```
174
175Issues with per algorithm ctx setters
176------------------------------------------------
177
178Normally a user would set params (such as OSSL_PKEY_PARAM_FIPS_KEY_CHECK) using
179set_ctx_params(), but some algorithms currently do checks in their init operation.
180These init functions normally pass an OSSL_PARAM[] argument, but this still
181requires the user to set the ctx params in their init.
182
183e.g.
184
185```c
186int strict = 0;
187params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FIPS_KEY_CHECK, strict);
188EVP_DigestSignInit_ex(ctx, &pctx, name, libctx, NULL, pkey, params);
189// using EVP_PKEY_CTX_set_params() here would be too late
190```
191
192Delaying the check to after the init would be possible, but it would be a change
193in existing behaviour. For example the keysize checks are done in the init since
194this is when the key is setup.
195
196Notes
197-----
198
199There was discussion related to also having a global config setting that could
200turn off FIPS mode. This will not be added at this stage.
201
202MACROS
203------
204
205A generic object is used internally to embed the variables required for
206indicators into each algorithm ctx. The object contains the ctx settables and
207the approved flag.
208
209```c
210typedef struct ossl_fips_ind_st {
211    unsigned char approved;
212    signed char settable[OSSL_FIPS_IND_SETTABLE_MAX];
213} OSSL_FIPS_IND;
214```
215
216Since there are a lot of algorithms where indicators are needed it was decided
217to use MACROS to simplify the process.
218The following macros are only defined for the FIPS provider.
219
220- OSSL_FIPS_IND_DECLARE
221
222OSSL_FIPS_IND should be placed into the algorithm objects struct that is
223returned by a new()
224
225- OSSL_FIPS_IND_COPY(dst, src)
226
227This is used to copy the OSSL_FIPS_IND when calling a dup(). If the dup() uses
228*dst = *src then it is not required.
229
230- OSSL_FIPS_IND_INIT(ctx)
231
232Initializes the OSSL_FIPS_IND object. It should be called in the new().
233
234- OSSL_FIPS_IND_ON_UNAPPROVED(ctx, id, libctx, algname, opname, configopt_fn)
235
236This triggers the callback, id is the settable index and must also be used
237by OSSL_FIPS_IND_SET_CTX_PARAM(), algname and opname are strings that are passed
238to the indicator callback, configopt_fn is the FIPS configuration option.
239Where this is triggered depends on the algorithm. In most cases this can be done
240in the set_ctx().
241
242- OSSL_FIPS_IND_SETTABLE_CTX_PARAM(name)
243
244This must be put into the algorithms settable ctx_params table.
245The name is the settable 'key' name such as OSSL_PKEY_PARAM_FIPS_KEY_CHECK.
246There should be a matching name used by OSSL_FIPS_IND_SET_CTX_PARAM().
247There may be multiple of these.
248
249- OSSL_FIPS_IND_SET_CTX_PARAM(ctx, id, params, name)
250
251This should be put at the top of the algorithms set_ctx_params().
252There may be multiple of these. The name should match an
253OSSL_FIPS_IND_SETTABLE_CTX_PARAM() entry.
254The id should match an OSSL_FIPS_IND_ON_UNAPPROVED() entry.
255
256- OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
257
258This must be placed in the algorithms gettable_ctx_params table
259
260- OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params)
261
262This must be placed in the algorithms get_ctx_params(),
263
264Some existing algorithms will require set_ctx_params()/settable_ctx_params()
265and/or get_ctx_params()/gettable_ctx_params() to be added if required.
266
267New Changes Required
268--------------------
269
270The following changes are required for FIPS 140-3 and will require indicators.
271On a cases by case basis we must decide what to do when unapproved mode is
272detected.
273The mechanism using FIPS configuration options and the indicator callback should
274be used for most of these unapproved cases (rather than always returning an error).
275
276### key size >= 112 bits
277
278There are a few places where we do not enforce key size that need to be addressed.
279
280- HMAC  Which applies to all algorithms that use HMAC also (e.g. HKDF, SSKDF, KBKDF)
281- CMAC
282- KMAC
283
284### Algorithm Transitions
285
286- DES_EDE3_ECB.  Disallowed for encryption, allowed for legacy decryption
287- DSA.  Keygen and Signing are no longer approved, verify is still allowed.
288- ECDSA B & K curves are deprecated, but still approved according to (IG C.K Resolution 4).\
289  If we chose not to remove them , then we need to check that OSSL_PKEY_PARAM_USE_COFACTOR_ECDH is set for key agreement if the cofactor is not 1.
290- ED25519 and ED448 are now approved.
291- X25519 and X448 are not approved currently. keygen and keyexchange would also need an indicator if we allow them?
292- RSA encryption(for key agreement/key transport) using PKCSV15 is no longer allowed. (Note that this breaks TLS 1.2 using RSA for KeyAgreement),
293  Padding mode updates required. Check RSA KEM also.
294- RSA signing using PKCS1 is still allowed (i.e. signature uses shaXXXWithRSAEncryption)
295- RSA signing using X931 is no longer allowed. (Still allowed for verification). Check if PSS saltlen needs a indicator (Note FIPS 186-4 Section 5.5 bullet(e). Padding mode updates required in rsa_check_padding(). Check if sha1 is allowed?
296- RSA (From SP800-131Ar2) RSA >= 2048 is approved for keygen, signatures and key transport. Verification allows 1024 also. Note also that according to the (IG section C.F) that fips 186-2 verification is also allowed (So this may need either testing OR an indicator, it also mentions the modulus size must be a multiple of 256). Check that rsa_keygen_pairwise_test() and RSA self tests are all compliant with the above RSA restrictions.
297- TLS1_PRF  If we are only trying to support TLS1.2 here then we should remove the tls1.0/1.1 code from the FIPS MODULE.
298- ECDSA Verify using prehashed message is not allowed.
299
300### Digest Checks
301
302Any algorithms that use a digest need to make sure that the CAVP certificate lists all supported FIPS digests otherwise an indicator is required.
303This applies to the following algorithms:
304
305- TLS_1_3_KDF (Only SHA256 and SHA384 Are allowed due to RFC 8446  Appendix B.4)
306- TLS1_PRF (Only SHA256,SHA384,SHA512 are allowed)
307- X963KDF (SHA1 is not allowed)
308- X942KDF
309- PBKDF2
310- HKDF
311- KBKDF
312- SSKDF
313- SSHKDF
314- HMAC
315- KMAC
316- Any signature algorithms such as RSA, DSA, ECDSA.
317
318The FIPS 140-3 IG Section C.B & C.C have notes related to Vendor affirmation.
319
320Note many of these (such as KDF's will not support SHAKE).
321See <https://gitlab.com/redhat/centos-stream/rpms/openssl/-/blob/c9s/0078-KDF-Add-FIPS-indicators.patch?ref_type=heads>
322ECDSA and RSA-PSS Signatures allow use of SHAKE.
323
324KECCAK-KMAC-128 and KECCAK-KMAC-256 should not be allowed for anything other than KMAC.
325Do we need to check which algorithms allow SHA1 also?
326
327Test that Deterministic ECDSA does not allow SHAKE (IG C.K Additional Comments 6)
328
329### Cipher Checks
330
331- CMAC
332- KBKDF CMAC
333- GMAC
334
335We should only allow AES. We currently just check the mode.
336
337### Configurable options
338
339- PBKDF2 'lower_bound_checks' needs to be part of the indicator check
340
341Other Changes
342-------------
343
344- AES-GCM Security Policy must list AES GCM IV generation scenarios
345- TEST_RAND is not approved.
346- SSKDF  The security policy needs to be specific about what it supports i.e. hash, kmac 128/256, hmac-hash. There are also currently no limitations on the digest for hash and hmac
347- KBKDF  Security policy should list KMAC-128, KMAC-256 otherwise it should be removed.
348- KMAC may need a lower bound check on the output size (SP800-185 Section 8.4.2)
349- HMAC (FIPS 140-3 IG Section C.D has notes about the output length when using a Truncated HMAC)
350