]>
Commit | Line | Data |
---|---|---|
7bb82f92 SL |
1 | /* |
2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (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> | |
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, | |
36fc5fc6 SL |
135 | OPENSSL_CTX *libctx, OSSL_ST_EVENT *ev, |
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 | ||
36fc5fc6 SL |
146 | SELF_TEST_EVENT_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC); |
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 | ||
36fc5fc6 | 173 | SELF_TEST_EVENT_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: | |
36fc5fc6 | 179 | SELF_TEST_EVENT_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; |
36fc5fc6 | 195 | OSSL_ST_EVENT ev; |
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 | ||
36fc5fc6 SL |
226 | SELF_TEST_EVENT_init(&ev, st->event_cb, st->event_cb_arg); |
227 | ||
7bb82f92 SL |
228 | module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data, |
229 | &checksum_len); | |
230 | if (module_checksum == NULL) | |
231 | goto end; | |
232 | bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb"); | |
233 | ||
234 | /* Always check the integrity of the fips module */ | |
235 | if (bio_module == NULL | |
236 | || !verify_integrity(bio_module, st->bio_read_ex_cb, | |
36fc5fc6 SL |
237 | module_checksum, checksum_len, st->libctx, |
238 | &ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) | |
7bb82f92 SL |
239 | goto end; |
240 | ||
241 | /* This will be NULL during installation - so the self test KATS will run */ | |
242 | if (st->indicator_data != NULL) { | |
243 | /* | |
244 | * If the kats have already passed indicator is set - then check the | |
245 | * integrity of the indicator. | |
246 | */ | |
247 | if (st->indicator_checksum_data == NULL) | |
248 | goto end; | |
249 | indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data, | |
250 | &checksum_len); | |
251 | if (indicator_checksum == NULL) | |
252 | goto end; | |
253 | ||
254 | bio_indicator = | |
255 | (*st->bio_new_buffer_cb)(st->indicator_data, | |
256 | strlen(st->indicator_data)); | |
257 | if (bio_indicator == NULL | |
258 | || !verify_integrity(bio_indicator, st->bio_read_ex_cb, | |
259 | indicator_checksum, checksum_len, | |
36fc5fc6 SL |
260 | st->libctx, &ev, |
261 | OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY)) | |
7bb82f92 SL |
262 | goto end; |
263 | else | |
264 | kats_already_passed = 1; | |
265 | } | |
266 | ||
267 | /* Only runs the KAT's during installation OR on_demand() */ | |
268 | if (on_demand_test || kats_already_passed == 0) { | |
36fc5fc6 SL |
269 | if (!SELF_TEST_kats(&ev, st->libctx)) |
270 | goto end; | |
7bb82f92 SL |
271 | } |
272 | ok = 1; | |
273 | end: | |
274 | OPENSSL_free(module_checksum); | |
275 | OPENSSL_free(indicator_checksum); | |
276 | ||
12fca1af SL |
277 | if (st != NULL) { |
278 | (*st->bio_free_cb)(bio_indicator); | |
279 | (*st->bio_free_cb)(bio_module); | |
280 | } | |
7bb82f92 | 281 | FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR; |
14a684bf | 282 | CRYPTO_THREAD_unlock(self_test_lock); |
7bb82f92 SL |
283 | |
284 | return ok; | |
285 | } |