VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.7/providers/fips/self_test.c@ 107835

Last change on this file since 107835 was 104078, checked in by vboxsync, 11 months ago

openssl-3.1.5: Applied and adjusted our OpenSSL changes to 3.1.4. bugref:10638

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette