xref: /freebsd/crypto/openssl/providers/fips/self_test.c (revision 10a428653ee7216475f1ddce3fb4cbf1200319f8)
1 /*
2  * Copyright 2019-2026 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 #ifndef __CYGWIN__
105         cleanup();
106 #endif
107         break;
108     default:
109         break;
110     }
111     return TRUE;
112 }
113 
114 #elif defined(__GNUC__) && !defined(_AIX)
115 #undef DEP_INIT_ATTRIBUTE
116 #undef DEP_FINI_ATTRIBUTE
117 #define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
118 #define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
119 
120 #elif defined(__sun)
121 #pragma init(init)
122 #pragma fini(cleanup)
123 
124 #elif defined(_AIX) && !defined(__GNUC__)
125 void _init(void);
126 void _cleanup(void);
127 #pragma init(_init)
128 #pragma fini(_cleanup)
_init(void)129 void _init(void)
130 {
131     init();
132 }
_cleanup(void)133 void _cleanup(void)
134 {
135     cleanup();
136 }
137 
138 #elif defined(__hpux)
139 #pragma init "init"
140 #pragma fini "cleanup"
141 
142 #elif defined(__TANDEM)
143 /* Method automatically called by the NonStop OS when the DLL loads */
__INIT__init(void)144 void __INIT__init(void)
145 {
146     init();
147 }
148 
149 /* Method automatically called by the NonStop OS prior to unloading the DLL */
__TERM__cleanup(void)150 void __TERM__cleanup(void)
151 {
152     cleanup();
153 }
154 
155 #else
156 /*
157  * This build does not support any kind of DEP.
158  * We force the self-tests to run as part of the FIPS provider initialisation
159  * rather than being triggered by the DEP.
160  */
161 #undef DEP_INIT_ATTRIBUTE
162 #undef DEP_FINI_ATTRIBUTE
163 #undef DEP_INITIAL_STATE
164 #define DEP_INITIAL_STATE FIPS_STATE_SELFTEST
165 #endif
166 
167 static TSAN_QUALIFIER int FIPS_state = DEP_INITIAL_STATE;
168 
169 #if defined(DEP_INIT_ATTRIBUTE)
init(void)170 DEP_INIT_ATTRIBUTE void init(void)
171 {
172     tsan_store(&FIPS_state, FIPS_STATE_SELFTEST);
173 }
174 #endif
175 
176 #if defined(DEP_FINI_ATTRIBUTE)
cleanup(void)177 DEP_FINI_ATTRIBUTE void cleanup(void)
178 {
179     CRYPTO_THREAD_lock_free(self_test_lock);
180 }
181 #endif
182 
183 #if !defined(OPENSSL_NO_FIPS_POST)
184 /*
185  * We need an explicit HMAC-SHA-256 KAT even though it is also
186  * checked as part of the KDF KATs.  Refer IG 10.3.
187  */
188 static const unsigned char hmac_kat_pt[] = {
189     0xdd, 0x0c, 0x30, 0x33, 0x35, 0xf9, 0xe4, 0x2e,
190     0xc2, 0xef, 0xcc, 0xbf, 0x07, 0x95, 0xee, 0xa2
191 };
192 static const unsigned char hmac_kat_key[] = {
193     0xf4, 0x55, 0x66, 0x50, 0xac, 0x31, 0xd3, 0x54,
194     0x61, 0x61, 0x0b, 0xac, 0x4e, 0xd8, 0x1b, 0x1a,
195     0x18, 0x1b, 0x2d, 0x8a, 0x43, 0xea, 0x28, 0x54,
196     0xcb, 0xae, 0x22, 0xca, 0x74, 0x56, 0x08, 0x13
197 };
198 static const unsigned char hmac_kat_digest[] = {
199     0xf5, 0xf5, 0xe5, 0xf2, 0x66, 0x49, 0xe2, 0x40,
200     0xfc, 0x9e, 0x85, 0x7f, 0x2b, 0x9a, 0xbe, 0x28,
201     0x20, 0x12, 0x00, 0x92, 0x82, 0x21, 0x3e, 0x51,
202     0x44, 0x5d, 0xe3, 0x31, 0x04, 0x01, 0x72, 0x6b
203 };
204 
integrity_self_test(OSSL_SELF_TEST * ev,OSSL_LIB_CTX * libctx)205 static int integrity_self_test(OSSL_SELF_TEST *ev, OSSL_LIB_CTX *libctx)
206 {
207     int ok = 0;
208     unsigned char out[EVP_MAX_MD_SIZE];
209     size_t out_len = 0;
210 
211     OSSL_PARAM params[2];
212     EVP_MAC *mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
213     EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac);
214 
215     OSSL_SELF_TEST_onbegin(ev, OSSL_SELF_TEST_TYPE_KAT_INTEGRITY,
216         OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
217 
218     params[0] = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
219     params[1] = OSSL_PARAM_construct_end();
220 
221     if (ctx == NULL
222         || mac == NULL
223         || !EVP_MAC_init(ctx, hmac_kat_key, sizeof(hmac_kat_key), params)
224         || !EVP_MAC_update(ctx, hmac_kat_pt, sizeof(hmac_kat_pt))
225         || !EVP_MAC_final(ctx, out, &out_len, MAX_MD_SIZE))
226         goto err;
227 
228     /* Optional corruption */
229     OSSL_SELF_TEST_oncorrupt_byte(ev, out);
230 
231     if (out_len != sizeof(hmac_kat_digest)
232         || memcmp(out, hmac_kat_digest, out_len) != 0)
233         goto err;
234     ok = 1;
235 err:
236     OSSL_SELF_TEST_onend(ev, ok);
237     EVP_MAC_free(mac);
238     EVP_MAC_CTX_free(ctx);
239     return ok;
240 }
241 
242 /*
243  * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
244  * the result matches the expected value.
245  * Return 1 if verified, or 0 if it fails.
246  */
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)247 static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb,
248     unsigned char *expected, size_t expected_len,
249     OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev,
250     const char *event_type)
251 {
252     int ret = 0, status;
253     unsigned char out[MAX_MD_SIZE];
254     unsigned char buf[INTEGRITY_BUF_SIZE];
255     size_t bytes_read = 0, out_len = 0;
256     EVP_MAC *mac = NULL;
257     EVP_MAC_CTX *ctx = NULL;
258     OSSL_PARAM params[2], *p = params;
259 
260     if (!integrity_self_test(ev, libctx))
261         goto err;
262 
263     OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
264 
265     mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
266     if (mac == NULL)
267         goto err;
268     ctx = EVP_MAC_CTX_new(mac);
269     if (ctx == NULL)
270         goto err;
271 
272     *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
273     *p = OSSL_PARAM_construct_end();
274 
275     if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params))
276         goto err;
277 
278     while (1) {
279         status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
280         if (status != 1)
281             break;
282         if (!EVP_MAC_update(ctx, buf, bytes_read))
283             goto err;
284     }
285     if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
286         goto err;
287 
288     OSSL_SELF_TEST_oncorrupt_byte(ev, out);
289     if (expected_len != out_len
290         || memcmp(expected, out, out_len) != 0)
291         goto err;
292     ret = 1;
293 err:
294     OSSL_SELF_TEST_onend(ev, ret);
295     EVP_MAC_CTX_free(ctx);
296     EVP_MAC_free(mac);
297 #ifdef OPENSSL_PEDANTIC_ZEROIZATION
298     OPENSSL_cleanse(out, sizeof(out));
299 #endif
300     return ret;
301 }
302 #endif /* OPENSSL_NO_FIPS_POST */
303 
set_fips_state(int state)304 static void set_fips_state(int state)
305 {
306     tsan_store(&FIPS_state, state);
307 }
308 
309 /* Return 1 if the FIPS self tests are running and 0 otherwise */
ossl_fips_self_testing(void)310 int ossl_fips_self_testing(void)
311 {
312     return tsan_load(&FIPS_state) == FIPS_STATE_SELFTEST;
313 }
314 
315 /* 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)316 int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
317 {
318     int loclstate;
319 #if !defined(OPENSSL_NO_FIPS_POST)
320     int ok = 0;
321     long checksum_len;
322     OSSL_CORE_BIO *bio_module = NULL;
323     unsigned char *module_checksum = NULL;
324     OSSL_SELF_TEST *ev = NULL;
325     EVP_RAND *testrand = NULL;
326     EVP_RAND_CTX *rng;
327 #endif
328 
329     if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
330         return 0;
331 
332     loclstate = tsan_load(&FIPS_state);
333 
334     if (loclstate == FIPS_STATE_RUNNING) {
335         if (!on_demand_test)
336             return 1;
337     } else if (loclstate != FIPS_STATE_SELFTEST) {
338         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
339         return 0;
340     }
341 
342     if (!CRYPTO_THREAD_write_lock(self_test_lock))
343         return 0;
344 
345 #if !defined(OPENSSL_NO_FIPS_POST)
346     loclstate = tsan_load(&FIPS_state);
347     if (loclstate == FIPS_STATE_RUNNING) {
348         if (!on_demand_test) {
349             CRYPTO_THREAD_unlock(self_test_lock);
350             return 1;
351         }
352         set_fips_state(FIPS_STATE_SELFTEST);
353     } else if (loclstate != FIPS_STATE_SELFTEST) {
354         CRYPTO_THREAD_unlock(self_test_lock);
355         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
356         return 0;
357     }
358 
359     if (st == NULL
360         || st->module_checksum_data == NULL) {
361         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
362         goto end;
363     }
364 
365     ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg);
366     if (ev == NULL)
367         goto end;
368 
369     module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
370         &checksum_len);
371     if (module_checksum == NULL) {
372         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
373         goto end;
374     }
375     bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
376 
377     /* Always check the integrity of the fips module */
378     if (bio_module == NULL
379         || !verify_integrity(bio_module, st->bio_read_ex_cb,
380             module_checksum, checksum_len, st->libctx,
381             ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) {
382         ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE);
383         goto end;
384     }
385 
386     if (!SELF_TEST_kats(ev, st->libctx)) {
387         ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
388         goto end;
389     }
390 
391     /* Verify that the RNG has been restored properly */
392     rng = ossl_rand_get0_private_noncreating(st->libctx);
393     if (rng != NULL)
394         if ((testrand = EVP_RAND_fetch(st->libctx, "TEST-RAND", NULL)) == NULL
395             || strcmp(EVP_RAND_get0_name(EVP_RAND_CTX_get0_rand(rng)),
396                    EVP_RAND_get0_name(testrand))
397                 == 0) {
398             ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
399             goto end;
400         }
401 
402     ok = 1;
403 end:
404     EVP_RAND_free(testrand);
405     OSSL_SELF_TEST_free(ev);
406     OPENSSL_free(module_checksum);
407 
408     if (st != NULL)
409         (*st->bio_free_cb)(bio_module);
410 
411     if (ok)
412         set_fips_state(FIPS_STATE_RUNNING);
413     else
414         ossl_set_error_state(OSSL_SELF_TEST_TYPE_NONE);
415     CRYPTO_THREAD_unlock(self_test_lock);
416 
417     return ok;
418 #else
419     set_fips_state(FIPS_STATE_RUNNING);
420     CRYPTO_THREAD_unlock(self_test_lock);
421     return 1;
422 #endif /* !defined(OPENSSL_NO_FIPS_POST) */
423 }
424 
SELF_TEST_disable_conditional_error_state(void)425 void SELF_TEST_disable_conditional_error_state(void)
426 {
427     FIPS_conditional_error_check = 0;
428 }
429 
ossl_set_error_state(const char * type)430 void ossl_set_error_state(const char *type)
431 {
432     int cond_test = 0;
433     int import_pct = 0;
434 
435     if (type != NULL) {
436         cond_test = strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0;
437         import_pct = strcmp(type, OSSL_SELF_TEST_TYPE_PCT_IMPORT) == 0;
438     }
439 
440     if (import_pct) {
441         /* Failure to import is transient to avoid a DoS attack */
442         ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IMPORT_PCT_ERROR);
443     } else if (!cond_test || (FIPS_conditional_error_check == 1)) {
444         set_fips_state(FIPS_STATE_ERROR);
445         ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE);
446     } else {
447         ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR);
448     }
449 }
450 
ossl_prov_is_running(void)451 int ossl_prov_is_running(void)
452 {
453     int res, loclstate;
454     static TSAN_QUALIFIER unsigned int rate_limit = 0;
455 
456     loclstate = tsan_load(&FIPS_state);
457     res = loclstate == FIPS_STATE_RUNNING || loclstate == FIPS_STATE_SELFTEST;
458     if (loclstate == FIPS_STATE_ERROR)
459         if (tsan_counter(&rate_limit) < FIPS_ERROR_REPORTING_RATE_LIMIT)
460             ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE);
461     return res;
462 }
463