Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/providers/fips/self_test.c
105194 views
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
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);
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)
127
void _init(void)
128
{
129
init();
130
}
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 */
142
void __INIT__init(void)
143
{
144
init();
145
}
146
147
/* Method automatically called by the NonStop OS prior to unloading the DLL */
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)
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)
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
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
*/
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
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 */
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 */
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
423
void SELF_TEST_disable_conditional_error_state(void)
424
{
425
FIPS_conditional_error_check = 0;
426
}
427
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
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
462