xref: /freebsd/crypto/openssl/providers/fips/self_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1 /*
2  * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <string.h>
11 #include <openssl/evp.h>
12 #include <openssl/params.h>
13 #include <openssl/crypto.h>
14 #include "internal/cryptlib.h"
15 #include <openssl/fipskey.h>
16 #include <openssl/err.h>
17 #include <openssl/proverr.h>
18 #include <openssl/rand.h>
19 #include "internal/e_os.h"
20 #include "internal/fips.h"
21 #include "internal/tsan_assist.h"
22 #include "prov/providercommon.h"
23 #include "crypto/rand.h"
24 
25 /*
26  * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
27  * module because all such initialisation should be associated with an
28  * individual OSSL_LIB_CTX. That doesn't work with the self test though because
29  * it should be run once regardless of the number of OSSL_LIB_CTXs we have.
30  */
31 #define ALLOW_RUN_ONCE_IN_FIPS
32 #include "internal/thread_once.h"
33 #include "self_test.h"
34 
35 #define FIPS_STATE_INIT     0
36 #define FIPS_STATE_SELFTEST 1
37 #define FIPS_STATE_RUNNING  2
38 #define FIPS_STATE_ERROR    3
39 
40 /*
41  * The number of times the module will report it is in the error state
42  * before going quiet.
43  */
44 #define FIPS_ERROR_REPORTING_RATE_LIMIT     10
45 
46 /* The size of a temp buffer used to read in data */
47 #define INTEGRITY_BUF_SIZE (4096)
48 #define MAX_MD_SIZE 64
49 #define MAC_NAME    "HMAC"
50 #define DIGEST_NAME "SHA256"
51 
52 static int FIPS_conditional_error_check = 1;
53 static CRYPTO_RWLOCK *self_test_lock = NULL;
54 
55 static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
56 #if !defined(OPENSSL_NO_FIPS_POST)
57 static unsigned char fixed_key[32] = { FIPS_KEY_ELEMENTS };
58 #endif
59 
DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)60 DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
61 {
62     /*
63      * These locks get freed in platform specific ways that may occur after we
64      * do mem leak checking. If we don't know how to free it for a particular
65      * platform then we just leak it deliberately.
66      */
67     self_test_lock = CRYPTO_THREAD_lock_new();
68     return self_test_lock != NULL;
69 }
70 
71 /*
72  * Declarations for the DEP entry/exit points.
73  * Ones not required or incorrect need to be undefined or redefined respectively.
74  */
75 #define DEP_INITIAL_STATE   FIPS_STATE_INIT
76 #define DEP_INIT_ATTRIBUTE  static
77 #define DEP_FINI_ATTRIBUTE  static
78 
79 static void init(void);
80 static void cleanup(void);
81 
82 /*
83  * This is the Default Entry Point (DEP) code.
84  * See FIPS 140-2 IG 9.10
85  */
86 #if defined(_WIN32) || defined(__CYGWIN__)
87 # ifdef __CYGWIN__
88 /* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
89 #  include <windows.h>
90 /*
91  * this has side-effect of _WIN32 getting defined, which otherwise is
92  * mutually exclusive with __CYGWIN__...
93  */
94 # endif
95 
96 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)97 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
98 {
99     switch (fdwReason) {
100     case DLL_PROCESS_ATTACH:
101         init();
102         break;
103     case DLL_PROCESS_DETACH:
104         cleanup();
105         break;
106     default:
107         break;
108     }
109     return TRUE;
110 }
111 
112 #elif defined(__GNUC__) && !defined(_AIX)
113 # undef DEP_INIT_ATTRIBUTE
114 # undef DEP_FINI_ATTRIBUTE
115 # define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
116 # define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
117 
118 #elif defined(__sun)
119 # pragma init(init)
120 # pragma fini(cleanup)
121 
122 #elif defined(_AIX) && !defined(__GNUC__)
123 void _init(void);
124 void _cleanup(void);
125 # pragma init(_init)
126 # pragma fini(_cleanup)
_init(void)127 void _init(void)
128 {
129     init();
130 }
_cleanup(void)131 void _cleanup(void)
132 {
133     cleanup();
134 }
135 
136 #elif defined(__hpux)
137 # pragma init "init"
138 # pragma fini "cleanup"
139 
140 #elif defined(__TANDEM)
141 /* Method automatically called by the NonStop OS when the DLL loads */
__INIT__init(void)142 void __INIT__init(void) {
143     init();
144 }
145 
146 /* Method automatically called by the NonStop OS prior to unloading the DLL */
__TERM__cleanup(void)147 void __TERM__cleanup(void) {
148     cleanup();
149 }
150 
151 #else
152 /*
153  * This build does not support any kind of DEP.
154  * We force the self-tests to run as part of the FIPS provider initialisation
155  * rather than being triggered by the DEP.
156  */
157 # undef DEP_INIT_ATTRIBUTE
158 # undef DEP_FINI_ATTRIBUTE
159 # undef DEP_INITIAL_STATE
160 # define DEP_INITIAL_STATE  FIPS_STATE_SELFTEST
161 #endif
162 
163 static TSAN_QUALIFIER int FIPS_state = DEP_INITIAL_STATE;
164 
165 #if defined(DEP_INIT_ATTRIBUTE)
init(void)166 DEP_INIT_ATTRIBUTE void init(void)
167 {
168     tsan_store(&FIPS_state, FIPS_STATE_SELFTEST);
169 }
170 #endif
171 
172 #if defined(DEP_FINI_ATTRIBUTE)
cleanup(void)173 DEP_FINI_ATTRIBUTE void cleanup(void)
174 {
175     CRYPTO_THREAD_lock_free(self_test_lock);
176 }
177 #endif
178 
179 #if !defined(OPENSSL_NO_FIPS_POST)
180 /*
181  * We need an explicit HMAC-SHA-256 KAT even though it is also
182  * checked as part of the KDF KATs.  Refer IG 10.3.
183  */
184 static const unsigned char hmac_kat_pt[] = {
185     0xdd, 0x0c, 0x30, 0x33, 0x35, 0xf9, 0xe4, 0x2e,
186     0xc2, 0xef, 0xcc, 0xbf, 0x07, 0x95, 0xee, 0xa2
187 };
188 static const unsigned char hmac_kat_key[] = {
189     0xf4, 0x55, 0x66, 0x50, 0xac, 0x31, 0xd3, 0x54,
190     0x61, 0x61, 0x0b, 0xac, 0x4e, 0xd8, 0x1b, 0x1a,
191     0x18, 0x1b, 0x2d, 0x8a, 0x43, 0xea, 0x28, 0x54,
192     0xcb, 0xae, 0x22, 0xca, 0x74, 0x56, 0x08, 0x13
193 };
194 static const unsigned char hmac_kat_digest[] = {
195     0xf5, 0xf5, 0xe5, 0xf2, 0x66, 0x49, 0xe2, 0x40,
196     0xfc, 0x9e, 0x85, 0x7f, 0x2b, 0x9a, 0xbe, 0x28,
197     0x20, 0x12, 0x00, 0x92, 0x82, 0x21, 0x3e, 0x51,
198     0x44, 0x5d, 0xe3, 0x31, 0x04, 0x01, 0x72, 0x6b
199 };
200 
integrity_self_test(OSSL_SELF_TEST * ev,OSSL_LIB_CTX * libctx)201 static int integrity_self_test(OSSL_SELF_TEST *ev, OSSL_LIB_CTX *libctx)
202 {
203     int ok = 0;
204     unsigned char out[EVP_MAX_MD_SIZE];
205     size_t out_len = 0;
206 
207     OSSL_PARAM   params[2];
208     EVP_MAC     *mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
209     EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac);
210 
211     OSSL_SELF_TEST_onbegin(ev, OSSL_SELF_TEST_TYPE_KAT_INTEGRITY,
212                                OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
213 
214     params[0] = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
215     params[1] = OSSL_PARAM_construct_end();
216 
217     if (ctx == NULL
218             || mac == NULL
219             || !EVP_MAC_init(ctx, hmac_kat_key, sizeof(hmac_kat_key), params)
220             || !EVP_MAC_update(ctx, hmac_kat_pt, sizeof(hmac_kat_pt))
221             || !EVP_MAC_final(ctx, out, &out_len, MAX_MD_SIZE))
222         goto err;
223 
224     /* Optional corruption */
225     OSSL_SELF_TEST_oncorrupt_byte(ev, out);
226 
227     if (out_len != sizeof(hmac_kat_digest)
228             || memcmp(out, hmac_kat_digest, out_len) != 0)
229         goto err;
230     ok = 1;
231 err:
232     OSSL_SELF_TEST_onend(ev, ok);
233     EVP_MAC_free(mac);
234     EVP_MAC_CTX_free(ctx);
235     return ok;
236 }
237 
238 /*
239  * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
240  * the result matches the expected value.
241  * Return 1 if verified, or 0 if it fails.
242  */
verify_integrity(OSSL_CORE_BIO * bio,OSSL_FUNC_BIO_read_ex_fn read_ex_cb,unsigned char * expected,size_t expected_len,OSSL_LIB_CTX * libctx,OSSL_SELF_TEST * ev,const char * event_type)243 static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb,
244                             unsigned char *expected, size_t expected_len,
245                             OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev,
246                             const char *event_type)
247 {
248     int ret = 0, status;
249     unsigned char out[MAX_MD_SIZE];
250     unsigned char buf[INTEGRITY_BUF_SIZE];
251     size_t bytes_read = 0, out_len = 0;
252     EVP_MAC *mac = NULL;
253     EVP_MAC_CTX *ctx = NULL;
254     OSSL_PARAM params[2], *p = params;
255 
256     if (!integrity_self_test(ev, libctx))
257         goto err;
258 
259     OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
260 
261     mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
262     if (mac == NULL)
263         goto err;
264     ctx = EVP_MAC_CTX_new(mac);
265     if (ctx == NULL)
266         goto err;
267 
268     *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
269     *p = OSSL_PARAM_construct_end();
270 
271     if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params))
272         goto err;
273 
274     while (1) {
275         status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
276         if (status != 1)
277             break;
278         if (!EVP_MAC_update(ctx, buf, bytes_read))
279             goto err;
280     }
281     if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
282         goto err;
283 
284     OSSL_SELF_TEST_oncorrupt_byte(ev, out);
285     if (expected_len != out_len
286             || memcmp(expected, out, out_len) != 0)
287         goto err;
288     ret = 1;
289 err:
290     OSSL_SELF_TEST_onend(ev, ret);
291     EVP_MAC_CTX_free(ctx);
292     EVP_MAC_free(mac);
293 # ifdef OPENSSL_PEDANTIC_ZEROIZATION
294     OPENSSL_cleanse(out, sizeof(out));
295 # endif
296     return ret;
297 }
298 #endif /* OPENSSL_NO_FIPS_POST */
299 
set_fips_state(int state)300 static void set_fips_state(int state)
301 {
302     tsan_store(&FIPS_state, state);
303 }
304 
305 /* Return 1 if the FIPS self tests are running and 0 otherwise */
ossl_fips_self_testing(void)306 int ossl_fips_self_testing(void)
307 {
308     return tsan_load(&FIPS_state) == FIPS_STATE_SELFTEST;
309 }
310 
311 /* This API is triggered either on loading of the FIPS module or on demand */
SELF_TEST_post(SELF_TEST_POST_PARAMS * st,int on_demand_test)312 int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
313 {
314     int loclstate;
315 #if !defined(OPENSSL_NO_FIPS_POST)
316     int ok = 0;
317     long checksum_len;
318     OSSL_CORE_BIO *bio_module = NULL;
319     unsigned char *module_checksum = NULL;
320     OSSL_SELF_TEST *ev = NULL;
321     EVP_RAND *testrand = NULL;
322     EVP_RAND_CTX *rng;
323 #endif
324 
325     if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
326         return 0;
327 
328     loclstate = tsan_load(&FIPS_state);
329 
330     if (loclstate == FIPS_STATE_RUNNING) {
331         if (!on_demand_test)
332             return 1;
333     } else if (loclstate != FIPS_STATE_SELFTEST) {
334         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
335         return 0;
336     }
337 
338     if (!CRYPTO_THREAD_write_lock(self_test_lock))
339         return 0;
340 
341 #if !defined(OPENSSL_NO_FIPS_POST)
342     loclstate = tsan_load(&FIPS_state);
343     if (loclstate == FIPS_STATE_RUNNING) {
344         if (!on_demand_test) {
345             CRYPTO_THREAD_unlock(self_test_lock);
346             return 1;
347         }
348         set_fips_state(FIPS_STATE_SELFTEST);
349     } else if (loclstate != FIPS_STATE_SELFTEST) {
350         CRYPTO_THREAD_unlock(self_test_lock);
351         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
352         return 0;
353     }
354 
355     if (st == NULL
356             || st->module_checksum_data == NULL) {
357         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
358         goto end;
359     }
360 
361     ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg);
362     if (ev == NULL)
363         goto end;
364 
365     module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
366                                          &checksum_len);
367     if (module_checksum == NULL) {
368         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
369         goto end;
370     }
371     bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
372 
373     /* Always check the integrity of the fips module */
374     if (bio_module == NULL
375             || !verify_integrity(bio_module, st->bio_read_ex_cb,
376                                  module_checksum, checksum_len, st->libctx,
377                                  ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) {
378         ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE);
379         goto end;
380     }
381 
382     if (!SELF_TEST_kats(ev, st->libctx)) {
383         ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
384         goto end;
385     }
386 
387     /* Verify that the RNG has been restored properly */
388     rng = ossl_rand_get0_private_noncreating(st->libctx);
389     if (rng != NULL)
390         if ((testrand = EVP_RAND_fetch(st->libctx, "TEST-RAND", NULL)) == NULL
391                 || strcmp(EVP_RAND_get0_name(EVP_RAND_CTX_get0_rand(rng)),
392                           EVP_RAND_get0_name(testrand)) == 0) {
393             ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
394             goto end;
395         }
396 
397     ok = 1;
398 end:
399     EVP_RAND_free(testrand);
400     OSSL_SELF_TEST_free(ev);
401     OPENSSL_free(module_checksum);
402 
403     if (st != NULL)
404         (*st->bio_free_cb)(bio_module);
405 
406     if (ok)
407         set_fips_state(FIPS_STATE_RUNNING);
408     else
409         ossl_set_error_state(OSSL_SELF_TEST_TYPE_NONE);
410     CRYPTO_THREAD_unlock(self_test_lock);
411 
412     return ok;
413 #else
414     set_fips_state(FIPS_STATE_RUNNING);
415     CRYPTO_THREAD_unlock(self_test_lock);
416     return 1;
417 #endif /* !defined(OPENSSL_NO_FIPS_POST) */
418 }
419 
SELF_TEST_disable_conditional_error_state(void)420 void SELF_TEST_disable_conditional_error_state(void)
421 {
422     FIPS_conditional_error_check = 0;
423 }
424 
ossl_set_error_state(const char * type)425 void ossl_set_error_state(const char *type)
426 {
427     int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0);
428 
429     if (!cond_test || (FIPS_conditional_error_check == 1)) {
430         set_fips_state(FIPS_STATE_ERROR);
431         ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE);
432     } else {
433         ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR);
434     }
435 }
436 
ossl_prov_is_running(void)437 int ossl_prov_is_running(void)
438 {
439     int res, loclstate;
440     static TSAN_QUALIFIER unsigned int rate_limit = 0;
441 
442     loclstate = tsan_load(&FIPS_state);
443     res = loclstate == FIPS_STATE_RUNNING || loclstate == FIPS_STATE_SELFTEST;
444     if (loclstate == FIPS_STATE_ERROR)
445         if (tsan_counter(&rate_limit) < FIPS_ERROR_REPORTING_RATE_LIMIT)
446             ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE);
447     return res;
448 }
449