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