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