1 /* module_hooks.c -- module load/unload hooks for libwolfssl.ko
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22 #ifndef WOLFSSL_LICENSE
23 #define WOLFSSL_LICENSE "GPL v2"
24 #endif
25
26 #define FIPS_NO_WRAPPERS
27
28 #define WOLFSSL_NEED_LINUX_CURRENT
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <wolfssl/wolfcrypt/settings.h>
35 #include <wolfssl/wolfcrypt/error-crypt.h>
36 #include <wolfssl/ssl.h>
37 #ifdef HAVE_FIPS
38 #include <wolfssl/wolfcrypt/fips_test.h>
39 #endif
40 #ifndef NO_CRYPT_TEST
41 #include <wolfcrypt/test/test.h>
42 #include <linux/delay.h>
43 #endif
44
libwolfssl_cleanup(void)45 static int libwolfssl_cleanup(void) {
46 int ret;
47 #ifdef WOLFCRYPT_ONLY
48 ret = wolfCrypt_Cleanup();
49 if (ret != 0)
50 pr_err("wolfCrypt_Cleanup() failed: %s\n", wc_GetErrorString(ret));
51 else
52 pr_info("wolfCrypt " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n");
53 #else
54 ret = wolfSSL_Cleanup();
55 if (ret != WOLFSSL_SUCCESS)
56 pr_err("wolfSSL_Cleanup() failed: %s\n", wc_GetErrorString(ret));
57 else
58 pr_info("wolfSSL " LIBWOLFSSL_VERSION_STRING " cleanup complete.\n");
59 #endif
60
61 return ret;
62 }
63
64 #ifdef HAVE_LINUXKM_PIE_SUPPORT
65
66 extern int wolfCrypt_PIE_first_function(void);
67 extern int wolfCrypt_PIE_last_function(void);
68 extern const unsigned int wolfCrypt_PIE_rodata_start[];
69 extern const unsigned int wolfCrypt_PIE_rodata_end[];
70
71 /* cheap portable ad-hoc hash function to confirm bitwise stability of the PIE
72 * binary image.
73 */
hash_span(char * start,char * end)74 static unsigned int hash_span(char *start, char *end) {
75 unsigned int sum = 1;
76 while (start < end) {
77 unsigned int rotate_by;
78 sum ^= *start++;
79 rotate_by = (sum ^ (sum >> 5)) & 31;
80 sum = (sum << rotate_by) | (sum >> (32 - rotate_by));
81 }
82 return sum;
83 }
84
85 #ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE
86 extern struct wolfssl_linuxkm_pie_redirect_table wolfssl_linuxkm_pie_redirect_table;
87 static int set_up_wolfssl_linuxkm_pie_redirect_table(void);
88 #endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
89
90 #endif /* HAVE_LINUXKM_PIE_SUPPORT */
91
92 #ifdef HAVE_FIPS
lkmFipsCb(int ok,int err,const char * hash)93 static void lkmFipsCb(int ok, int err, const char* hash)
94 {
95 if ((! ok) || (err != 0))
96 pr_err("libwolfssl FIPS error: %s\n", wc_GetErrorString(err));
97 if (err == IN_CORE_FIPS_E) {
98 pr_err("In-core integrity hash check failure.\n"
99 "Update verifyCore[] in fips_test.c with new hash \"%s\" and rebuild.\n",
100 hash ? hash : "<null>");
101 }
102 }
103 #endif
104
105 #ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
106 #ifndef CONFIG_MODULE_SIG
107 #error WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE requires a CONFIG_MODULE_SIG kernel.
108 #endif
109 static int updateFipsHash(void);
110 #endif
111
112 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
wolfssl_init(void)113 static int __init wolfssl_init(void)
114 #else
115 static int wolfssl_init(void)
116 #endif
117 {
118 int ret;
119
120 #ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
121 if (THIS_MODULE->sig_ok == false) {
122 pr_err("wolfSSL module load aborted -- bad or missing module signature with FIPS dynamic hash.\n");
123 return -ECANCELED;
124 }
125 ret = updateFipsHash();
126 if (ret < 0) {
127 pr_err("wolfSSL module load aborted -- updateFipsHash: %s\n",wc_GetErrorString(ret));
128 return -ECANCELED;
129 }
130 #endif
131
132 #ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE
133 ret = set_up_wolfssl_linuxkm_pie_redirect_table();
134 if (ret < 0)
135 return ret;
136 #endif
137
138 #ifdef HAVE_LINUXKM_PIE_SUPPORT
139
140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
141 #define THIS_MODULE_BASE (THIS_MODULE->core_layout.base)
142 #define THIS_MODULE_TEXT_SIZE (THIS_MODULE->core_layout.text_size)
143 #define THIS_MODULE_RO_SIZE (THIS_MODULE->core_layout.ro_size)
144 #else
145 #define THIS_MODULE_BASE (THIS_MODULE->module_core)
146 #define THIS_MODULE_TEXT_SIZE (THIS_MODULE->core_text_size)
147 #define THIS_MODULE_RO_SIZE (THIS_MODULE->core_ro_size)
148 #endif
149
150 {
151 char *pie_text_start = (char *)wolfCrypt_PIE_first_function;
152 char *pie_text_end = (char *)wolfCrypt_PIE_last_function;
153 char *pie_rodata_start = (char *)wolfCrypt_PIE_rodata_start;
154 char *pie_rodata_end = (char *)wolfCrypt_PIE_rodata_end;
155 unsigned int text_hash, rodata_hash;
156
157 if ((pie_text_start < pie_text_end) &&
158 (pie_text_start >= (char *)THIS_MODULE_BASE) &&
159 (pie_text_end - (char *)THIS_MODULE_BASE <= THIS_MODULE_TEXT_SIZE))
160 {
161 text_hash = hash_span(pie_text_start, pie_text_end);
162 } else {
163 pr_info("out-of-bounds PIE fenceposts! pie_text_start=%px pie_text_end=%px (span=%lu)"
164 " core_layout.base=%px text_end=%px\n",
165 pie_text_start,
166 pie_text_end,
167 pie_text_end-pie_text_start,
168 THIS_MODULE_BASE,
169 (char *)THIS_MODULE_BASE + THIS_MODULE_TEXT_SIZE);
170 text_hash = 0;
171 }
172
173 if ((pie_rodata_start < pie_rodata_end) &&
174 (pie_rodata_start >= (char *)THIS_MODULE_BASE + THIS_MODULE_TEXT_SIZE) &&
175 (pie_rodata_end - (char *)THIS_MODULE_BASE <= THIS_MODULE_RO_SIZE))
176 {
177 rodata_hash = hash_span(pie_rodata_start, pie_rodata_end);
178 } else {
179 pr_info("out-of-bounds PIE fenceposts! pie_rodata_start=%px pie_rodata_end=%px (span=%lu)"
180 " core_layout.base+core_layout.text_size=%px rodata_end=%px\n",
181 pie_rodata_start,
182 pie_rodata_end,
183 pie_rodata_end-pie_rodata_start,
184 (char *)THIS_MODULE_BASE + THIS_MODULE_TEXT_SIZE,
185 (char *)THIS_MODULE_BASE + THIS_MODULE_RO_SIZE);
186 rodata_hash = 0;
187 }
188
189 /* note, "%pK" conceals the actual layout information. "%px" exposes
190 * the true module start address, which is potentially useful to an
191 * attacker.
192 */
193 pr_info("wolfCrypt container hashes (spans): %x (%lu) %x (%lu), module base %pK\n",
194 text_hash, pie_text_end-pie_text_start,
195 rodata_hash, pie_rodata_end-pie_rodata_start,
196 THIS_MODULE_BASE);
197 }
198 #endif /* HAVE_LINUXKM_PIE_SUPPORT */
199
200 #ifdef HAVE_FIPS
201 ret = wolfCrypt_SetCb_fips(lkmFipsCb);
202 if (ret != 0) {
203 pr_err("wolfCrypt_SetCb_fips() failed: %s\n", wc_GetErrorString(ret));
204 return -ECANCELED;
205 }
206 fipsEntry();
207 ret = wolfCrypt_GetStatus_fips();
208 if (ret != 0) {
209 pr_err("wolfCrypt_GetStatus_fips() failed: %s\n", wc_GetErrorString(ret));
210 if (ret == IN_CORE_FIPS_E) {
211 const char *newhash = wolfCrypt_GetCoreHash_fips();
212 pr_err("Update verifyCore[] in fips_test.c with new hash \"%s\" and rebuild.\n",
213 newhash ? newhash : "<null>");
214 }
215 return -ECANCELED;
216 }
217
218 pr_info("wolfCrypt FIPS ["
219
220 #if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 3)
221 "ready"
222 #elif defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2) \
223 && defined(WOLFCRYPT_FIPS_RAND)
224 "140-2 rand"
225 #elif defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION == 2)
226 "140-2"
227 #else
228 "140"
229 #endif
230 "] POST succeeded.\n");
231 #endif /* HAVE_FIPS */
232
233 #ifdef WOLFCRYPT_ONLY
234 ret = wolfCrypt_Init();
235 if (ret != 0) {
236 pr_err("wolfCrypt_Init() failed: %s\n", wc_GetErrorString(ret));
237 return -ECANCELED;
238 }
239 #else
240 ret = wolfSSL_Init();
241 if (ret != WOLFSSL_SUCCESS) {
242 pr_err("wolfSSL_Init() failed: %s\n", wc_GetErrorString(ret));
243 return -ECANCELED;
244 }
245 #endif
246
247 #ifndef NO_CRYPT_TEST
248
249 #ifdef WC_RNG_SEED_CB
250 ret = wc_SetSeed_Cb(wc_GenerateSeed);
251 if (ret == 0)
252 #endif
253 {
254 ret = wolfcrypt_test(NULL);
255 }
256 if (ret < 0) {
257 pr_err("wolfcrypt self-test failed with return code %d.\n", ret);
258 (void)libwolfssl_cleanup();
259 msleep(10);
260 return -ECANCELED;
261 }
262 pr_info("wolfCrypt self-test passed.\n");
263 #endif
264
265 #ifdef WOLFCRYPT_ONLY
266 pr_info("wolfCrypt " LIBWOLFSSL_VERSION_STRING " loaded%s"
267 ".\nSee https://www.wolfssl.com/ for more information.\n"
268 "wolfCrypt Copyright (C) 2006-present wolfSSL Inc. Licensed under " WOLFSSL_LICENSE ".\n",
269 #ifdef CONFIG_MODULE_SIG
270 THIS_MODULE->sig_ok ? " with valid module signature" : " without valid module signature"
271 #else
272 ""
273 #endif
274 );
275 #else
276 pr_info("wolfSSL " LIBWOLFSSL_VERSION_STRING " loaded%s"
277 ".\nSee https://www.wolfssl.com/ for more information.\n"
278 "wolfSSL Copyright (C) 2006-present wolfSSL Inc. Licensed under " WOLFSSL_LICENSE ".\n",
279 #ifdef CONFIG_MODULE_SIG
280 THIS_MODULE->sig_ok ? " with valid module signature" : " without valid module signature"
281 #else
282 ""
283 #endif
284 );
285 #endif
286
287 return 0;
288 }
289
290 module_init(wolfssl_init);
291
292 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
wolfssl_exit(void)293 static void __exit wolfssl_exit(void)
294 #else
295 static void wolfssl_exit(void)
296 #endif
297 {
298 (void)libwolfssl_cleanup();
299
300 return;
301 }
302
303 module_exit(wolfssl_exit);
304
305 MODULE_LICENSE(WOLFSSL_LICENSE);
306 MODULE_AUTHOR("https://www.wolfssl.com/");
307 MODULE_DESCRIPTION("libwolfssl cryptographic and protocol facilities");
308 MODULE_VERSION(LIBWOLFSSL_VERSION_STRING);
309
310 #ifdef USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE
311
312 /* get_current() is an inline or macro, depending on the target -- sidestep the whole issue with a wrapper func. */
my_get_current_thread(void)313 static struct task_struct *my_get_current_thread(void) {
314 return get_current();
315 }
316
317 /* ditto for preempt_count(). */
my_preempt_count(void)318 static int my_preempt_count(void) {
319 return preempt_count();
320 }
321
322 #if defined(WOLFSSL_LINUXKM_SIMD_X86) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0))
my_copy_fpregs_to_fpstate(struct fpu * fpu)323 static int my_copy_fpregs_to_fpstate(struct fpu *fpu) {
324 return copy_fpregs_to_fpstate(fpu);
325 }
my_copy_kernel_to_fpregs(union fpregs_state * fpstate)326 static void my_copy_kernel_to_fpregs(union fpregs_state *fpstate) {
327 copy_kernel_to_fpregs(fpstate);
328 }
329 #endif
330
set_up_wolfssl_linuxkm_pie_redirect_table(void)331 static int set_up_wolfssl_linuxkm_pie_redirect_table(void) {
332 memset(
333 &wolfssl_linuxkm_pie_redirect_table,
334 0,
335 sizeof wolfssl_linuxkm_pie_redirect_table);
336
337 #ifndef __ARCH_MEMCMP_NO_REDIRECT
338 wolfssl_linuxkm_pie_redirect_table.memcmp = memcmp;
339 #endif
340 #ifndef __ARCH_MEMCPY_NO_REDIRECT
341 wolfssl_linuxkm_pie_redirect_table.memcpy = memcpy;
342 #endif
343 #ifndef __ARCH_MEMSET_NO_REDIRECT
344 wolfssl_linuxkm_pie_redirect_table.memset = memset;
345 #endif
346 #ifndef __ARCH_MEMMOVE_NO_REDIRECT
347 wolfssl_linuxkm_pie_redirect_table.memmove = memmove;
348 #endif
349 #ifndef __ARCH_STRNCMP_NO_REDIRECT
350 wolfssl_linuxkm_pie_redirect_table.strncmp = strncmp;
351 #endif
352 #ifndef __ARCH_STRLEN_NO_REDIRECT
353 wolfssl_linuxkm_pie_redirect_table.strlen = strlen;
354 #endif
355 #ifndef __ARCH_STRSTR_NO_REDIRECT
356 wolfssl_linuxkm_pie_redirect_table.strstr = strstr;
357 #endif
358 #ifndef __ARCH_STRNCPY_NO_REDIRECT
359 wolfssl_linuxkm_pie_redirect_table.strncpy = strncpy;
360 #endif
361 #ifndef __ARCH_STRNCAT_NO_REDIRECT
362 wolfssl_linuxkm_pie_redirect_table.strncat = strncat;
363 #endif
364 #ifndef __ARCH_STRNCASECMP_NO_REDIRECT
365 wolfssl_linuxkm_pie_redirect_table.strncasecmp = strncasecmp;
366 #endif
367 wolfssl_linuxkm_pie_redirect_table.kstrtoll = kstrtoll;
368
369 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
370 wolfssl_linuxkm_pie_redirect_table._printk = _printk;
371 #else
372 wolfssl_linuxkm_pie_redirect_table.printk = printk;
373 #endif
374 wolfssl_linuxkm_pie_redirect_table.snprintf = snprintf;
375
376 wolfssl_linuxkm_pie_redirect_table._ctype = _ctype;
377
378 wolfssl_linuxkm_pie_redirect_table.kmalloc = kmalloc;
379 wolfssl_linuxkm_pie_redirect_table.kfree = kfree;
380 wolfssl_linuxkm_pie_redirect_table.ksize = ksize;
381 wolfssl_linuxkm_pie_redirect_table.krealloc = krealloc;
382 #ifdef HAVE_KVMALLOC
383 wolfssl_linuxkm_pie_redirect_table.kvmalloc_node = kvmalloc_node;
384 wolfssl_linuxkm_pie_redirect_table.kvfree = kvfree;
385 #endif
386 wolfssl_linuxkm_pie_redirect_table.is_vmalloc_addr = is_vmalloc_addr;
387 wolfssl_linuxkm_pie_redirect_table.kmem_cache_alloc_trace =
388 kmem_cache_alloc_trace;
389 wolfssl_linuxkm_pie_redirect_table.kmalloc_order_trace =
390 kmalloc_order_trace;
391
392 wolfssl_linuxkm_pie_redirect_table.get_random_bytes = get_random_bytes;
393 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
394 wolfssl_linuxkm_pie_redirect_table.getnstimeofday =
395 getnstimeofday;
396 #elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0)
397 wolfssl_linuxkm_pie_redirect_table.current_kernel_time64 =
398 current_kernel_time64;
399 #else
400 wolfssl_linuxkm_pie_redirect_table.ktime_get_coarse_real_ts64 =
401 ktime_get_coarse_real_ts64;
402 #endif
403
404 wolfssl_linuxkm_pie_redirect_table.get_current = my_get_current_thread;
405 wolfssl_linuxkm_pie_redirect_table.preempt_count = my_preempt_count;
406
407 #ifdef WOLFSSL_LINUXKM_SIMD_X86
408 wolfssl_linuxkm_pie_redirect_table.irq_fpu_usable = irq_fpu_usable;
409 #ifdef kernel_fpu_begin
410 wolfssl_linuxkm_pie_redirect_table.kernel_fpu_begin_mask =
411 kernel_fpu_begin_mask;
412 #else
413 wolfssl_linuxkm_pie_redirect_table.kernel_fpu_begin =
414 kernel_fpu_begin;
415 #endif
416 wolfssl_linuxkm_pie_redirect_table.kernel_fpu_end = kernel_fpu_end;
417 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)
418 wolfssl_linuxkm_pie_redirect_table.copy_fpregs_to_fpstate = my_copy_fpregs_to_fpstate;
419 wolfssl_linuxkm_pie_redirect_table.copy_kernel_to_fpregs = my_copy_kernel_to_fpregs;
420 #else
421 wolfssl_linuxkm_pie_redirect_table.save_fpregs_to_fpstate = save_fpregs_to_fpstate;
422 wolfssl_linuxkm_pie_redirect_table.__restore_fpregs_from_fpstate = __restore_fpregs_from_fpstate;
423 wolfssl_linuxkm_pie_redirect_table.xfeatures_mask_all = &xfeatures_mask_all;
424 #endif
425 wolfssl_linuxkm_pie_redirect_table.cpu_number = &cpu_number;
426 wolfssl_linuxkm_pie_redirect_table.nr_cpu_ids = &nr_cpu_ids;
427 #endif
428
429 wolfssl_linuxkm_pie_redirect_table.__mutex_init = __mutex_init;
430 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
431 wolfssl_linuxkm_pie_redirect_table.mutex_lock_nested = mutex_lock_nested;
432 #else
433 wolfssl_linuxkm_pie_redirect_table.mutex_lock = mutex_lock;
434 #endif
435 wolfssl_linuxkm_pie_redirect_table.mutex_unlock = mutex_unlock;
436 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
437 wolfssl_linuxkm_pie_redirect_table.mutex_destroy = mutex_destroy;
438 #endif
439
440 #ifdef HAVE_FIPS
441 wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_first =
442 wolfCrypt_FIPS_first;
443 wolfssl_linuxkm_pie_redirect_table.wolfCrypt_FIPS_last =
444 wolfCrypt_FIPS_last;
445 #endif
446
447 #if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS)
448 wolfssl_linuxkm_pie_redirect_table.GetCA = GetCA;
449 #ifndef NO_SKID
450 wolfssl_linuxkm_pie_redirect_table.GetCAByName = GetCAByName;
451 #endif
452 #endif
453
454 /* runtime assert that the table has no null slots after initialization. */
455 {
456 unsigned long *i;
457 for (i = (unsigned long *)&wolfssl_linuxkm_pie_redirect_table;
458 i < (unsigned long *)&wolfssl_linuxkm_pie_redirect_table._last_slot;
459 ++i)
460 if (*i == 0) {
461 pr_err("wolfCrypt container redirect table initialization was incomplete.\n");
462 return -EFAULT;
463 }
464 }
465
466 return 0;
467 }
468
469 #endif /* USE_WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */
470
471
472 #ifdef WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE
473
474 #include <wolfssl/wolfcrypt/coding.h>
475
476 PRAGMA_GCC_DIAG_PUSH;
477 PRAGMA_GCC("GCC diagnostic ignored \"-Wnested-externs\"");
478 PRAGMA_GCC("GCC diagnostic ignored \"-Wpointer-arith\"");
479 #include <crypto/hash.h>
480 PRAGMA_GCC_DIAG_POP;
481
482 extern char verifyCore[WC_SHA256_DIGEST_SIZE*2 + 1];
483 extern const char coreKey[WC_SHA256_DIGEST_SIZE*2 + 1];
484 extern const unsigned int wolfCrypt_FIPS_ro_start[];
485 extern const unsigned int wolfCrypt_FIPS_ro_end[];
486
487 #define FIPS_IN_CORE_KEY_SZ 32
488 #define FIPS_IN_CORE_VERIFY_SZ FIPS_IN_CORE_KEY_SZ
489 typedef int (*fips_address_function)(void);
490 #define MAX_FIPS_DATA_SZ 100000
491 #define MAX_FIPS_CODE_SZ 1000000
492 extern int GenBase16_Hash(const byte* in, int length, char* out, int outSz);
493
updateFipsHash(void)494 static int updateFipsHash(void)
495 {
496 struct crypto_shash *tfm = NULL;
497 struct shash_desc *desc = NULL;
498 word32 verifySz = FIPS_IN_CORE_VERIFY_SZ;
499 word32 binCoreSz = FIPS_IN_CORE_KEY_SZ;
500 int ret;
501 byte *hash = NULL;
502 char *base16_hash = NULL;
503 byte *binCoreKey = NULL;
504 byte *binVerify = NULL;
505
506 fips_address_function first = wolfCrypt_FIPS_first;
507 fips_address_function last = wolfCrypt_FIPS_last;
508
509 char* start = (char*)wolfCrypt_FIPS_ro_start;
510 char* end = (char*)wolfCrypt_FIPS_ro_end;
511
512 unsigned long code_sz = (unsigned long)last - (unsigned long)first;
513 unsigned long data_sz = (unsigned long)end - (unsigned long)start;
514
515 if (data_sz == 0 || data_sz > MAX_FIPS_DATA_SZ)
516 return BAD_FUNC_ARG; /* bad fips data size */
517
518 if (code_sz == 0 || code_sz > MAX_FIPS_CODE_SZ)
519 return BAD_FUNC_ARG; /* bad fips code size */
520
521 hash = XMALLOC(WC_SHA256_DIGEST_SIZE, 0, DYNAMIC_TYPE_TMP_BUFFER);
522 if (hash == NULL) {
523 ret = MEMORY_E;
524 goto out;
525 }
526 base16_hash = XMALLOC(WC_SHA256_DIGEST_SIZE*2 + 1, 0, DYNAMIC_TYPE_TMP_BUFFER);
527 if (base16_hash == NULL) {
528 ret = MEMORY_E;
529 goto out;
530 }
531 binCoreKey = XMALLOC(binCoreSz, 0, DYNAMIC_TYPE_TMP_BUFFER);
532 if (binCoreKey == NULL) {
533 ret = MEMORY_E;
534 goto out;
535 }
536 binVerify = XMALLOC(verifySz, 0, DYNAMIC_TYPE_TMP_BUFFER);
537 if (binVerify == NULL) {
538 ret = MEMORY_E;
539 goto out;
540 }
541
542 {
543 word32 base16_out_len = binCoreSz;
544 ret = Base16_Decode((const byte *)coreKey, sizeof coreKey - 1, binCoreKey, &base16_out_len);
545 if (ret != 0) {
546 pr_err("Base16_Decode for coreKey: %s\n", wc_GetErrorString(ret));
547 goto out;
548 }
549 if (base16_out_len != binCoreSz) {
550 pr_err("unexpected output length %u for coreKey from Base16_Decode.\n",base16_out_len);
551 ret = BAD_STATE_E;
552 goto out;
553 }
554 }
555
556 tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
557 if (IS_ERR(tfm)) {
558 if (PTR_ERR(tfm) == -ENOMEM) {
559 pr_err("crypto_alloc_shash failed: out of memory\n");
560 ret = MEMORY_E;
561 } else if (PTR_ERR(tfm) == -ENOENT) {
562 pr_err("crypto_alloc_shash failed: kernel is missing hmac(sha256) implementation\n");
563 pr_err("check for CONFIG_CRYPTO_SHA256 and CONFIG_CRYPTO_HMAC.\n");
564 ret = NOT_COMPILED_IN;
565 } else {
566 pr_err("crypto_alloc_shash failed with ret %ld\n",PTR_ERR(tfm));
567 ret = HASH_TYPE_E;
568 }
569 tfm = NULL;
570 goto out;
571 }
572
573 {
574 size_t desc_size = crypto_shash_descsize(tfm) + sizeof *desc;
575 desc = XMALLOC(desc_size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
576 if (desc == NULL) {
577 pr_err("failed allocating desc.");
578 ret = MEMORY_E;
579 goto out;
580 }
581 XMEMSET(desc, 0, desc_size);
582 }
583
584 ret = crypto_shash_setkey(tfm, binCoreKey, binCoreSz);
585 if (ret) {
586 pr_err("crypto_ahash_setkey failed: err %d\n", ret);
587 ret = BAD_STATE_E;
588 goto out;
589 }
590
591 desc->tfm = tfm;
592 ret = crypto_shash_init(desc);
593 if (ret) {
594 pr_err("crypto_shash_init failed: err %d\n", ret);
595 ret = BAD_STATE_E;
596 goto out;
597 }
598
599 ret = crypto_shash_update(desc, (byte *)(wc_ptr_t)first, (word32)code_sz);
600 if (ret) {
601 pr_err("crypto_shash_update failed: err %d\n", ret);
602 ret = BAD_STATE_E;
603 goto out;
604 }
605
606 /* don't hash verifyCore or changing verifyCore will change hash */
607 if (verifyCore >= start && verifyCore < end) {
608 data_sz = (unsigned long)verifyCore - (unsigned long)start;
609 ret = crypto_shash_update(desc, (byte*)start, (word32)data_sz);
610 if (ret) {
611 pr_err("crypto_shash_update failed: err %d\n", ret);
612 ret = BAD_STATE_E;
613 goto out;
614 }
615 start = (char*)verifyCore + sizeof(verifyCore);
616 data_sz = (unsigned long)end - (unsigned long)start;
617 }
618 ret = crypto_shash_update(desc, (byte*)start, (word32)data_sz);
619 if (ret) {
620 pr_err("crypto_shash_update failed: err %d\n", ret);
621 ret = BAD_STATE_E;
622 goto out;
623 }
624
625 ret = crypto_shash_final(desc, hash);
626 if (ret) {
627 pr_err("crypto_shash_final failed: err %d\n", ret);
628 ret = BAD_STATE_E;
629 goto out;
630 }
631
632 ret = GenBase16_Hash(hash, WC_SHA256_DIGEST_SIZE, base16_hash, WC_SHA256_DIGEST_SIZE*2 + 1);
633 if (ret != 0) {
634 pr_err("GenBase16_Hash failed: %s\n", wc_GetErrorString(ret));
635 goto out;
636 }
637
638 {
639 word32 base16_out_len = verifySz;
640 ret = Base16_Decode((const byte *)verifyCore, sizeof verifyCore - 1, binVerify, &base16_out_len);
641 if (ret != 0) {
642 pr_err("Base16_Decode for verifyCore: %s\n", wc_GetErrorString(ret));
643 goto out;
644 }
645 if (base16_out_len != binCoreSz) {
646 pr_err("unexpected output length %u for verifyCore from Base16_Decode.\n",base16_out_len);
647 ret = BAD_STATE_E;
648 goto out;
649 }
650 }
651
652 if (XMEMCMP(hash, binVerify, WC_SHA256_DIGEST_SIZE) == 0)
653 pr_info("updateFipsHash: verifyCore already matches.\n");
654 else {
655 XMEMCPY(verifyCore, base16_hash, WC_SHA256_DIGEST_SIZE*2 + 1);
656 pr_info("updateFipsHash: verifyCore updated.\n");
657 }
658
659 ret = 0;
660
661 out:
662
663 if (tfm != NULL)
664 crypto_free_shash(tfm);
665 if (desc != NULL)
666 XFREE(desc, NULL, DYNAMIC_TYPE_TMP_BUFFER);
667 if (hash != NULL)
668 XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
669 if (base16_hash != NULL)
670 XFREE(base16_hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
671 if (binCoreKey != NULL)
672 XFREE(binCoreKey, NULL, DYNAMIC_TYPE_TMP_BUFFER);
673 if (binVerify != NULL)
674 XFREE(binVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
675
676 return ret;
677 }
678
679 #endif /* WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE */
680