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