VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.3/providers/fips/self_test.c@ 101773

Last change on this file since 101773 was 101211, checked in by vboxsync, 20 months ago

openssl-3.1.3: Applied and adjusted our OpenSSL changes to 3.1.2. bugref:10527

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

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