]>
Commit | Line | Data |
---|---|---|
7bb82f92 | 1 | /* |
33388b44 | 2 | * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. |
7bb82f92 | 3 | * |
a6ed19dc | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
7bb82f92 SL |
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> | |
14a684bf MC |
13 | #include <openssl/crypto.h> |
14 | #include "e_os.h" | |
15 | /* | |
16 | * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS | |
17 | * module because all such initialisation should be associated with an | |
18 | * individual OPENSSL_CTX. That doesn't work with the self test though because | |
19 | * it should be run once regardless of the number of OPENSSL_CTXs we have. | |
20 | */ | |
21 | #define ALLOW_RUN_ONCE_IN_FIPS | |
22 | #include <internal/thread_once.h> | |
36fc5fc6 | 23 | #include "self_test.h" |
7bb82f92 SL |
24 | |
25 | #define FIPS_STATE_INIT 0 | |
14a684bf MC |
26 | #define FIPS_STATE_SELFTEST 1 |
27 | #define FIPS_STATE_RUNNING 2 | |
7bb82f92 SL |
28 | #define FIPS_STATE_ERROR 3 |
29 | ||
30 | /* The size of a temp buffer used to read in data */ | |
31 | #define INTEGRITY_BUF_SIZE (4096) | |
32 | #define MAX_MD_SIZE 64 | |
33 | #define MAC_NAME "HMAC" | |
34 | #define DIGEST_NAME "SHA256" | |
35 | ||
36 | static int FIPS_state = FIPS_STATE_INIT; | |
14a684bf | 37 | static CRYPTO_RWLOCK *self_test_lock = NULL; |
7bb82f92 SL |
38 | static unsigned char fixed_key[32] = { 0 }; |
39 | ||
14a684bf MC |
40 | static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT; |
41 | DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init) | |
42 | { | |
cc38e643 MC |
43 | /* |
44 | * This lock gets freed in platform specific ways that may occur after we | |
45 | * do mem leak checking. If we don't know how to free it for a particular | |
46 | * platform then we just leak it deliberately. So we temporarily disable the | |
47 | * mem leak checking while we allocate this. | |
48 | */ | |
14a684bf | 49 | self_test_lock = CRYPTO_THREAD_lock_new(); |
14a684bf MC |
50 | return self_test_lock != NULL; |
51 | } | |
52 | ||
390b18a7 SL |
53 | #define DEP_DECLARE() \ |
54 | void init(void); \ | |
55 | void cleanup(void); | |
56 | ||
14a684bf MC |
57 | /* |
58 | * This is the Default Entry Point (DEP) code. Every platform must have a DEP. | |
59 | * See FIPS 140-2 IG 9.10 | |
60 | * | |
61 | * If we're run on a platform where we don't know how to define the DEP then | |
62 | * the self-tests will never get triggered (FIPS_state never moves to | |
63 | * FIPS_STATE_SELFTEST). This will be detected as an error when SELF_TEST_post() | |
64 | * is called from OSSL_provider_init(), and so the fips module will be unusable | |
65 | * on those platforms. | |
66 | */ | |
67 | #if defined(_WIN32) || defined(__CYGWIN__) | |
68 | # ifdef __CYGWIN__ | |
69 | /* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */ | |
70 | # include <windows.h> | |
71 | /* | |
72 | * this has side-effect of _WIN32 getting defined, which otherwise is | |
73 | * mutually exclusive with __CYGWIN__... | |
74 | */ | |
75 | # endif | |
76 | ||
390b18a7 SL |
77 | DEP_DECLARE() |
78 | # define DEP_INIT_ATTRIBUTE | |
79 | # define DEP_FINI_ATTRIBUTE | |
14a684bf MC |
80 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); |
81 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | |
82 | { | |
83 | switch (fdwReason) { | |
84 | case DLL_PROCESS_ATTACH: | |
390b18a7 | 85 | init(); |
14a684bf MC |
86 | break; |
87 | case DLL_PROCESS_DETACH: | |
390b18a7 | 88 | cleanup(); |
14a684bf MC |
89 | break; |
90 | default: | |
91 | break; | |
92 | } | |
93 | return TRUE; | |
94 | } | |
390b18a7 SL |
95 | #elif defined(__sun) |
96 | ||
97 | DEP_DECLARE() /* must be declared before pragma */ | |
98 | # define DEP_INIT_ATTRIBUTE | |
99 | # define DEP_FINI_ATTRIBUTE | |
100 | # pragma init(init) | |
101 | # pragma fini(cleanup) | |
102 | ||
103 | #elif defined(__hpux) | |
104 | ||
105 | DEP_DECLARE() | |
106 | # define DEP_INIT_ATTRIBUTE | |
107 | # define DEP_FINI_ATTRIBUTE | |
108 | # pragma init "init" | |
109 | # pragma fini "cleanup" | |
110 | ||
14a684bf | 111 | #elif defined(__GNUC__) |
390b18a7 SL |
112 | # define DEP_INIT_ATTRIBUTE static __attribute__((constructor)) |
113 | # define DEP_FINI_ATTRIBUTE static __attribute__((destructor)) | |
114 | #endif | |
14a684bf | 115 | |
390b18a7 SL |
116 | #if defined(DEP_INIT_ATTRIBUTE) && defined(DEP_FINI_ATTRIBUTE) |
117 | DEP_INIT_ATTRIBUTE void init(void) | |
14a684bf MC |
118 | { |
119 | FIPS_state = FIPS_STATE_SELFTEST; | |
120 | } | |
121 | ||
390b18a7 | 122 | DEP_FINI_ATTRIBUTE void cleanup(void) |
14a684bf MC |
123 | { |
124 | CRYPTO_THREAD_lock_free(self_test_lock); | |
125 | } | |
14a684bf MC |
126 | #endif |
127 | ||
7bb82f92 SL |
128 | /* |
129 | * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify | |
130 | * the result matches the expected value. | |
131 | * Return 1 if verified, or 0 if it fails. | |
132 | */ | |
133 | static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb, | |
134 | unsigned char *expected, size_t expected_len, | |
47c239c6 | 135 | OPENSSL_CTX *libctx, OSSL_SELF_TEST *ev, |
36fc5fc6 | 136 | const char *event_type) |
7bb82f92 SL |
137 | { |
138 | int ret = 0, status; | |
139 | unsigned char out[MAX_MD_SIZE]; | |
140 | unsigned char buf[INTEGRITY_BUF_SIZE]; | |
141 | size_t bytes_read = 0, out_len = 0; | |
142 | EVP_MAC *mac = NULL; | |
143 | EVP_MAC_CTX *ctx = NULL; | |
144 | OSSL_PARAM params[3], *p = params; | |
145 | ||
47c239c6 | 146 | OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC); |
36fc5fc6 | 147 | |
7bb82f92 SL |
148 | mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); |
149 | ctx = EVP_MAC_CTX_new(mac); | |
150 | if (mac == NULL || ctx == NULL) | |
151 | goto err; | |
152 | ||
153 | *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, | |
154 | strlen(DIGEST_NAME) + 1); | |
155 | *p++ = OSSL_PARAM_construct_octet_string("key", fixed_key, | |
156 | sizeof(fixed_key)); | |
157 | *p = OSSL_PARAM_construct_end(); | |
158 | ||
159 | if (EVP_MAC_CTX_set_params(ctx, params) <= 0 | |
160 | || !EVP_MAC_init(ctx)) | |
161 | goto err; | |
162 | ||
163 | while (1) { | |
164 | status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read); | |
165 | if (status != 1) | |
166 | break; | |
167 | if (!EVP_MAC_update(ctx, buf, bytes_read)) | |
168 | goto err; | |
169 | } | |
170 | if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out))) | |
171 | goto err; | |
172 | ||
47c239c6 | 173 | OSSL_SELF_TEST_oncorrupt_byte(ev, out); |
7bb82f92 SL |
174 | if (expected_len != out_len |
175 | || memcmp(expected, out, out_len) != 0) | |
176 | goto err; | |
177 | ret = 1; | |
178 | err: | |
47c239c6 | 179 | OSSL_SELF_TEST_onend(ev, ret); |
7bb82f92 SL |
180 | EVP_MAC_CTX_free(ctx); |
181 | EVP_MAC_free(mac); | |
182 | return ret; | |
183 | } | |
184 | ||
185 | /* This API is triggered either on loading of the FIPS module or on demand */ | |
14a684bf | 186 | int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test) |
7bb82f92 SL |
187 | { |
188 | int ok = 0; | |
189 | int kats_already_passed = 0; | |
7bb82f92 SL |
190 | long checksum_len; |
191 | BIO *bio_module = NULL, *bio_indicator = NULL; | |
192 | unsigned char *module_checksum = NULL; | |
193 | unsigned char *indicator_checksum = NULL; | |
14a684bf | 194 | int loclstate; |
47c239c6 | 195 | OSSL_SELF_TEST *ev = NULL; |
14a684bf MC |
196 | |
197 | if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init)) | |
198 | return 0; | |
199 | ||
200 | CRYPTO_THREAD_read_lock(self_test_lock); | |
201 | loclstate = FIPS_state; | |
202 | CRYPTO_THREAD_unlock(self_test_lock); | |
7bb82f92 | 203 | |
14a684bf MC |
204 | if (loclstate == FIPS_STATE_RUNNING) { |
205 | if (!on_demand_test) | |
206 | return 1; | |
207 | } else if (loclstate != FIPS_STATE_SELFTEST) { | |
208 | return 0; | |
209 | } | |
210 | ||
211 | CRYPTO_THREAD_write_lock(self_test_lock); | |
212 | if (FIPS_state == FIPS_STATE_RUNNING) { | |
213 | if (!on_demand_test) { | |
214 | CRYPTO_THREAD_unlock(self_test_lock); | |
215 | return 1; | |
216 | } | |
217 | FIPS_state = FIPS_STATE_SELFTEST; | |
218 | } else if (FIPS_state != FIPS_STATE_SELFTEST) { | |
219 | CRYPTO_THREAD_unlock(self_test_lock); | |
220 | return 0; | |
221 | } | |
7bb82f92 | 222 | if (st == NULL |
7bb82f92 SL |
223 | || st->module_checksum_data == NULL) |
224 | goto end; | |
225 | ||
47c239c6 SL |
226 | ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg); |
227 | if (ev == NULL) | |
228 | goto end; | |
36fc5fc6 | 229 | |
7bb82f92 SL |
230 | module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data, |
231 | &checksum_len); | |
232 | if (module_checksum == NULL) | |
233 | goto end; | |
234 | bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb"); | |
235 | ||
236 | /* Always check the integrity of the fips module */ | |
237 | if (bio_module == NULL | |
238 | || !verify_integrity(bio_module, st->bio_read_ex_cb, | |
36fc5fc6 | 239 | module_checksum, checksum_len, st->libctx, |
47c239c6 | 240 | ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) |
7bb82f92 SL |
241 | goto end; |
242 | ||
243 | /* This will be NULL during installation - so the self test KATS will run */ | |
244 | if (st->indicator_data != NULL) { | |
245 | /* | |
246 | * If the kats have already passed indicator is set - then check the | |
247 | * integrity of the indicator. | |
248 | */ | |
249 | if (st->indicator_checksum_data == NULL) | |
250 | goto end; | |
251 | indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data, | |
252 | &checksum_len); | |
253 | if (indicator_checksum == NULL) | |
254 | goto end; | |
255 | ||
256 | bio_indicator = | |
257 | (*st->bio_new_buffer_cb)(st->indicator_data, | |
258 | strlen(st->indicator_data)); | |
259 | if (bio_indicator == NULL | |
260 | || !verify_integrity(bio_indicator, st->bio_read_ex_cb, | |
261 | indicator_checksum, checksum_len, | |
47c239c6 | 262 | st->libctx, ev, |
36fc5fc6 | 263 | OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY)) |
7bb82f92 SL |
264 | goto end; |
265 | else | |
266 | kats_already_passed = 1; | |
267 | } | |
268 | ||
269 | /* Only runs the KAT's during installation OR on_demand() */ | |
270 | if (on_demand_test || kats_already_passed == 0) { | |
47c239c6 | 271 | if (!SELF_TEST_kats(ev, st->libctx)) |
36fc5fc6 | 272 | goto end; |
7bb82f92 SL |
273 | } |
274 | ok = 1; | |
275 | end: | |
47c239c6 | 276 | OSSL_SELF_TEST_free(ev); |
7bb82f92 SL |
277 | OPENSSL_free(module_checksum); |
278 | OPENSSL_free(indicator_checksum); | |
279 | ||
12fca1af SL |
280 | if (st != NULL) { |
281 | (*st->bio_free_cb)(bio_indicator); | |
282 | (*st->bio_free_cb)(bio_module); | |
283 | } | |
7bb82f92 | 284 | FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR; |
14a684bf | 285 | CRYPTO_THREAD_unlock(self_test_lock); |
7bb82f92 SL |
286 | |
287 | return ok; | |
288 | } |