diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index 17c9d4f137..fe3f823942 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -118,11 +118,11 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes" ifndef NO_PIE_FLAG ifeq ($(KERNEL_ARCH),arm) ifeq ($(intcmp $(VERSION),5,1,0,0),1) - NO_PIE_FLAG := + NO_PIE_FLAG := 1 $(info Note: disabling -fPIE to avoid R_ARM_REL32 on pre-5.11 target kernel.) else ifeq ($(intcmp $(VERSION),5,0,1,0)-$(intcmp $(PATCHLEVEL),11,1,0,0),1-1) - NO_PIE_FLAG := + NO_PIE_FLAG := 1 $(info Note: disabling -fPIE to avoid R_ARM_REL32 on pre-5.11 target kernel.) endif endif diff --git a/linuxkm/Makefile b/linuxkm/Makefile index b91d4c0b1b..0c1cdfaa11 100644 --- a/linuxkm/Makefile +++ b/linuxkm/Makefile @@ -157,30 +157,48 @@ GENERATE_SECTION_MAP := $(AWK) 'BEGIN { printf("") >ENVIRON["SECTION_MAP"]; } \ }' GENERATE_RELOC_TAB := $(AWK) ' \ - BEGIN { \ - n=0; \ + function open_seg(seg) { \ + seen_seg[seg] = 1; \ + printf("%s\n ", \ + "WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_" seg "_reloc_tab[] = { "); \ + cur_seg = seg; \ + } \ + function close_cur_seg() { \ + print " { .offset = ~0U, .dest_offset = ~0U, .dest_addend = 0, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \ + print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_" cur_seg "_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_" cur_seg "_reloc_tab / sizeof wc_linuxkm_pie_" cur_seg "_reloc_tab[0]);"; \ + cur_seg = ""; \ + } \ + BEGIN { \ bad_relocs=0; \ print "\#include "; \ print "\#include "; \ - printf("%s\n ", \ - "WOLFSSL_LOCAL const struct wc_reloc_table_ent wc_linuxkm_pie_reloc_tab[] = { "); \ + print ""; \ if ("SECTION_MAP" in ENVIRON) { \ while (getline 0) \ section_map[$$1] = $$2; \ close(ENVIRON["SECTION_MAP"]); \ } \ } \ - /^Relocation section '\''\.rela?\.text_wolfcrypt'\''/ { \ - p=1; \ - next; \ - } \ + \ /^Relocation section/ { \ - p=0; \ + if (cur_seg) { \ + close_cur_seg(); \ + } \ + { \ + if (match($$0, "^Relocation section '\''\\.rela?\\.(text|rodata)_wolfcrypt'\''", a)) {\ + open_seg(a[1]); \ + next; \ + } \ + } \ + } \ + \ + { \ + if (! cur_seg) \ + next; \ } \ /^0/ { \ - if (p) { \ - if ($$3 !~ "^(R_X86_64_PLT32|R_X86_64_PC32|R_AARCH64_.*|R_ARM.*)$$") { \ - print "Unexpected relocation type:\n" $$0 >"/dev/stderr"; \ + if ($$3 !~ "^(R_X86_.*|R_AARCH64_.*|R_ARM.*)$$") { \ + print "Unexpected relocation type in " cur_seg ":\n" $$0 >"/dev/stderr"; \ ++bad_relocs; \ } \ if ($$5 in section_map) \ @@ -224,15 +242,22 @@ GENERATE_RELOC_TAB := $(AWK) ' \ strtonum("0x" $$4), \ $$6 strtonum("0x" $$7), \ section_tag, reloc_type); \ - } \ } \ END { \ + if (cur_seg) { \ + close_cur_seg(); \ + } \ + n = split("text rodata", segs, " "); \ + for (i = 1; i <= n; ++i) { \ + if (! (segs[i] in seen_seg)) { \ + open_seg(segs[i]); \ + close_cur_seg(); \ + } \ + } \ if (bad_relocs) { \ print "Found " bad_relocs " unresolvable relocations." >"/dev/stderr"; \ exit(1); \ } \ - print " { .offset = ~0U, .dest_offset = ~0U, .dest_addend = 0, .dest_segment = WC_R_SEG_NONE, .reloc_type = WC_R_NONE } };"; \ - print "WOLFSSL_LOCAL const unsigned int wc_linuxkm_pie_reloc_tab_length = (unsigned int)(sizeof wc_linuxkm_pie_reloc_tab / sizeof wc_linuxkm_pie_reloc_tab[0]);"; \ }' ifeq "$(V)" "1" @@ -384,7 +409,7 @@ $(MODULE_TOP)/libwolfssl-user-build/src/.libs/libwolfssl.so: $(LIBWOLFSSL_NAME). @ echo 'Using existing Makefile for libwolfssl.so.' @else @ echo -n 'Configuring user libwolfssl.so...' - @ $(FRESH_ENV) ./configure $(QFLAG) $(VFLAG) --disable-jobserver --enable-cryptonly --enable-fips="$$FIPS_FLAVOR" CFLAGS='-DWC_SYM_RELOC_TABLES_SUPPORT -DWOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE -DWOLFSSL_USER_SETTINGS -DWOLFSSL_USER_SETTINGS_ASM' $(if $(HOSTCC),CC='$(HOSTCC)') + @ $(FRESH_ENV) ./configure $(QFLAG) $(VFLAG) --disable-jobserver --enable-cryptonly --enable-fips="$$FIPS_FLAVOR" CFLAGS='-DWC_SYM_RELOC_TABLES_SUPPORT -DWOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE -DWOLFSSL_USER_SETTINGS -DWOLFSSL_USER_SETTINGS_ASM -DDEBUG_LINUXKM_PIE_SUPPORT' $(if $(HOSTCC),CC='$(HOSTCC)') @ echo ' done.' @fi @echo -n 'Building user libwolfssl.so...' diff --git a/linuxkm/linuxkm-fips-hash-wrapper.sh b/linuxkm/linuxkm-fips-hash-wrapper.sh index 57a2f02be0..1018d30c15 100755 --- a/linuxkm/linuxkm-fips-hash-wrapper.sh +++ b/linuxkm/linuxkm-fips-hash-wrapper.sh @@ -48,15 +48,19 @@ fi # shellcheck disable=SC2016 # using $AWK instead of awk confuses shellcheck. readarray -t fenceposts < <(readelf --wide --sections --symbols "$mod_path" | "$AWK" ' BEGIN { - fips_fenceposts["wc_linuxkm_pie_reloc_tab"] = "reloc_tab_start"; - fips_fenceposts["wc_linuxkm_pie_reloc_tab_length"] = "reloc_tab_len_start"; + fips_fenceposts["wc_linuxkm_pie_text_reloc_tab"] = "text_reloc_tab.start"; + fips_fenceposts["wc_linuxkm_pie_text_reloc_tab_length"] = "text_reloc_tab.len_start"; + fips_fenceposts["wc_linuxkm_pie_rodata_reloc_tab"] = "rodata_reloc_tab.start"; + fips_fenceposts["wc_linuxkm_pie_rodata_reloc_tab_length"] = "rodata_reloc_tab.len_start"; fips_fenceposts["verifyCore"] = "verifyCore_start"; fips_fenceposts["wolfCrypt_FIPS_first"] = "fips_text_start"; fips_fenceposts["wolfCrypt_FIPS_last"] = "fips_text_end"; fips_fenceposts["wolfCrypt_FIPS_ro_start"] = "fips_rodata_start"; fips_fenceposts["wolfCrypt_FIPS_ro_end"] = "fips_rodata_end"; - singleton_ends["wc_linuxkm_pie_reloc_tab"] = "reloc_tab_end"; - singleton_ends["wc_linuxkm_pie_reloc_tab_length"] = "reloc_tab_len_end"; + singleton_ends["wc_linuxkm_pie_text_reloc_tab"] = "text_reloc_tab.end"; + singleton_ends["wc_linuxkm_pie_text_reloc_tab_length"] = "text_reloc_tab.len_end"; + singleton_ends["wc_linuxkm_pie_rodata_reloc_tab"] = "rodata_reloc_tab.end"; + singleton_ends["wc_linuxkm_pie_rodata_reloc_tab_length"] = "rodata_reloc_tab.len_end"; singleton_ends["verifyCore"] = "verifyCore_end"; } diff --git a/linuxkm/linuxkm-fips-hash.c b/linuxkm/linuxkm-fips-hash.c index fc53a1619f..ff327f0ceb 100644 --- a/linuxkm/linuxkm-fips-hash.c +++ b/linuxkm/linuxkm-fips-hash.c @@ -104,10 +104,14 @@ int main(int argc, char **argv) .val = FENCEPOST_OPT_FLAG | offsetof(typeof(seg_map), x) } FENCEPOST_OPT(text_start), FENCEPOST_OPT(text_end), - FENCEPOST_OPT(reloc_tab_start), - FENCEPOST_OPT(reloc_tab_end), - FENCEPOST_OPT(reloc_tab_len_start), - FENCEPOST_OPT(reloc_tab_len_end), + FENCEPOST_OPT(text_reloc_tab.start), + FENCEPOST_OPT(text_reloc_tab.end), + FENCEPOST_OPT(text_reloc_tab.len_start), + FENCEPOST_OPT(text_reloc_tab.len_end), + FENCEPOST_OPT(rodata_reloc_tab.start), + FENCEPOST_OPT(rodata_reloc_tab.end), + FENCEPOST_OPT(rodata_reloc_tab.len_start), + FENCEPOST_OPT(rodata_reloc_tab.len_end), FENCEPOST_OPT(fips_text_start), FENCEPOST_OPT(fips_text_end), FENCEPOST_OPT(rodata_start), @@ -228,10 +232,14 @@ int main(int argc, char **argv) if ((seg_map.text_start == ~0UL) || (seg_map.text_end == ~0UL) || - (seg_map.reloc_tab_start == ~0UL) || - (seg_map.reloc_tab_end == ~0UL) || - (seg_map.reloc_tab_len_start == ~0UL) || - (seg_map.reloc_tab_len_end == ~0UL) || + (seg_map.text_reloc_tab.start == ~0UL) || + (seg_map.text_reloc_tab.end == ~0UL) || + (seg_map.text_reloc_tab.len_start == ~0UL) || + (seg_map.text_reloc_tab.len_end == ~0UL) || + (seg_map.rodata_reloc_tab.start == ~0UL) || + (seg_map.rodata_reloc_tab.end == ~0UL) || + (seg_map.rodata_reloc_tab.len_start == ~0UL) || + (seg_map.rodata_reloc_tab.len_end == ~0UL) || (seg_map.fips_text_start == ~0UL) || (seg_map.fips_text_end == ~0UL) || (seg_map.rodata_start == ~0UL) || @@ -267,12 +275,23 @@ int main(int argc, char **argv) exit(1); } - if ((seg_map.reloc_tab_start >= seg_map.reloc_tab_end) || - (seg_map.reloc_tab_end >= (unsigned long)st.st_size) || - (seg_map.reloc_tab_len_start >= seg_map.reloc_tab_len_end) || - (seg_map.reloc_tab_len_end >= (unsigned long)st.st_size)) + if ((seg_map.text_reloc_tab.start >= seg_map.text_reloc_tab.end) || + (seg_map.text_reloc_tab.end >= (unsigned long)st.st_size) || + (seg_map.text_reloc_tab.len_start >= seg_map.text_reloc_tab.len_end) || + (seg_map.text_reloc_tab.len_end >= (unsigned long)st.st_size)) { - fprintf(stderr, "%s: supplied reloc_tab fencepost(s) are out of bounds " + fprintf(stderr, "%s: supplied text_reloc_tab fencepost(s) are out of bounds " + "for supplied module %s with length %lu.\n", + progname, mod_path, (unsigned long)st.st_size); + exit(1); + } + + if ((seg_map.rodata_reloc_tab.start >= seg_map.rodata_reloc_tab.end) || + (seg_map.rodata_reloc_tab.end >= (unsigned long)st.st_size) || + (seg_map.rodata_reloc_tab.len_start >= seg_map.rodata_reloc_tab.len_end) || + (seg_map.rodata_reloc_tab.len_end >= (unsigned long)st.st_size)) + { + fprintf(stderr, "%s: supplied rodata_reloc_tab fencepost(s) are out of bounds " "for supplied module %s with length %lu.\n", progname, mod_path, (unsigned long)st.st_size); exit(1); @@ -291,10 +310,15 @@ int main(int argc, char **argv) seg_map.start = (unsigned long)mod_map; seg_map.end = (unsigned long)mod_map + st.st_size; - seg_map.reloc_tab_start += (unsigned long)mod_map; - seg_map.reloc_tab_end += (unsigned long)mod_map; - seg_map.reloc_tab_len_start += (unsigned long)mod_map; - seg_map.reloc_tab_len_end += (unsigned long)mod_map; + seg_map.text_reloc_tab.start += (unsigned long)mod_map; + seg_map.text_reloc_tab.end += (unsigned long)mod_map; + seg_map.text_reloc_tab.len_start += (unsigned long)mod_map; + seg_map.text_reloc_tab.len_end += (unsigned long)mod_map; + + seg_map.rodata_reloc_tab.start += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.end += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.len_start += (unsigned long)mod_map; + seg_map.rodata_reloc_tab.len_end += (unsigned long)mod_map; seg_map.verifyCore_start += (unsigned long)mod_map; seg_map.verifyCore_end += (unsigned long)mod_map; diff --git a/linuxkm/linuxkm_memory.c b/linuxkm/linuxkm_memory.c index 3448cc6de8..27814207e6 100644 --- a/linuxkm/linuxkm_memory.c +++ b/linuxkm/linuxkm_memory.c @@ -74,44 +74,41 @@ static const struct reloc_layout_ent { }; static inline long find_reloc_tab_offset( - const struct wc_reloc_table_segments *seg_map, const struct wc_reloc_table_ent reloc_tab[], word32 reloc_tab_len, - size_t text_in_offset) + size_t seg_in_offset) { long ret; unsigned long hop; - if (reloc_tab_len <= 1) { - RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__); - return -1; - } - if (text_in_offset >= (size_t)(seg_map->text_end - seg_map->text_start)) { + + if (seg_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) { RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__); - return -1; + return BAD_FUNC_ARG; } - if (text_in_offset >= (size_t)reloc_tab[reloc_tab_len - 1].offset) { - RELOC_DEBUG_PRINTF("ERROR: %s failed.\n", __FUNCTION__); - return -1; + + if (reloc_tab_len <= 1) { + /* empty relocation table. */ + return 0; } for (ret = 0, hop = reloc_tab_len >> 1; hop; hop >>= 1) { - if (text_in_offset == (size_t)reloc_tab[ret].offset) + if (seg_in_offset == (size_t)reloc_tab[ret].offset) break; - else if (text_in_offset > (size_t)reloc_tab[ret].offset) + else if (seg_in_offset > (size_t)reloc_tab[ret].offset) ret += hop; else if (ret) ret -= hop; } while ((ret < (long)reloc_tab_len - 1) && - ((size_t)reloc_tab[ret].offset < text_in_offset)) + ((size_t)reloc_tab[ret].offset < seg_in_offset)) ++ret; while ((ret > 0) && - ((size_t)reloc_tab[ret - 1].offset >= text_in_offset)) + ((size_t)reloc_tab[ret - 1].offset >= seg_in_offset)) --ret; #ifdef DEBUG_LINUXKM_PIE_SUPPORT @@ -128,35 +125,65 @@ static inline long find_reloc_tab_offset( #define wc_get_unaligned(v) ({ typeof(*(v)) _v_aligned; XMEMCPY((void *)&_v_aligned, (void *)(v), sizeof _v_aligned); _v_aligned; }) #define wc_put_unaligned(v, v_out) do { typeof(v) _v = (v); XMEMCPY((void *)(v_out), (void *)&_v, sizeof(typeof(*(v_out)))); } while (0) -ssize_t wc_reloc_normalize_text( - const byte *text_in, - size_t text_in_len, - byte *text_out, +ssize_t wc_reloc_normalize_segment( + const byte *seg_in, + size_t *seg_in_out_len, + byte *seg_out, ssize_t *cur_index_p, const struct wc_reloc_table_segments *seg_map, struct wc_reloc_counts *reloc_counts) { ssize_t i; - size_t text_in_offset; + size_t seg_in_offset; const struct wc_reloc_table_ent *last_reloc; /* for error-checking order in reloc_tab[] */ int n_text_r = 0, n_rodata_r = 0, n_rwdata_r = 0, n_bss_r = 0, n_other_r = 0, n_oob_r = 0; - const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->reloc_tab_start; - const word32 reloc_tab_len = *(const word32 *)seg_map->reloc_tab_len_start; + const struct wc_reloc_table_ent *reloc_tab; + word32 reloc_tab_len; + uintptr_t src_seg_start; +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + uintptr_t src_seg_end; + const char *src_seg_name; +#endif + + if (*seg_in_out_len == 0) + return BAD_FUNC_ARG; - if ((text_in_len == 0) || - ((uintptr_t)text_in < seg_map->text_start) || - ((uintptr_t)(text_in + text_in_len) > seg_map->text_end)) + if (((uintptr_t)seg_in >= seg_map->text_start) && + ((uintptr_t)(seg_in + *seg_in_out_len) <= seg_map->text_end)) { - RELOC_DEBUG_PRINTF("ERROR: %s returning -1 with span %llx-%llx versus segment %llx-%llx.\n", + reloc_tab = (const struct wc_reloc_table_ent *)seg_map->text_reloc_tab.start; + reloc_tab_len = *(const word32 *)seg_map->text_reloc_tab.len_start; + src_seg_start = seg_map->text_start; +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + src_seg_end = seg_map->text_end; + src_seg_name = "text"; +#endif + } + else if (((uintptr_t)seg_in >= seg_map->rodata_start) && + ((uintptr_t)(seg_in + *seg_in_out_len) <= seg_map->rodata_end)) + { + reloc_tab = (const struct wc_reloc_table_ent *)seg_map->rodata_reloc_tab.start; + reloc_tab_len = *(const word32 *)seg_map->rodata_reloc_tab.len_start; + src_seg_start = seg_map->rodata_start; +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + src_seg_end = seg_map->rodata_end; + src_seg_name = "rodata"; +#endif + } + else + { + RELOC_DEBUG_PRINTF("ERROR: %s returning BAD_FUNC_ARG with span %llx-%llx versus text %llx-%llx and rodata %llx-%llx.\n", __FUNCTION__, - (unsigned long long)(uintptr_t)text_in, - (unsigned long long)(uintptr_t)(text_in + text_in_len), + (unsigned long long)(uintptr_t)seg_in, + (unsigned long long)(uintptr_t)(seg_in + *seg_in_out_len), (unsigned long long)seg_map->text_start, - (unsigned long long)seg_map->text_end); - return -1; + (unsigned long long)seg_map->text_end, + (unsigned long long)seg_map->rodata_start, + (unsigned long long)seg_map->rodata_end); + return BAD_FUNC_ARG; } - text_in_offset = (uintptr_t)text_in - seg_map->text_start; + seg_in_offset = (uintptr_t)seg_in - src_seg_start; if (cur_index_p) i = *cur_index_p; @@ -164,25 +191,28 @@ ssize_t wc_reloc_normalize_text( i = -1; if (i == -1) - i = find_reloc_tab_offset(seg_map, reloc_tab, reloc_tab_len, text_in_offset); + i = find_reloc_tab_offset(reloc_tab, reloc_tab_len, seg_in_offset); if (i < 0) return i; WC_SANITIZE_DISABLE(); - memcpy(text_out, text_in, text_in_len); + memcpy(seg_out, seg_in, *seg_in_out_len); WC_SANITIZE_ENABLE(); + /* note, if there are no relocations in the src seg, the loop isn't entered + * at all, and we return without further ado. + */ for (last_reloc = &reloc_tab[i > 0 ? i-1 : 0]; (size_t)i < reloc_tab_len - 1; ++i) { const struct wc_reloc_table_ent *next_reloc = &reloc_tab[i]; enum wc_reloc_dest_segment dest_seg; - uintptr_t seg_beg; + uintptr_t dest_seg_start; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - uintptr_t seg_end; - const char *seg_name; + uintptr_t dest_seg_end; + const char *dest_seg_name; #endif word64 reloc_buf = 0; const struct reloc_layout_ent *layout; @@ -196,7 +226,7 @@ ssize_t wc_reloc_normalize_text( if (last_reloc->offset > next_reloc->offset) { RELOC_DEBUG_PRINTF("BUG: out-of-order offset found at reloc_tab[%zd]: %u > %u\n", i, last_reloc->offset, next_reloc->offset); - return -1; + return BAD_FUNC_ARG; } last_reloc = next_reloc; @@ -204,7 +234,7 @@ ssize_t wc_reloc_normalize_text( if (next_reloc->reloc_type >= (sizeof reloc_layouts / sizeof reloc_layouts[0])) { RELOC_DEBUG_PRINTF("BUG: unknown relocation type %u found at reloc_tab[%zd]\n", next_reloc->reloc_type, i); - return -1; + return BAD_FUNC_ARG; } layout = &reloc_layouts[next_reloc->reloc_type]; @@ -217,7 +247,7 @@ ssize_t wc_reloc_normalize_text( default: RELOC_DEBUG_PRINTF("BUG: unexpected relocation width %llu found at reloc_tab[%lld], reloc type %u\n", (unsigned long long)layout->width, (long long)i, next_reloc->reloc_type); - return -1; + return BAD_FUNC_ARG; } /* provisionally assign the destination segment from the reloc record -- @@ -227,23 +257,23 @@ ssize_t wc_reloc_normalize_text( dest_seg = next_reloc->dest_segment; /* next_reloc_rel is the offset of the relocation relative to the start - * of the current text chunk (text_in). i.e., text_in + next_reloc_rel + * of the current text chunk (seg_in). i.e., seg_in + next_reloc_rel * is the start of the relocation. */ - next_reloc_rel = next_reloc->offset - text_in_offset; + next_reloc_rel = next_reloc->offset - seg_in_offset; - if (next_reloc_rel >= text_in_len) { + if (next_reloc_rel >= *seg_in_out_len) { /* no more relocations in this buffer. */ break; } - if ((text_in_len < WC_BITS_TO_BYTES(layout->width)) || - (next_reloc_rel > text_in_len - WC_BITS_TO_BYTES(layout->width))) + if ((*seg_in_out_len < WC_BITS_TO_BYTES(layout->width)) || + (next_reloc_rel > *seg_in_out_len - WC_BITS_TO_BYTES(layout->width))) { /* relocation straddles buffer at end -- caller will try again with * that relocation at the start. */ - text_in_len = next_reloc_rel; + *seg_in_out_len = next_reloc_rel; break; } @@ -257,61 +287,61 @@ ssize_t wc_reloc_normalize_text( */ switch (layout->width) { case 32: - reloc_buf = (word64)(sword64)(wc_get_unaligned((sword32 *)&text_out[next_reloc_rel]) & (sword32)layout->mask); + reloc_buf = (word64)(sword64)(wc_get_unaligned((sword32 *)&seg_out[next_reloc_rel]) & (sword32)layout->mask); break; case 64: - reloc_buf = (word64)(sword64)(wc_get_unaligned((sword64 *)&text_out[next_reloc_rel]) & (sword64)layout->mask); + reloc_buf = (word64)(sword64)(wc_get_unaligned((sword64 *)&seg_out[next_reloc_rel]) & (sword64)layout->mask); break; case 16: - reloc_buf = (word64)(sword64)(wc_get_unaligned((sword16 *)&text_out[next_reloc_rel]) & (sword16)layout->mask); + reloc_buf = (word64)(sword64)(wc_get_unaligned((sword16 *)&seg_out[next_reloc_rel]) & (sword16)layout->mask); break; } } else { switch (layout->width) { case 32: - reloc_buf = (word64)(wc_get_unaligned((word32 *)&text_out[next_reloc_rel]) & (word32)layout->mask); + reloc_buf = (word64)(wc_get_unaligned((word32 *)&seg_out[next_reloc_rel]) & (word32)layout->mask); break; case 64: - reloc_buf = (word64)(wc_get_unaligned((word64 *)&text_out[next_reloc_rel]) & layout->mask); + reloc_buf = (word64)(wc_get_unaligned((word64 *)&seg_out[next_reloc_rel]) & layout->mask); break; case 16: - reloc_buf = (word64)(wc_get_unaligned((word16 *)&text_out[next_reloc_rel]) & (word16)layout->mask); + reloc_buf = (word64)(wc_get_unaligned((word16 *)&seg_out[next_reloc_rel]) & (word16)layout->mask); break; } } switch (dest_seg) { case WC_R_SEG_TEXT: - seg_beg = seg_map->text_start; + dest_seg_start = seg_map->text_start; ++n_text_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->text_end; - seg_name = "text"; + dest_seg_end = seg_map->text_end; + dest_seg_name = "text"; #endif break; case WC_R_SEG_RODATA: - seg_beg = seg_map->rodata_start; + dest_seg_start = seg_map->rodata_start; ++n_rodata_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->rodata_end; - seg_name = "rodata"; + dest_seg_end = seg_map->rodata_end; + dest_seg_name = "rodata"; #endif break; case WC_R_SEG_RWDATA: - seg_beg = seg_map->data_start; + dest_seg_start = seg_map->data_start; ++n_rwdata_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->data_end; - seg_name = "data"; + dest_seg_end = seg_map->data_end; + dest_seg_name = "data"; #endif break; case WC_R_SEG_BSS: - seg_beg = seg_map->bss_start; + dest_seg_start = seg_map->bss_start; ++n_bss_r; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = seg_map->bss_end; - seg_name = "bss"; + dest_seg_end = seg_map->bss_end; + dest_seg_name = "bss"; #endif break; default: @@ -319,10 +349,10 @@ ssize_t wc_reloc_normalize_text( dest_seg = WC_R_SEG_OTHER; FALL_THROUGH; case WC_R_SEG_OTHER: - seg_beg = 0; + dest_seg_start = 0; #ifdef DEBUG_LINUXKM_PIE_SUPPORT - seg_end = 0; - seg_name = "other"; + dest_seg_end = 0; + dest_seg_name = "other"; #endif break; } @@ -344,33 +374,35 @@ ssize_t wc_reloc_normalize_text( * baked into the reloc_tab for each relocation. */ if (layout->is_relative) - reloc_buf = reloc_buf + (uintptr_t)next_reloc->offset - (uintptr_t)next_reloc->dest_addend - (seg_beg - seg_map->text_start); + reloc_buf = reloc_buf + (uintptr_t)next_reloc->offset - (uintptr_t)next_reloc->dest_addend - (dest_seg_start - src_seg_start); else - reloc_buf = reloc_buf - seg_beg - (uintptr_t)next_reloc->dest_addend; + reloc_buf = reloc_buf - dest_seg_start - (uintptr_t)next_reloc->dest_addend; } else { reloc_buf = (word64)next_reloc->dest_offset; } #ifdef DEBUG_LINUXKM_PIE_SUPPORT - if (reloc_buf >= seg_end - seg_beg) { + if (reloc_buf >= dest_seg_end - dest_seg_start) { ++n_oob_r; - RELOC_DEBUG_PRINTF("WARNING: normalized value is out of bounds (%s0x%llx) at index %lld, text offset 0x%x, reloc type %s, " - "dest seg .%s_wolfcrypt, offset from text to dest segment %s0x%llx, raw dest addr %s0x%llx, " - "seg span 0x%llx - 0x%llx, seg size 0x%llx, text base 0x%llx\n", + RELOC_DEBUG_PRINTF("WARNING: normalized value is out of bounds (%s0x%llx) at index %lld, %s offset 0x%x, reloc type %s, " + "src seg .%s_wolfcrypt, dest seg .%s_wolfcrypt, offset from src to dest segment %s0x%llx, raw dest addr %s0x%llx, " + "seg span 0x%llx - 0x%llx, seg size 0x%llx, src seg 0x%llx-0x%llx\n", (long long)reloc_buf < 0 ? "-" : "", (long long)reloc_buf < 0 ? -(long long)reloc_buf : (long long)reloc_buf, (long long)i, + src_seg_name, next_reloc->offset, layout->name, - seg_name, - seg_beg < seg_map->text_start ? "-" : "+", - seg_beg < seg_map->text_start ? (unsigned long long)seg_map->text_start - seg_beg : seg_beg - (unsigned long long)seg_map->text_start, + src_seg_name, + dest_seg_name, + dest_seg_start < src_seg_start ? "-" : "+", + dest_seg_start < src_seg_start ? (unsigned long long)src_seg_start - dest_seg_start : dest_seg_start - (unsigned long long)src_seg_start, (layout->is_signed && ((long long)raw_dest_addr < 0)) ? "-" : "", (layout->is_signed && ((long long)raw_dest_addr < 0)) ? (unsigned long long)-(long long)raw_dest_addr : raw_dest_addr, - (unsigned long long)seg_beg, - (unsigned long long)seg_end, - (unsigned long long)(seg_end - seg_beg), - (unsigned long long)seg_map->text_start); + (unsigned long long)dest_seg_start, + (unsigned long long)dest_seg_end, + (unsigned long long)(dest_seg_end - dest_seg_start), + (unsigned long long)src_seg_start, (unsigned long long)src_seg_end); } #endif } @@ -414,8 +446,8 @@ ssize_t wc_reloc_normalize_text( break; default: - RELOC_DEBUG_PRINTF("BUG: unrecognized relocation type %u in reloc record %zu, text offset 0x%x\n", - (unsigned)next_reloc->reloc_type, i, reloc_tab[i].offset); + RELOC_DEBUG_PRINTF("BUG: unrecognized relocation type %u in reloc record %zu, %s offset 0x%x\n", + (unsigned)next_reloc->reloc_type, i, src_seg_name, reloc_tab[i].offset); ++n_oob_r; dest_seg = WC_R_SEG_OTHER; } @@ -427,8 +459,8 @@ ssize_t wc_reloc_normalize_text( reloc_buf = 0; ++n_other_r; - RELOC_DEBUG_PRINTF("found non-wolfcrypt relocation at index %lld, text offset 0x%x.\n", - (long long)i, reloc_tab[i].offset); + RELOC_DEBUG_PRINTF("found non-wolfcrypt relocation at index %lld, %s offset 0x%x.\n", + (long long)i, src_seg_name, reloc_tab[i].offset); } /* xor in a label identifying the dest segment and reloc type. */ @@ -438,13 +470,13 @@ ssize_t wc_reloc_normalize_text( /* write the modified reloc_buf to the destination buffer. */ switch (layout->width) { case 32: - wc_put_unaligned((word32)reloc_buf, (word32 *)&text_out[next_reloc_rel]); + wc_put_unaligned((word32)reloc_buf, (word32 *)&seg_out[next_reloc_rel]); break; case 64: - wc_put_unaligned(reloc_buf, (word64 *)&text_out[next_reloc_rel]); + wc_put_unaligned(reloc_buf, (word64 *)&seg_out[next_reloc_rel]); break; case 16: - wc_put_unaligned((word16)reloc_buf, (word16 *)&text_out[next_reloc_rel]); + wc_put_unaligned((word16)reloc_buf, (word16 *)&seg_out[next_reloc_rel]); break; } } @@ -458,15 +490,15 @@ ssize_t wc_reloc_normalize_text( } if ((n_other_r > 0) || (n_oob_r > 0)) - RELOC_DEBUG_PRINTF("text_in=%llx relocs=%d/%d/%d/%d/%d/%d ret = %llu\n", - (unsigned long long)(uintptr_t)text_in, n_text_r, n_rodata_r, + RELOC_DEBUG_PRINTF("seg_in=%llx relocs=%d/%d/%d/%d/%d/%d ret = %llu\n", + (unsigned long long)(uintptr_t)seg_in, n_text_r, n_rodata_r, n_rwdata_r, n_bss_r, n_other_r, n_oob_r, - (unsigned long long)text_in_len); + (unsigned long long)*seg_in_out_len); if (cur_index_p) *cur_index_p = i; - return (ssize_t)text_in_len; + return (ssize_t)*seg_in_out_len; } #endif /* WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT */ @@ -553,16 +585,28 @@ int wc_fips_generate_hash( #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) if (seg_map->text_is_live) { - if ((seg_map->reloc_tab_start == 0) || - (seg_map->reloc_tab_len_start == 0)) + if ((seg_map->text_reloc_tab.start == 0) || + (seg_map->text_reloc_tab.len_start == 0)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + if ((seg_map->rodata_reloc_tab.start == 0) || + (seg_map->rodata_reloc_tab.len_start == 0)) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } } else { - if ((seg_map->reloc_tab_end == 0) || - (seg_map->reloc_tab_len_end == 0)) + if ((seg_map->text_reloc_tab.end == 0) || + (seg_map->text_reloc_tab.len_end == 0)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + if ((seg_map->rodata_reloc_tab.end == 0) || + (seg_map->rodata_reloc_tab.len_end == 0)) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; @@ -575,8 +619,10 @@ int wc_fips_generate_hash( (seg_map->fips_rodata_start >= seg_map->fips_rodata_end) #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) || - ((seg_map->reloc_tab_end != 0) && (seg_map->reloc_tab_start >= seg_map->reloc_tab_end)) || - ((seg_map->reloc_tab_len_end != 0) && (seg_map->reloc_tab_len_start >= seg_map->reloc_tab_len_end)) || + ((seg_map->text_reloc_tab.end != 0) && (seg_map->text_reloc_tab.start >= seg_map->text_reloc_tab.end)) || + ((seg_map->text_reloc_tab.len_end != 0) && (seg_map->text_reloc_tab.len_start >= seg_map->text_reloc_tab.len_end)) || + ((seg_map->rodata_reloc_tab.end != 0) && (seg_map->rodata_reloc_tab.start >= seg_map->rodata_reloc_tab.end)) || + ((seg_map->rodata_reloc_tab.len_end != 0) && (seg_map->rodata_reloc_tab.len_start >= seg_map->rodata_reloc_tab.len_end)) || (seg_map->text_start >= seg_map->text_end) || (seg_map->rodata_start >= seg_map->rodata_end) || (seg_map->data_start >= seg_map->data_end) || @@ -594,8 +640,10 @@ int wc_fips_generate_hash( (seg_map->verifyCore_start < seg_map->start) #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) || - (seg_map->reloc_tab_start < seg_map->start) || - (seg_map->reloc_tab_len_start < seg_map->start) || + (seg_map->text_reloc_tab.start < seg_map->start) || + (seg_map->text_reloc_tab.len_start < seg_map->start) || + (seg_map->rodata_reloc_tab.start < seg_map->start) || + (seg_map->rodata_reloc_tab.len_start < seg_map->start) || (seg_map->text_start < seg_map->start) || (seg_map->rodata_start < seg_map->start) || (seg_map->data_start < seg_map->start) || @@ -614,10 +662,14 @@ int wc_fips_generate_hash( (seg_map->verifyCore_end > seg_map->end) #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) || - ((seg_map->reloc_tab_end != 0) && - (seg_map->reloc_tab_end > seg_map->end)) || - ((seg_map->reloc_tab_len_end != 0) && - (seg_map->reloc_tab_len_end > seg_map->end)) || + ((seg_map->text_reloc_tab.end != 0) && + (seg_map->text_reloc_tab.end > seg_map->end)) || + ((seg_map->text_reloc_tab.len_end != 0) && + (seg_map->text_reloc_tab.len_end > seg_map->end)) || + ((seg_map->rodata_reloc_tab.end != 0) && + (seg_map->rodata_reloc_tab.end > seg_map->end)) || + ((seg_map->rodata_reloc_tab.len_end != 0) && + (seg_map->rodata_reloc_tab.len_end > seg_map->end)) || (seg_map->text_end > seg_map->end) || (seg_map->rodata_end > seg_map->end) || (seg_map->data_end > seg_map->end) || @@ -631,15 +683,15 @@ int wc_fips_generate_hash( } #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) - if ((seg_map->reloc_tab_len_end != 0) && - (seg_map->reloc_tab_len_end - seg_map->reloc_tab_len_start != sizeof(word32))) + if ((seg_map->text_reloc_tab.len_end != 0) && + (seg_map->text_reloc_tab.len_end - seg_map->text_reloc_tab.len_start != sizeof(word32))) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } - else if (seg_map->reloc_tab_len_start & (sizeof(word32) - 1)) { - /* fprintf(stderr, "%s: seg_map->reloc_tab_len_start isn't properly aligned: 0x%llx.\n", progname, ( - unsigned long long)seg_map->reloc_tab_len_start); */ + else if (seg_map->text_reloc_tab.len_start & (sizeof(word32) - 1)) { + /* fprintf(stderr, "%s: seg_map->text_reloc_tab.len_start isn't properly aligned: 0x%llx.\n", progname, ( + unsigned long long)seg_map->text_reloc_tab.len_start); */ RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_ALIGN_E; } @@ -649,8 +701,8 @@ int wc_fips_generate_hash( * a nonsense byte-swapped value, or the final reloc_tab ent has * nonsense flags. */ - word32 reloc_tab_len = *(const word32 *)seg_map->reloc_tab_len_start; - const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->reloc_tab_start; + word32 reloc_tab_len = *(const word32 *)seg_map->text_reloc_tab.len_start; + const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->text_reloc_tab.start; if (reloc_tab_len == 0) { RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; @@ -667,14 +719,64 @@ int wc_fips_generate_hash( RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; } - else if ((seg_map->reloc_tab_end != 0) && - (seg_map->reloc_tab_end - seg_map->reloc_tab_start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->reloc_tab_len_start)) + else if ((seg_map->text_reloc_tab.end != 0) && + (seg_map->text_reloc_tab.end - seg_map->text_reloc_tab.start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->text_reloc_tab.len_start)) { /* - fprintf(stderr, "%s: wc_linuxkm_pie_reloc_tab_length from module (%u) is inconsistent with actual reloc_tab size %llu.\n", + fprintf(stderr, "%s: wc_linuxkm_pie_text_reloc_tab_length from module (%u) is inconsistent with actual text_reloc_tab size %llu.\n", progname, - *(const word32 *)seg_map->reloc_tab_len_start, - (unsigned long long)(seg_map->reloc_tab_end - seg_map->reloc_tab_start)); + *(const word32 *)seg_map->text_reloc_tab.len_start, + (unsigned long long)(seg_map->text_reloc_tab.end - seg_map->text_reloc_tab.start)); + */ + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + } + + if ((seg_map->rodata_reloc_tab.len_end != 0) && + (seg_map->rodata_reloc_tab.len_end - seg_map->rodata_reloc_tab.len_start != sizeof(word32))) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if (seg_map->rodata_reloc_tab.len_start & (sizeof(word32) - 1)) { + /* fprintf(stderr, "%s: seg_map->rodata_reloc_tab.len_start isn't properly aligned: 0x%llx.\n", progname, ( + unsigned long long)seg_map->rodata_reloc_tab.len_start); */ + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_ALIGN_E; + } + else { + /* Note we don't currently handle modules that are endian-conflicted + * with the build host -- that'll be caught here, when reloc_tab_len is + * a nonsense byte-swapped value, or the final reloc_tab ent has + * nonsense flags. + */ + word32 reloc_tab_len = *(const word32 *)seg_map->rodata_reloc_tab.len_start; + const struct wc_reloc_table_ent *reloc_tab = (const struct wc_reloc_table_ent *)seg_map->rodata_reloc_tab.start; + if (reloc_tab_len == 0) { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if ((seg_map->end != 0) && + ((unsigned long)(reloc_tab + reloc_tab_len) > seg_map->end)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if ((reloc_tab[reloc_tab_len - 1].dest_segment != WC_R_SEG_NONE) || + (reloc_tab[reloc_tab_len - 1].reloc_type != WC_R_NONE)) + { + RELOC_DEBUG_PRINTF("assert failed.\n"); + return BAD_FUNC_ARG; + } + else if ((seg_map->rodata_reloc_tab.end != 0) && + (seg_map->rodata_reloc_tab.end - seg_map->rodata_reloc_tab.start != sizeof(struct wc_reloc_table_ent) * *(const word32 *)seg_map->rodata_reloc_tab.len_start)) + { + /* + fprintf(stderr, "%s: wc_linuxkm_pie_rodata_reloc_tab_length from module (%u) is inconsistent with actual rodata_reloc_tab size %llu.\n", + progname, + *(const word32 *)seg_map->rodata_reloc_tab.len_start, + (unsigned long long)(seg_map->rodata_reloc_tab.end - seg_map->rodata_reloc_tab.start)); */ RELOC_DEBUG_PRINTF("assert failed.\n"); return BAD_FUNC_ARG; @@ -728,9 +830,10 @@ int wc_fips_generate_hash( #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) { - ssize_t cur_reloc_index = -1; + ssize_t cur_reloc_index; const byte *text_p = (const byte *)seg_map->fips_text_start; - byte *buf = XMALLOC(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + const byte *rodata_p = (const byte *)seg_map->fips_rodata_start; + byte *buf = XMALLOC(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (! buf) { ret = MEMORY_E; @@ -738,23 +841,23 @@ int wc_fips_generate_hash( goto out; } + cur_reloc_index = -1; while (text_p < (const byte *)seg_map->fips_text_end) { - /* wc_reloc_normalize_text() does its own WC_SANITIZE_DISABLE()s, so - * we defer it here. - */ - ssize_t progress = wc_reloc_normalize_text( + size_t text_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const byte *)seg_map->fips_text_end - text_p)); + ssize_t progress = wc_reloc_normalize_segment( text_p, - min(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, (word32)((const byte *)seg_map->fips_text_end - text_p)), + &text_in_out_len, buf, &cur_reloc_index, seg_map, reloc_counts); if (progress <= 0) { - ret = IN_CORE_FIPS_E; - RELOC_DEBUG_PRINTF("wc_reloc_normalize_text() failed.\n"); + RELOC_DEBUG_PRINTF("wc_reloc_normalize_segment() for text failed: %zd.\n", progress); + ret = progress ? (int)progress : IN_CORE_FIPS_E; break; } - ret = hmac_update(hmac_ctx, buf, (word32)progress); + ret = hmac_update(hmac_ctx, buf, (word32)text_in_out_len); if (ret) { RELOC_DEBUG_PRINTF("hmac_update() failed.\n"); break; @@ -762,15 +865,61 @@ int wc_fips_generate_hash( text_p += progress; } + if (ret) { + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + goto out; + } + + cur_reloc_index = -1; + while (rodata_p < (const byte *)seg_map->fips_rodata_end) { + size_t rodata_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const byte *)seg_map->fips_rodata_end - rodata_p)); + /* don't hash verifyCore or changing verifyCore will change hash */ + if ((rodata_p < (const byte *)seg_map->verifyCore_end) && + (rodata_p + rodata_in_out_len >= (const byte *)seg_map->verifyCore_start)) + { + rodata_in_out_len = (size_t)((const byte *)seg_map->verifyCore_start - rodata_p); + if (rodata_in_out_len == 0) { + rodata_p = (const byte *)seg_map->verifyCore_end; + /* force recomputation of relocation offset when skipping + * a span (not processed by wc_reloc_normalize_segment()). + */ + cur_reloc_index = -1; + continue; + } + } + + ssize_t progress = wc_reloc_normalize_segment( + rodata_p, + &rodata_in_out_len, + buf, + &cur_reloc_index, + seg_map, + reloc_counts); + if (progress <= 0) { + RELOC_DEBUG_PRINTF("wc_reloc_normalize_segment() for rodata failed: %zd.\n", progress); + ret = progress ? (int)progress : IN_CORE_FIPS_E; + break; + } + ret = hmac_update(hmac_ctx, buf, (word32)rodata_in_out_len); + if (ret) { + RELOC_DEBUG_PRINTF("hmac_update() failed.\n"); + break; + } + rodata_p += progress; + } + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret) + goto out; } - WC_SANITIZE_DISABLE(); -#else +#else /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ + (void)reloc_counts; WC_SANITIZE_DISABLE(); ret = hmac_update(hmac_ctx, (byte *)(wc_ptr_t)seg_map->fips_text_start, (word32)(seg_map->fips_text_end - seg_map->fips_text_start)); -#endif /* !WOLFSSL_LINUXKM_PIE_REDIRECT_TABLE */ if (ret) { RELOC_DEBUG_PRINTF("ERROR: hmac_update failed: err %d\n", ret); @@ -801,6 +950,8 @@ int wc_fips_generate_hash( goto out; } +#endif /* ! (WC_SYM_RELOC_TABLES || WC_SYM_RELOC_TABLES_SUPPORT) */ + ret = hmac_final(hmac_ctx, hash, digest_size); if (ret) { RELOC_DEBUG_PRINTF("ERROR: hmac_final failed: err %d\n", ret); diff --git a/linuxkm/linuxkm_memory.h b/linuxkm/linuxkm_memory.h index 695a82aafa..76e681da80 100644 --- a/linuxkm/linuxkm_memory.h +++ b/linuxkm/linuxkm_memory.h @@ -80,13 +80,25 @@ struct __attribute__((packed)) wc_reloc_table_ent { /* full ELF fencepost representation, to allow wc_reloc_normalize_text() */ +struct wc_reloc_table_fenceposts { + unsigned long start; + unsigned long end; + unsigned long len_start; + unsigned long len_end; +}; + +#define WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER { \ + .start = ~0UL, \ + .end = ~0UL, \ + .len_start = ~0UL, \ + .len_end = ~0UL \ +} + struct wc_reloc_table_segments { unsigned long start; unsigned long end; - unsigned long reloc_tab_start; - unsigned long reloc_tab_end; - unsigned long reloc_tab_len_start; - unsigned long reloc_tab_len_end; + struct wc_reloc_table_fenceposts text_reloc_tab; + struct wc_reloc_table_fenceposts rodata_reloc_tab; unsigned long text_start; unsigned long text_end; #ifdef HAVE_FIPS @@ -113,10 +125,8 @@ struct wc_reloc_table_segments { #define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \ .start = ~0UL, \ .end = ~0UL, \ - .reloc_tab_start = ~0UL, \ - .reloc_tab_end = ~0UL, \ - .reloc_tab_len_start = ~0UL, \ - .reloc_tab_len_end = ~0UL, \ + .text_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ + .rodata_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ .text_start = ~0UL, \ .text_end = ~0UL, \ .fips_text_start = ~0UL, \ @@ -139,10 +149,8 @@ struct wc_reloc_table_segments { #define WC_RELOC_TABLE_SEGMENTS_INITIALIZER { \ .start = ~0UL, \ .end = ~0UL, \ - .reloc_tab_start = ~0UL, \ - .reloc_tab_end = ~0UL, \ - .reloc_tab_len_start = ~0UL, \ - .reloc_tab_len_end = ~0UL, \ + .text_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ + .rodata_reloc_tab = WC_RELOC_TABLE_FENCEPOSTS_INITIALIZER, \ .text_start = ~0UL, \ .text_end = ~0UL, \ .rodata_start = ~0UL, \ @@ -167,7 +175,7 @@ struct wc_reloc_counts { #elif defined(HAVE_FIPS) /* barebones FIPS fencepost representation -- no provision for - * wc_reloc_normalize_text() + * wc_reloc_normalize_segment() */ struct wc_reloc_table_segments { @@ -200,14 +208,18 @@ struct wc_reloc_counts { #if defined(WC_SYM_RELOC_TABLES) || defined(WC_SYM_RELOC_TABLES_SUPPORT) +#ifndef WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ + #define WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ 8192 +#endif + #ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ - #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ 8192 + #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ #endif -WOLFSSL_API ssize_t wc_reloc_normalize_text( - const byte *text_in, - size_t text_in_len, - byte *text_out, +WOLFSSL_API ssize_t wc_reloc_normalize_segment( + const byte *seg_in, + size_t *seg_in_out_len, + byte *seg_out, ssize_t *cur_index_p, const struct wc_reloc_table_segments *seg_map, struct wc_reloc_counts *reloc_counts); diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 22255af456..c359277e34 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -876,15 +876,33 @@ __wc_bss_end[]; extern ssize_t wc_linuxkm_normalize_relocations( - const u8 *text_in, - size_t text_in_len, - u8 *text_out, + const u8 *seg_in, + size_t *seg_in_out_len, + u8 *seg_out, ssize_t *cur_index_p); + extern ssize_t wc_linuxkm_normalize_relocations_noresize( + const u8 *seg_in, + size_t seg_in_len, + u8 *seg_out, + ssize_t *cur_index_p); + + #ifndef WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ + #define WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ 8192 + #endif + + #ifndef WOLFSSL_SEGMENT_CANONICALIZER + #define WOLFSSL_SEGMENT_CANONICALIZER(seg_in, seg_in_out_len, seg_out, cur_index_p) \ + wc_linuxkm_normalize_relocations(seg_in, seg_in_out_len, seg_out, cur_index_p) + #endif + + /* backward-compatible wrappers */ #ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER(text_in, text_in_len, text_out, cur_index_p) \ - wc_linuxkm_normalize_relocations(text_in, text_in_len, text_out, cur_index_p) - #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ 8192 + wc_linuxkm_normalize_relocations_noresize(text_in, text_in_len, text_out, cur_index_p) + #endif + #ifndef WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ + #define WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ #endif #ifdef CONFIG_MIPS @@ -896,6 +914,7 @@ struct wolfssl_linuxkm_pie_redirect_table { #ifdef HAVE_FIPS typeof(wc_linuxkm_normalize_relocations) *wc_linuxkm_normalize_relocations; + typeof(wc_linuxkm_normalize_relocations_noresize) *wc_linuxkm_normalize_relocations_noresize; #endif #ifndef __ARCH_MEMCMP_NO_REDIRECT @@ -1234,6 +1253,8 @@ #ifdef HAVE_FIPS #define wc_linuxkm_normalize_relocations \ WC_PIE_INDIRECT_SYM(wc_linuxkm_normalize_relocations) + #define wc_linuxkm_normalize_relocations_noresize \ + WC_PIE_INDIRECT_SYM(wc_linuxkm_normalize_relocations_noresize) #endif #ifndef __ARCH_MEMCMP_NO_REDIRECT diff --git a/linuxkm/lkcapi_dh_glue.c b/linuxkm/lkcapi_dh_glue.c index 9e885ed856..6caabf06ac 100644 --- a/linuxkm/lkcapi_dh_glue.c +++ b/linuxkm/lkcapi_dh_glue.c @@ -347,7 +347,7 @@ static int km_dh_decode_secret(const u8 * buf, unsigned int len, if (secret.len != expected_len) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: km_dh_decode_secret: got %d, expected %zu", + pr_err("%s: km_dh_decode_secret: got %d, expected %zu\n", WOLFKM_DH_DRIVER, secret.len, expected_len); #endif /* WOLFKM_DEBUG_DH */ return -EINVAL; @@ -413,7 +413,7 @@ static int km_dh_alloc_keys(struct km_dh_ctx * ctx) alloc_keys_end: if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: km_dh_alloc_keys failed: %d", + pr_err("%s: km_dh_alloc_keys failed: %d\n", WOLFKM_DH_DRIVER, err); #endif km_dh_clear_keys(ctx); @@ -478,7 +478,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (km_dh_decode_secret(buf, len, ¶ms) < 0) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: dh_set_secret: decode secret failed: %d", + pr_err("%s: dh_set_secret: decode secret failed: %d\n", WOLFKM_DH_DRIVER, params.key_size); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -488,7 +488,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, /* the key, p, and g, must all be provided for normal dh. */ if (!params.key || !params.key_size || !params.p_size || !params.g_size) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: dh_set_secret: empty params", WOLFKM_DH_DRIVER); + pr_err("%s: dh_set_secret: empty params\n", WOLFKM_DH_DRIVER); #endif err = -EINVAL; goto dh_secret_end; @@ -496,7 +496,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (params.key_size > params.p_size || params.g_size > params.p_size) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: dh_set_secret: invalid params", WOLFKM_DH_DRIVER); + pr_err("%s: dh_set_secret: invalid params\n", WOLFKM_DH_DRIVER); #endif err = -EINVAL; goto dh_secret_end; @@ -518,7 +518,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhSetKey failed: %d", WOLFKM_DH_DRIVER, err); + pr_err("%s: wc_DhSetKey failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; goto dh_secret_end; @@ -530,7 +530,7 @@ static int km_dh_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhImportKeyPair failed: %d", WOLFKM_DH_DRIVER, err); + pr_err("%s: wc_DhImportKeyPair failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; goto dh_secret_end; @@ -585,7 +585,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: ffdhe_set_secret: decode secret failed: %d", + pr_err("%s: ffdhe_set_secret: decode secret failed: %d\n", WOLFKM_DH_DRIVER, params.key_size); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -595,7 +595,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, /* p_size and g_size should be 0 for ffdhe. */ if (params.p_size || params.g_size) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: ffdhe_set_secret: unexpected p, g params: %d, %d", + pr_err("%s: ffdhe_set_secret: unexpected p, g params: %d, %d\n", WOLFKM_DH_DRIVER, params.p_size, params.g_size); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -616,7 +616,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (!params.key_size) { /* generate the ffdhe key pair*/ #ifdef WOLFKM_DEBUG_DH - pr_info("ffdhe gen key pair"); + pr_info("ffdhe gen key pair\n"); #endif PRIVATE_KEY_UNLOCK(); err = wc_DhGenerateKeyPair(ctx->key, &ctx->rng, @@ -626,7 +626,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhGenerateKeyPair failed: %d", + pr_err("%s: wc_DhGenerateKeyPair failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; @@ -641,7 +641,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (ctx->pub_len < (ctx->nbits / WOLFSSL_BIT_SIZE)) { word32 pad_len = ctx->nbits / WOLFSSL_BIT_SIZE - ctx->pub_len; #ifdef WOLFKM_DEBUG_DH - pr_info("info: km_ffdhe_set_secret: pub key padding %d", pad_len); + pr_info("info: km_ffdhe_set_secret: pub key padding %d\n", pad_len); #endif memmove(ctx->pub_key + pad_len, ctx->pub_key, ctx->pub_len); @@ -660,7 +660,7 @@ static int km_ffdhe_set_secret(struct crypto_kpp *tfm, const void *buf, if (err) { #ifdef WOLFKM_DEBUG_DH - pr_err("%s: wc_DhImportKeyPair failed: %d", + pr_err("%s: wc_DhImportKeyPair failed: %d\n", WOLFKM_DH_DRIVER, err); #endif err = -EINVAL; @@ -783,7 +783,7 @@ static int km_ffdhe_init(struct crypto_kpp *tfm, int name, word32 nbits) } #ifdef WOLFKM_DEBUG_DH - pr_info("info: exiting km_dh_init: name %d, nbits %d", + pr_info("info: exiting km_dh_init: name %d, nbits %d\n", ctx->name, ctx->nbits); #endif /* WOLFKM_DEBUG_DH */ return 0; @@ -874,7 +874,7 @@ static int km_dh_gen_pub(struct kpp_request *req) if (ctx->pub_len > req->dst_len) { #ifdef WOLFKM_DEBUG_DH - pr_err("error: dst_len too small: %d", req->dst_len); + pr_err("error: dst_len too small: %d\n", req->dst_len); #endif /* WOLFKM_DEBUG_DH */ req->dst_len = ctx->pub_len; return -EOVERFLOW; @@ -885,7 +885,7 @@ static int km_dh_gen_pub(struct kpp_request *req) err = 0; #ifdef WOLFKM_DEBUG_DH - pr_info("info: exiting km_dh_gen_pub: %d", ctx->pub_len); + pr_info("info: exiting km_dh_gen_pub: %d\n", ctx->pub_len); #endif /* WOLFKM_DEBUG_DH */ return err; } @@ -921,7 +921,7 @@ static int km_dh_compute_shared_secret(struct kpp_request *req) if (req->src_len <= 0 || req->src_len > (ctx->nbits / WOLFSSL_BIT_SIZE)) { #ifdef WOLFKM_DEBUG_DH - pr_err("error: got src_len %d, expected %d", req->src_len, + pr_err("error: got src_len %d, expected %d\n", req->src_len, (ctx->nbits / WOLFSSL_BIT_SIZE)); #endif /* WOLFKM_DEBUG_DH */ err = -EINVAL; @@ -2903,7 +2903,7 @@ static int linuxkm_test_kpp_driver(const char * driver, dst_buf = malloc(dst_len); if (dst_buf == NULL) { - pr_err("error: allocating out buf failed"); + pr_err("error: allocating out buf failed\n"); test_rc = MEMORY_E; goto test_kpp_end; } @@ -2917,20 +2917,20 @@ static int linuxkm_test_kpp_driver(const char * driver, err = crypto_kpp_generate_public_key(req); if (err) { - pr_err("error: crypto_kpp_generate_public_key returned: %d", err); + pr_err("error: crypto_kpp_generate_public_key returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_kpp_end; } if (memcmp(expected_a_pub, sg_virt(req->dst), pub_len)) { - pr_err("error: crypto_kpp_generate_public_key: wrong output"); + pr_err("error: crypto_kpp_generate_public_key: wrong output\n"); test_rc = WC_KEY_MISMATCH_E; goto test_kpp_end; } src_buf = malloc(src_len); if (src_buf == NULL) { - pr_err("error: allocating in buf failed"); + pr_err("error: allocating in buf failed\n"); test_rc = MEMORY_E; goto test_kpp_end; } @@ -2945,13 +2945,13 @@ static int linuxkm_test_kpp_driver(const char * driver, err = crypto_kpp_compute_shared_secret(req); if (err) { - pr_err("error: crypto_kpp_compute_shared_secret returned: %d", err); + pr_err("error: crypto_kpp_compute_shared_secret returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_kpp_end; } if (memcmp(shared_secret, sg_virt(req->dst), shared_s_len)) { - pr_err("error: shared secret does not match"); + pr_err("error: shared secret does not match\n"); test_rc = BAD_FUNC_ARG; goto test_kpp_end; } diff --git a/linuxkm/lkcapi_ecdh_glue.c b/linuxkm/lkcapi_ecdh_glue.c index 86cef12ee3..2f88bd2037 100644 --- a/linuxkm/lkcapi_ecdh_glue.c +++ b/linuxkm/lkcapi_ecdh_glue.c @@ -199,7 +199,7 @@ static int km_ecdh_decode_secret(const u8 * buf, unsigned int len, if (secret.len != expected_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("%s: km_ecdh_decode_secret: got %d, expected %zu", + pr_err("%s: km_ecdh_decode_secret: got %d, expected %zu\n", WOLFKM_ECDH_DRIVER, secret.len, expected_len); #endif /* WOLFKM_DEBUG_ECDH */ return -EINVAL; @@ -249,7 +249,7 @@ static int km_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, if (km_ecdh_decode_secret(buf, len, ¶ms) < 0) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("%s: ecdh_set_secret: decode secret failed: %d", + pr_err("%s: ecdh_set_secret: decode secret failed: %d\n", WOLFKM_ECDH_DRIVER, params.key_size); #endif /* WOLFKM_DEBUG_ECDH */ return -EINVAL; @@ -417,7 +417,7 @@ static int km_ecdh_init(struct crypto_kpp *tfm, int curve_id) #endif /* ECC_TIMING_RESISTANT */ #ifdef WOLFKM_DEBUG_ECDH - pr_info("info: exiting km_ecdh_init: curve_id %d, curve_len %d", + pr_info("info: exiting km_ecdh_init: curve_id %d, curve_len %d\n", ctx->curve_id, ctx->curve_len); #endif /* WOLFKM_DEBUG_ECDH */ return 0; @@ -484,7 +484,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) if (raw_pub_len > req->dst_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: dst_len too small: %d", req->dst_len); + pr_err("error: dst_len too small: %d\n", req->dst_len); #endif /* WOLFKM_DEBUG_ECDH */ err = -EOVERFLOW; goto ecdh_gen_pub_end; @@ -504,7 +504,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) err = wc_ecc_make_pub(ctx->key, NULL); if (err) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: ecc_make_pub returned: %d", err); + pr_err("error: ecc_make_pub returned: %d\n", err); #endif /* WOLFKM_DEBUG_ECDH */ goto ecdh_gen_pub_end; } @@ -522,7 +522,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) if (err || pub_x_len != ctx->curve_len || pub_y_len != ctx->curve_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: ecc export pub returned: err=%d, x=%d, y=%d", err, + pr_err("error: ecc export pub returned: err=%d, x=%d, y=%d\n", err, pub_x_len, pub_y_len); #endif /* WOLFKM_DEBUG_ECDH */ err = -EINVAL; @@ -537,7 +537,7 @@ static int km_ecdh_gen_pub(struct kpp_request *req) if (pub) { free(pub); pub = NULL; } #ifdef WOLFKM_DEBUG_ECDH - pr_info("info: exiting km_ecdh_gen_pub: %d", err); + pr_info("info: exiting km_ecdh_gen_pub: %d\n", err); #endif /* WOLFKM_DEBUG_ECDH */ return err; } @@ -584,7 +584,7 @@ static int km_ecdh_compute_shared_secret(struct kpp_request *req) if (req->src_len != raw_pub_len) { #ifdef WOLFKM_DEBUG_ECDH - pr_err("error: got src_len %d, expected %d", req->src_len, raw_pub_len); + pr_err("error: got src_len %d, expected %d\n", req->src_len, raw_pub_len); #endif /* WOLFKM_DEBUG_ECDH */ err = -EINVAL; goto ecdh_shared_secret_end; @@ -928,7 +928,7 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, dst_buf = malloc(dst_len); if (dst_buf == NULL) { - pr_err("error: allocating out buf failed"); + pr_err("error: allocating out buf failed\n"); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } @@ -942,20 +942,20 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, err = crypto_kpp_generate_public_key(req); if (err) { - pr_err("error: crypto_kpp_generate_public_key returned: %d", err); + pr_err("error: crypto_kpp_generate_public_key returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } if (memcmp(expected_a_pub, sg_virt(req->dst), pub_len)) { - pr_err("error: crypto_kpp_generate_public_key: wrong output"); + pr_err("error: crypto_kpp_generate_public_key: wrong output\n"); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } src_buf = malloc(src_len); if (src_buf == NULL) { - pr_err("error: allocating in buf failed"); + pr_err("error: allocating in buf failed\n"); test_rc = MEMORY_E; goto test_ecdh_nist_end; } @@ -970,13 +970,13 @@ static int linuxkm_test_ecdh_nist_driver(const char * driver, err = crypto_kpp_compute_shared_secret(req); if (err) { - pr_err("error: crypto_kpp_compute_shared_secret returned: %d", err); + pr_err("error: crypto_kpp_compute_shared_secret returned: %d\n", err); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } if (memcmp(shared_secret, sg_virt(req->dst), shared_s_len)) { - pr_err("error: shared secret does not match"); + pr_err("error: shared secret does not match\n"); test_rc = BAD_FUNC_ARG; goto test_ecdh_nist_end; } diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index f88da9e2bb..4bb25a7298 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -244,7 +244,7 @@ static ssize_t install_algs_handler(struct kobject *kobj, struct kobj_attribute if (kstrtoint(buf, 10, &arg) || arg != 1) return -EINVAL; - pr_info("wolfCrypt: Installing algorithms"); + pr_info("wolfCrypt: Installing algorithms\n"); ret = linuxkm_lkcapi_register(); if (ret != 0) @@ -265,7 +265,7 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut if (kstrtoint(buf, 10, &arg) || arg != 1) return -EINVAL; - pr_info("wolfCrypt: Deinstalling algorithms"); + pr_info("wolfCrypt: Deinstalling algorithms\n"); ret = linuxkm_lkcapi_unregister(); if (ret != 0) @@ -274,7 +274,7 @@ static ssize_t deinstall_algs_handler(struct kobject *kobj, struct kobj_attribut #if defined(HAVE_FIPS) && defined(CONFIG_CRYPTO_MANAGER) && \ !defined(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) if (enabled_fips) { - pr_info("wolfCrypt: restoring fips_enabled to off."); + pr_info("wolfCrypt: restoring fips_enabled to off.\n"); enabled_fips = fips_enabled = 0; } #endif @@ -358,7 +358,7 @@ static int linuxkm_lkcapi_register(void) /* assert system-wide FIPS status, to disable FIPS-forbidden * test vectors and fuzzing from the CRYPTO_MANAGER. */ - pr_info("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module."); + pr_info("wolfCrypt: changing fips_enabled from 0 to 1 for FIPS module.\n"); enabled_fips = fips_enabled = 1; } #endif @@ -382,7 +382,7 @@ static int linuxkm_lkcapi_register(void) if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \ pr_err("ERROR: alg %s not _DEAD " \ "after crypto_unregister_%s -- " \ - "marking as loaded despite test failure.", \ + "marking as loaded despite test failure.\n", \ (alg).base.cra_driver_name, \ #alg_class); \ alg ## _loaded = 1; \ @@ -434,7 +434,7 @@ static int linuxkm_lkcapi_register(void) if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \ pr_err("ERROR: alg %s not _DEAD " \ "after crypto_unregister_%s -- " \ - "marking as loaded despite test failure.", \ + "marking as loaded despite test failure.\n", \ (alg).base.cra_driver_name, \ #alg_class); \ alg ## _loaded = 1; \ @@ -729,7 +729,7 @@ static int linuxkm_lkcapi_register(void) disable_setkey_warnings = 0; #endif - pr_info("wolfCrypt: %d algorithm%s registered.", linuxkm_lkcapi_n_registered, + pr_info("wolfCrypt: %d algorithm%s registered.\n", linuxkm_lkcapi_n_registered, linuxkm_lkcapi_n_registered == 1 ? "" : "s"); if (ret == -1) { @@ -794,7 +794,7 @@ static int linuxkm_lkcapi_unregister(void) do { \ if (alg ## _loaded) { \ if ((alg).base.cra_flags & CRYPTO_ALG_DEAD) { \ - pr_err("alg %s already CRYPTO_ALG_DEAD.", \ + pr_err("alg %s already CRYPTO_ALG_DEAD.\n", \ (alg).base.cra_driver_name); \ alg ## _loaded = 0; \ ++n_deregistered; \ @@ -807,7 +807,7 @@ static int linuxkm_lkcapi_unregister(void) if (! ((alg).base.cra_flags & CRYPTO_ALG_DEAD)) { \ pr_err("ERROR: alg %s not _DEAD after " \ "crypto_unregister_%s -- " \ - "leaving marked as loaded.", \ + "leaving marked as loaded.\n", \ (alg).base.cra_driver_name, \ #alg_class); \ seen_err = -EBUSY; \ @@ -817,7 +817,7 @@ static int linuxkm_lkcapi_unregister(void) } \ } \ else { \ - pr_err("alg %s cannot be uninstalled (refcnt = %d)", \ + pr_err("alg %s cannot be uninstalled (refcnt = %d)\n", \ (alg).base.cra_driver_name, cur_refcnt); \ if (cur_refcnt > 0) { seen_err = -EBUSY; } \ } \ @@ -1025,7 +1025,7 @@ static int linuxkm_lkcapi_unregister(void) #undef UNREGISTER_ALG linuxkm_lkcapi_n_registered -= n_deregistered; - pr_info("wolfCrypt: %d algorithm%s deregistered, %d remain%s registered.", + pr_info("wolfCrypt: %d algorithm%s deregistered, %d remain%s registered.\n", n_deregistered, n_deregistered == 1 ? "" : "s", linuxkm_lkcapi_n_registered, linuxkm_lkcapi_n_registered == 1 ? "s" : ""); diff --git a/linuxkm/lkcapi_rsa_glue.c b/linuxkm/lkcapi_rsa_glue.c index 056a0d589d..e38dfaf28c 100644 --- a/linuxkm/lkcapi_rsa_glue.c +++ b/linuxkm/lkcapi_rsa_glue.c @@ -1172,7 +1172,7 @@ static int km_pkcs1pad_sign(struct akcipher_request *req) #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1pad_sign msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", req->src_len, enc_len, sig_len, err); + " sig_len %d, err %d\n", req->src_len, enc_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1223,7 +1223,7 @@ static int km_pkcs1pad_verify(struct akcipher_request *req) hash_enc_len = get_hash_enc_len(ctx->hash_oid); if (hash_enc_len <= 0) { #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: bad hash enc len %d", + pr_err("error: %s: bad hash enc len %d\n", WOLFKM_RSA_DRIVER, hash_enc_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1233,7 +1233,7 @@ static int km_pkcs1pad_verify(struct akcipher_request *req) if (msg_len != ctx->digest_len || sig_len != ctx->key_len) { /* invalid src or dst args */ #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: got msg_len %d, expected %d", + pr_err("error: %s: got msg_len %d, expected %d\n", WOLFKM_RSA_DRIVER, msg_len, ctx->digest_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1287,7 +1287,7 @@ static int km_pkcs1pad_verify(struct akcipher_request *req) #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1pad_verify msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", msg_len, enc_msg_len, sig_len, err); + " sig_len %d, err %d\n", msg_len, enc_msg_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1420,7 +1420,7 @@ static int km_pkcs1_sign(struct crypto_sig *tfm, #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1_sign msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", slen, enc_msg_len, sig_len, err); + " sig_len %d, err %d\n", slen, enc_msg_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1474,7 +1474,7 @@ static int km_pkcs1_verify(struct crypto_sig *tfm, hash_enc_len = get_hash_enc_len(ctx->hash_oid); if (hash_enc_len <= 0) { #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: bad hash enc len %d", + pr_err("error: %s: bad hash enc len %d\n", WOLFKM_RSA_DRIVER, hash_enc_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1484,7 +1484,7 @@ static int km_pkcs1_verify(struct crypto_sig *tfm, if (msg_len != ctx->digest_len || sig_len != ctx->key_len) { /* invalid src or dst args */ #ifdef WOLFKM_DEBUG_RSA - pr_err("error: %s: got msg_len %d, expected %d", + pr_err("error: %s: got msg_len %d, expected %d\n", WOLFKM_RSA_DRIVER, msg_len, ctx->digest_len); #endif /* WOLFKM_DEBUG_RSA */ err = -EINVAL; @@ -1538,7 +1538,7 @@ static int km_pkcs1_verify(struct crypto_sig *tfm, #ifdef WOLFKM_DEBUG_RSA pr_info("info: exiting km_pkcs1_verify msg_len %d, enc_msg_len %d," - " sig_len %d, err %d", msg_len, enc_msg_len, sig_len, err); + " sig_len %d, err %d\n", msg_len, enc_msg_len, sig_len, err); #endif /* WOLFKM_DEBUG_RSA */ return err; } @@ -1817,7 +1817,7 @@ static int km_pkcs1pad_dec(struct akcipher_request *req) if (dec != NULL) { free(dec); dec = NULL; } #ifdef WOLFKM_DEBUG_RSA - pr_info("info: exiting km_pkcs1pad_dec %d", err); + pr_info("info: exiting km_pkcs1pad_dec %d\n", err); #endif /* WOLFKM_DEBUG_RSA */ return err; } diff --git a/linuxkm/lkcapi_sha_glue.c b/linuxkm/lkcapi_sha_glue.c index 6a75afc95f..39754a6424 100644 --- a/linuxkm/lkcapi_sha_glue.c +++ b/linuxkm/lkcapi_sha_glue.c @@ -1188,7 +1188,7 @@ static int wc_linuxkm_drbg_generate(struct wc_rng_bank *ctx, struct wc_rng_bank_inst *drbg = linuxkm_get_drbg(ctx); if (! drbg) { - pr_err_once("BUG: linuxkm_get_drbg() failed."); + pr_err_once("BUG: linuxkm_get_drbg() failed.\n"); return -EFAULT; } @@ -1235,11 +1235,11 @@ static int wc_linuxkm_drbg_generate(struct wc_rng_bank *ctx, WC_RNG_BANK_FLAG_CAN_WAIT); if (ret == 0) { - pr_warn("WARNING: reinitialized DRBG #%d after RNG_FAILURE_E from wc_RNG_GenerateBlock().", raw_smp_processor_id()); + pr_warn("WARNING: reinitialized DRBG #%d after RNG_FAILURE_E from wc_RNG_GenerateBlock().\n", raw_smp_processor_id()); continue; } else { - pr_warn_once("ERROR: reinitialization of DRBG #%d after RNG_FAILURE_E failed with ret %d.", raw_smp_processor_id(), ret); + pr_warn_once("ERROR: reinitialization of DRBG #%d after RNG_FAILURE_E failed with ret %d.\n", raw_smp_processor_id(), ret); ret = -EINVAL; break; } @@ -1264,7 +1264,7 @@ static int wc_linuxkm_drbg_generate_tfm(struct crypto_rng *tfm, { if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err_once("BUG: mismatched tfm."); + pr_err_once("BUG: mismatched tfm.\n"); return -EFAULT; } @@ -1294,7 +1294,7 @@ static int wc_linuxkm_drbg_seed_tfm(struct crypto_rng *tfm, { if (tfm->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err_once("BUG: mismatched tfm."); + pr_err_once("BUG: mismatched tfm.\n"); return -EFAULT; } @@ -1354,7 +1354,7 @@ static int wc__get_random_bytes(void *buf, size_t len) NULL, 0, buf, len); (void)wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); if (ret) { - pr_warn("BUG: wc__get_random_bytes falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.", ret); + pr_warn("BUG: wc__get_random_bytes falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.\n", ret); } return ret; } @@ -1383,7 +1383,7 @@ static ssize_t wc_get_random_bytes_user(struct iov_iter *iter) { ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, NULL, 0, block, sizeof block); if (unlikely(ret != 0)) { - pr_err("ERROR: wc_get_random_bytes_user() wc_linuxkm_drbg_generate() returned %d.", ret); + pr_err("ERROR: wc_get_random_bytes_user() wc_linuxkm_drbg_generate() returned %d.\n", ret); break; } @@ -1445,7 +1445,7 @@ static ssize_t wc_extract_crng_user(void __user *buf, size_t nbytes) { ret = wc_linuxkm_drbg_generate(current_default_wc_rng_bank, NULL, 0, block, sizeof block); if (unlikely(ret != 0)) { - pr_err("ERROR: wc_extract_crng_user() wc_linuxkm_drbg_generate() returned %d.", ret); + pr_err("ERROR: wc_extract_crng_user() wc_linuxkm_drbg_generate() returned %d.\n", ret); break; } @@ -1610,10 +1610,10 @@ static int wc_get_random_bytes_by_kprobe(struct kprobe *p, struct pt_regs *regs) regs->ip = (unsigned long)p->addr + p->ainsn.size; return 1; /* Handled. */ } - pr_warn("BUG: wc_get_random_bytes_by_kprobe falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.", ret); + pr_warn("BUG: wc_get_random_bytes_by_kprobe falling through to native get_random_bytes with wc_linuxkm_drbg_default_instance_registered, ret=%d.\n", ret); } else - pr_warn("BUG: wc_get_random_bytes_by_kprobe called without wc_linuxkm_drbg_default_instance_registered."); + pr_warn("BUG: wc_get_random_bytes_by_kprobe called without wc_linuxkm_drbg_default_instance_registered.\n"); /* Not handled. Fall through to native implementation, given * that the alternative is an immediate kernel panic. @@ -1668,7 +1668,7 @@ static int wc_get_random_bytes_user_kretprobe_enter(struct kretprobe_instance *p byte block[WC_SHA256_BLOCK_SIZE]; if (unlikely(!wc_linuxkm_drbg_default_instance_registered)) { - pr_warn("BUG: wc_get_random_bytes_user_kretprobe_enter() without wc_linuxkm_drbg_default_instance_registered."); + pr_warn("BUG: wc_get_random_bytes_user_kretprobe_enter() without wc_linuxkm_drbg_default_instance_registered.\n"); ret = -ENOENT; goto out; } @@ -1681,7 +1681,7 @@ static int wc_get_random_bytes_user_kretprobe_enter(struct kretprobe_instance *p for (;;) { ret = crypto_rng_get_bytes(crypto_default_rng, block, sizeof block); if (ret != 0) { - pr_err("ERROR: wc_get_random_bytes_user_kretprobe_enter() crypto_rng_get_bytes() returned %d.", ret); + pr_err("ERROR: wc_get_random_bytes_user_kretprobe_enter() crypto_rng_get_bytes() returned %d.\n", ret); break; } @@ -1714,7 +1714,7 @@ static int wc_get_random_bytes_user_kretprobe_enter(struct kretprobe_instance *p if ((ret != 0) && (this_copied == (size_t)(-1L))) { /* crypto_rng_get_bytes() failed on the first call, before any update to the iov_iter. */ - pr_warn("WARNING: wc_get_random_bytes_user_kretprobe_enter() falling through to native get_random_bytes_user()."); + pr_warn("WARNING: wc_get_random_bytes_user_kretprobe_enter() falling through to native get_random_bytes_user().\n"); return -EFAULT; } @@ -1741,7 +1741,7 @@ static int wc_get_random_bytes_user_kretprobe_exit(struct kretprobe_instance *p, struct wc_get_random_bytes_user_kretprobe_ctx *ctx = (struct wc_get_random_bytes_user_kretprobe_ctx *)p->data; if (unlikely(!wc_linuxkm_drbg_default_instance_registered)) { - pr_warn("BUG: wc_get_random_bytes_user_kretprobe_exit without wc_linuxkm_drbg_default_instance_registered."); + pr_warn("BUG: wc_get_random_bytes_user_kretprobe_exit without wc_linuxkm_drbg_default_instance_registered.\n"); return -EFAULT; } @@ -1777,7 +1777,7 @@ static int wc_linuxkm_drbg_startup(void) int ret; if (wc_linuxkm_drbg_loaded) { - pr_err("ERROR: wc_linuxkm_drbg_set_default called with wc_linuxkm_drbg_loaded."); + pr_err("ERROR: wc_linuxkm_drbg_set_default called with wc_linuxkm_drbg_loaded.\n"); return -EBUSY; } @@ -1791,7 +1791,7 @@ static int wc_linuxkm_drbg_startup(void) ret = crypto_register_rng(&wc_linuxkm_drbg); if (ret != 0) { - pr_err("ERROR: crypto_register_rng: %d", ret); + pr_err("ERROR: crypto_register_rng: %d\n", ret); return ret; } @@ -1860,7 +1860,7 @@ static int wc_linuxkm_drbg_startup(void) } if (ret) - pr_err("ERROR: wc_linuxkm_drbg_startup: PRNG quality test failed, block length %d, iters %d, ret %d", + pr_err("ERROR: wc_linuxkm_drbg_startup: PRNG quality test failed, block length %d, iters %d, ret %d\n", i, j, ret); } } @@ -1890,7 +1890,7 @@ static int wc_linuxkm_drbg_startup(void) ret = crypto_del_default_rng(); if (ret) { wc_linuxkm_rng_initing_default_bank_flag = 0; - pr_err("ERROR: crypto_del_default_rng returned %d", ret); + pr_err("ERROR: crypto_del_default_rng returned %d\n", ret); return ret; } @@ -1899,27 +1899,27 @@ static int wc_linuxkm_drbg_startup(void) wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { - pr_err("ERROR: crypto_get_default_rng returned %d", ret); + pr_err("ERROR: crypto_get_default_rng returned %d\n", ret); return ret; } { int cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt); if (cur_refcnt < 2) { - pr_err("ERROR: wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()", cur_refcnt); + pr_err("ERROR: wc_linuxkm_drbg refcnt = %d after crypto_get_default_rng()\n", cur_refcnt); crypto_put_default_rng(); return -EINVAL; } } if (! crypto_default_rng) { - pr_err("ERROR: crypto_default_rng is null"); + pr_err("ERROR: crypto_default_rng is null\n"); crypto_put_default_rng(); return -EINVAL; } if (crypto_default_rng->base.__crt_alg->cra_init != wc_linuxkm_drbg_init_tfm) { - pr_err("ERROR: %s NOT registered as systemwide default stdrng -- found \"%s\".", wc_linuxkm_drbg.base.cra_driver_name, crypto_tfm_alg_driver_name(&crypto_default_rng->base)); + pr_err("ERROR: %s NOT registered as systemwide default stdrng -- found \"%s\".\n", wc_linuxkm_drbg.base.cra_driver_name, crypto_tfm_alg_driver_name(&crypto_default_rng->base)); crypto_put_default_rng(); return -EINVAL; } @@ -1935,7 +1935,7 @@ static int wc_linuxkm_drbg_startup(void) ret = crypto_del_default_rng(); if (ret) { wc_linuxkm_rng_initing_default_bank_flag = 0; - pr_err("ERROR: crypto_del_default_rng returned %d", ret); + pr_err("ERROR: crypto_del_default_rng returned %d\n", ret); return ret; } @@ -1944,7 +1944,7 @@ static int wc_linuxkm_drbg_startup(void) wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { - pr_err("ERROR: __crypto_stdrng_get_bytes returned %d", ret); + pr_err("ERROR: __crypto_stdrng_get_bytes returned %d\n", ret); return ret; } } @@ -1954,7 +1954,7 @@ static int wc_linuxkm_drbg_startup(void) ret = wc_linuxkm_rng_bank_init(&default_bank); wc_linuxkm_rng_initing_default_bank_flag = 0; if (ret) { - pr_err("ERROR: wc_linuxkm_rng_bank_init returned %d", ret); + pr_err("ERROR: wc_linuxkm_rng_bank_init returned %d\n", ret); return ret; } default_bank_inited = 1; @@ -1966,11 +1966,11 @@ static int wc_linuxkm_drbg_startup(void) struct wc_rng_bank *current_default_wc_rng_bank; ret = wc_rng_bank_default_checkout(¤t_default_wc_rng_bank); if (ret) - pr_err("ERROR: wc_rng_bank_default_checkout() after default stdrng registration returned %d", ret); + pr_err("ERROR: wc_rng_bank_default_checkout() after default stdrng registration returned %d\n", ret); else { ret = wc_rng_bank_default_checkin(¤t_default_wc_rng_bank); if (ret) - pr_err("ERROR: wc_rng_bank_default_checkin() after wc_rng_bank_default_checkout() returned %d", ret); + pr_err("ERROR: wc_rng_bank_default_checkin() after wc_rng_bank_default_checkout() returned %d\n", ret); } if (ret != 0) { #if defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) && \ @@ -1986,8 +1986,8 @@ static int wc_linuxkm_drbg_startup(void) } wc_linuxkm_drbg_default_instance_registered = 1; - pr_info("%s registered as systemwide default stdrng.", wc_linuxkm_drbg.base.cra_driver_name); - pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs"); + pr_info("%s registered as systemwide default stdrng.\n", wc_linuxkm_drbg.base.cra_driver_name); + pr_info("libwolfssl: to unload module, first echo 1 > /sys/module/libwolfssl/deinstall_algs\n"); #ifdef LINUXKM_DRBG_GET_RANDOM_BYTES @@ -1999,7 +1999,7 @@ static int wc_linuxkm_drbg_startup(void) if (ret == 0) { wc_get_random_bytes_callbacks_installed = 1; - pr_info("libwolfssl: kernel global random_bytes handlers installed."); + pr_info("libwolfssl: kernel global random_bytes handlers installed.\n"); } else { pr_err("ERROR: wolfssl_linuxkm_register_random_bytes_handlers() failed: %d\n", ret); @@ -2039,22 +2039,22 @@ static int wc_linuxkm_drbg_startup(void) byte scratch[4]; ret = wc__get_random_bytes(scratch, sizeof(scratch)); if (ret != 0) { - pr_err("ERROR: wc__get_random_bytes() returned %d", ret); + pr_err("ERROR: wc__get_random_bytes() returned %d\n", ret); return -EINVAL; } ret = wc_mix_pool_bytes(scratch, sizeof(scratch)); if (ret != 0) { - pr_err("ERROR: wc_mix_pool_bytes() returned %d", ret); + pr_err("ERROR: wc_mix_pool_bytes() returned %d\n", ret); return -EINVAL; } ret = wc_crng_reseed(); if (ret != 0) { - pr_err("ERROR: wc_crng_reseed() returned %d", ret); + pr_err("ERROR: wc_crng_reseed() returned %d\n", ret); return -EINVAL; } ret = wc__get_random_bytes(scratch, sizeof(scratch)); if (ret != 0) { - pr_err("ERROR: wc__get_random_bytes() returned %d", ret); + pr_err("ERROR: wc__get_random_bytes() returned %d\n", ret); return -EINVAL; } } @@ -2071,7 +2071,7 @@ static int wc_linuxkm_drbg_cleanup(void) { int cur_refcnt; if (! wc_linuxkm_drbg_loaded) { - pr_err("ERROR: wc_linuxkm_drbg_cleanup called with ! wc_linuxkm_drbg_loaded"); + pr_err("ERROR: wc_linuxkm_drbg_cleanup called with ! wc_linuxkm_drbg_loaded\n"); return -EINVAL; } @@ -2094,7 +2094,7 @@ static int wc_linuxkm_drbg_cleanup(void) { if (wc_get_random_bytes_callbacks_installed) { ret = wolfssl_linuxkm_unregister_random_bytes_handlers(); if (ret != 0) { - pr_err("ERROR: wolfssl_linuxkm_unregister_random_bytes_handlers returned %d", ret); + pr_err("ERROR: wolfssl_linuxkm_unregister_random_bytes_handlers returned %d\n", ret); return ret; } pr_info("libwolfssl: kernel global random_bytes handlers uninstalled\n"); @@ -2127,7 +2127,7 @@ static int wc_linuxkm_drbg_cleanup(void) { #if LINUX_VERSION_CODE < KERNEL_VERSION(7, 1, 0) ret = crypto_del_default_rng(); if (ret) { - pr_err("ERROR: crypto_del_default_rng failed: %d", ret); + pr_err("ERROR: crypto_del_default_rng failed: %d\n", ret); return ret; } #else /* >= 7.1.0 */ @@ -2136,7 +2136,7 @@ static int wc_linuxkm_drbg_cleanup(void) { if (fips_enabled) { ret = crypto_del_default_rng(); if (ret) { - pr_err("ERROR: crypto_del_default_rng failed: %d", ret); + pr_err("ERROR: crypto_del_default_rng failed: %d\n", ret); return ret; } } @@ -2145,11 +2145,11 @@ static int wc_linuxkm_drbg_cleanup(void) { if (default_bank_inited) { ret = wc_rng_bank_default_clear(&default_bank); if (ret) - pr_err("ERROR: wc_rng_bank_default_clear in wc_linuxkm_drbg_cleanup failed: %d", ret); + pr_err("ERROR: wc_rng_bank_default_clear in wc_linuxkm_drbg_cleanup failed: %d\n", ret); else { ret = wc_rng_bank_fini(&default_bank); if (ret) - pr_err("ERROR: wc_rng_bank_fini in wc_linuxkm_drbg_cleanup failed: %d", ret); + pr_err("ERROR: wc_rng_bank_fini in wc_linuxkm_drbg_cleanup failed: %d\n", ret); } default_bank_inited = 0; } @@ -2162,14 +2162,14 @@ static int wc_linuxkm_drbg_cleanup(void) { cur_refcnt = WC_LKM_REFCOUNT_TO_INT(wc_linuxkm_drbg.base.cra_refcnt); if (cur_refcnt != 1) { - pr_err("ERROR: wc_linuxkm_drbg_cleanup called with refcnt = %d", cur_refcnt); + pr_err("ERROR: wc_linuxkm_drbg_cleanup called with refcnt = %d\n", cur_refcnt); return -EBUSY; } crypto_unregister_rng(&wc_linuxkm_drbg); if (! (wc_linuxkm_drbg.base.cra_flags & CRYPTO_ALG_DEAD)) { - pr_warn("WARNING: wc_linuxkm_drbg_cleanup: after crypto_unregister_rng, wc_linuxkm_drbg isn't dead."); + pr_warn("WARNING: wc_linuxkm_drbg_cleanup: after crypto_unregister_rng, wc_linuxkm_drbg isn't dead.\n"); return -EBUSY; } diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index 90fc3123b2..1cbde5a6ee 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -621,7 +621,7 @@ static int wolfssl_init(void) #ifdef HAVE_FIPS /* The compiled-in verifycore must be the right length, else the module * geometry will change when the correct value is passed in, destabilizing - * wc_linuxkm_pie_reloc_tab. It also must be the right length for the + * wc_linuxkm_pie_text_reloc_tab. It also must be the right length for the * module-update-fips-hash recipe (in-place overwrite) to work, and for * updateFipsHash() (WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE) to be safe from * overruns. @@ -711,28 +711,32 @@ static int wolfssl_init(void) { unsigned int text_hash = hash_span((const u8 *)__wc_text_start, (const u8 *)__wc_text_end, 1); unsigned int rodata_hash = hash_span((const u8 *)__wc_rodata_start, (const u8 *)__wc_rodata_end, 1); - u8 *canon_buf = malloc(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ); - ssize_t cur_reloc_index = -1; + u8 *canon_buf = malloc(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ); + ssize_t cur_reloc_index; const u8 *text_p = (const u8 *)__wc_text_start; + const u8 *rodata_p = (const u8 *)__wc_rodata_start; unsigned int stabilized_text_hash = 1; + unsigned int stabilized_rodata_hash = 1; if (! canon_buf) { - pr_err("ERROR: malloc(%d) for WOLFSSL_TEXT_SEGMENT_CANONICALIZER failed: %ld.\n", WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, PTR_ERR(canon_buf)); + pr_err("ERROR: malloc(%d) for WOLFSSL_*_SEGMENT_CANONICALIZER failed: %ld.\n", WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, PTR_ERR(canon_buf)); return -ECANCELED; } reloc_counts.text = reloc_counts.rodata = reloc_counts.rwdata = reloc_counts.bss = reloc_counts.other = 0; + cur_reloc_index = -1; while (text_p < (const u8 *)__wc_text_end) { + size_t text_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const u8 *)__wc_text_end - text_p)); ssize_t progress = - WOLFSSL_TEXT_SEGMENT_CANONICALIZER( + WOLFSSL_SEGMENT_CANONICALIZER( text_p, - min(WOLFSSL_TEXT_SEGMENT_CANONICALIZER_BUFSIZ, - (word32)((const u8 *)__wc_text_end - text_p)), + &text_in_out_len, canon_buf, &cur_reloc_index); if (progress <= 0) { - pr_err("ERROR: progress=%ld from WOLFSSL_TEXT_SEGMENT_CANONICALIZER() at offset %x (text=%x-%x).\n", + pr_err("ERROR: progress=%ld from WOLFSSL_SEGMENT_CANONICALIZER() at offset %x (text=%x-%x).\n", (long)progress, (unsigned)(uintptr_t)text_p, (unsigned)(uintptr_t)__wc_text_start, @@ -740,10 +744,33 @@ static int wolfssl_init(void) free(canon_buf); return -ECANCELED; } - stabilized_text_hash = hash_span(canon_buf, canon_buf + progress, stabilized_text_hash); + stabilized_text_hash = hash_span(canon_buf, canon_buf + text_in_out_len, stabilized_text_hash); text_p += progress; } + /* note verifyCore is hashed along with the rest of .rodata_wolfcrypt. */ + cur_reloc_index = -1; + while (rodata_p < (const u8 *)__wc_rodata_end) { + size_t rodata_in_out_len = min(WOLFSSL_SEGMENT_CANONICALIZER_BUFSIZ, + (size_t)((const u8 *)__wc_rodata_end - rodata_p)); + ssize_t progress = + WOLFSSL_SEGMENT_CANONICALIZER( + rodata_p, + &rodata_in_out_len, + canon_buf, &cur_reloc_index); + if (progress <= 0) { + pr_err("ERROR: progress=%ld from WOLFSSL_SEGMENT_CANONICALIZER() at offset %x (rodata=%x-%x).\n", + (long)progress, + (unsigned)(uintptr_t)rodata_p, + (unsigned)(uintptr_t)__wc_rodata_start, + (unsigned)(uintptr_t)__wc_rodata_end); + free(canon_buf); + return -ECANCELED; + } + stabilized_rodata_hash = hash_span(canon_buf, canon_buf + rodata_in_out_len, stabilized_rodata_hash); + rodata_p += progress; + } + free(canon_buf); canon_buf = 0; @@ -751,12 +778,13 @@ static int wolfssl_init(void) * the true module start address, which is potentially useful to an * attacker. */ - pr_info("wolfCrypt segment hashes (spans): text 0x%x (%llu), rodata 0x%x (%llu), offset %c0x%llx, canon text 0x%x\n", + pr_info("wolfCrypt segment hashes (spans): text 0x%x (%llu), rodata 0x%x (%llu), offset %c0x%llx, canon text 0x%x, canon rodata 0x%x\n", text_hash, (unsigned long long)((uintptr_t)__wc_text_end - (uintptr_t)__wc_text_start), rodata_hash, (unsigned long long)((uintptr_t)__wc_rodata_end - (uintptr_t)__wc_rodata_start), (uintptr_t)__wc_text_start < (uintptr_t)&__wc_rodata_start[0] ? '+' : '-', (uintptr_t)__wc_text_start < (uintptr_t)&__wc_rodata_start[0] ? (unsigned long long)((uintptr_t)&__wc_rodata_start[0] - (uintptr_t)__wc_text_start) : (unsigned long long)((uintptr_t)__wc_text_start - (uintptr_t)&__wc_rodata_start[0]), - stabilized_text_hash); + stabilized_text_hash, + stabilized_rodata_hash); pr_info("wolfCrypt segments: text=%llx-%llx, rodata=%llx-%llx, " "rwdata=%llx-%llx, bss=%llx-%llx\n", @@ -1090,7 +1118,7 @@ static void wolfssl_exit(void) pr_err("ERROR: wc_RunAllCast_fips() failed at shutdown with return value %d\n", ret); } else - pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified."); + pr_info("wolfCrypt FIPS re-self-test succeeded at unload: all algorithms re-verified.\n"); #endif (void)libwolfssl_cleanup(); @@ -1118,17 +1146,23 @@ MODULE_VERSION(LIBWOLFSSL_VERSION_STRING); #ifdef WC_SYM_RELOC_TABLES -extern const struct wc_reloc_table_ent wc_linuxkm_pie_reloc_tab[]; -extern const unsigned int wc_linuxkm_pie_reloc_tab_length; +extern const struct wc_reloc_table_ent wc_linuxkm_pie_text_reloc_tab[]; +extern const unsigned int wc_linuxkm_pie_text_reloc_tab_length; +extern const struct wc_reloc_table_ent wc_linuxkm_pie_rodata_reloc_tab[]; +extern const unsigned int wc_linuxkm_pie_rodata_reloc_tab_length; static const struct wc_reloc_table_segments seg_map = { .start = 0, .end = 0, .text_start = (size_t)(uintptr_t)__wc_text_start, .text_end = (size_t)(uintptr_t)__wc_text_end, - .reloc_tab_start = (size_t)(uintptr_t)wc_linuxkm_pie_reloc_tab, - .reloc_tab_end = 0, - .reloc_tab_len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_reloc_tab_length, - .reloc_tab_len_end = 0, + .text_reloc_tab.start = (size_t)(uintptr_t)wc_linuxkm_pie_text_reloc_tab, + .text_reloc_tab.end = 0, + .text_reloc_tab.len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_text_reloc_tab_length, + .text_reloc_tab.len_end = 0, + .rodata_reloc_tab.start = (size_t)(uintptr_t)wc_linuxkm_pie_rodata_reloc_tab, + .rodata_reloc_tab.end = 0, + .rodata_reloc_tab.len_start = (size_t)(uintptr_t)&wc_linuxkm_pie_rodata_reloc_tab_length, + .rodata_reloc_tab.len_end = 0, #ifdef HAVE_FIPS #ifdef WC_USE_PIE_FENCEPOSTS_FOR_FIPS .fips_text_start = (size_t)(uintptr_t)__wc_text_start, @@ -1161,18 +1195,40 @@ static const struct wc_reloc_table_segments seg_map = { }; ssize_t wc_linuxkm_normalize_relocations( - const u8 *text_in, - size_t text_in_len, - u8 *text_out, + const u8 *seg_in, + size_t *seg_in_out_len, + u8 *seg_out, + ssize_t *cur_index_p) +{ + return wc_reloc_normalize_segment(seg_in, seg_in_out_len, seg_out, cur_index_p, &seg_map, +#ifdef DEBUG_LINUXKM_PIE_SUPPORT + &reloc_counts +#else + NULL +#endif + ); +} + +ssize_t wc_linuxkm_normalize_relocations_noresize( + const u8 *seg_in, + size_t seg_in_len, + u8 *seg_out, ssize_t *cur_index_p) { - return wc_reloc_normalize_text(text_in, text_in_len, text_out, cur_index_p, &seg_map, + ssize_t ret; + ret = wc_reloc_normalize_segment(seg_in, &seg_in_len, seg_out, cur_index_p, &seg_map, #ifdef DEBUG_LINUXKM_PIE_SUPPORT &reloc_counts #else NULL #endif ); + if (ret < 0) + return ret; + if ((size_t)ret != seg_in_len) + return -EINVAL; + else + return seg_in_len; } #elif defined(HAVE_FIPS) @@ -1227,6 +1283,8 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { #ifdef HAVE_FIPS wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_normalize_relocations = wc_linuxkm_normalize_relocations; + wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_normalize_relocations_noresize = + wc_linuxkm_normalize_relocations_noresize; #endif #ifndef __ARCH_MEMCMP_NO_REDIRECT @@ -1717,7 +1775,7 @@ static int updateFipsHash(void) size_t desc_size = crypto_shash_descsize(tfm) + sizeof *desc; desc = XMALLOC(desc_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (desc == NULL) { - pr_err("ERROR: failed allocating desc."); + pr_err("ERROR: failed allocating desc.\n"); ret = MEMORY_E; goto out; } @@ -1790,13 +1848,17 @@ static WC_MAYBE_UNUSED void *my_kallsyms_lookup_name(const char *name) { int ret; kallsyms_lookup_name_kp.addr = NULL; if ((ret = register_kprobe(&kallsyms_lookup_name_kp)) != 0) { - pr_err_once("ERROR: register_kprobe(&kallsyms_lookup_name_kp) failed: %d", ret); +#ifdef WOLFSSL_LINUXKM_VERBOSE_DEBUG + pr_err_once("ERROR: register_kprobe(&kallsyms_lookup_name_kp) failed: %d\n", ret); +#endif return 0; } kallsyms_lookup_name_ptr = (typeof(kallsyms_lookup_name_ptr))kallsyms_lookup_name_kp.addr; unregister_kprobe(&kallsyms_lookup_name_kp); if (! kallsyms_lookup_name_ptr) { - pr_err_once("ERROR: kallsyms_lookup_name_kp.addr is null."); +#ifdef WOLFSSL_LINUXKM_VERBOSE_DEBUG + pr_err_once("ERROR: kallsyms_lookup_name_kp.addr is null.\n"); +#endif return 0; } } @@ -1825,7 +1887,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } - pr_info("wolfCrypt: rerunning FIPS self-test on command."); + pr_info("wolfCrypt: rerunning FIPS self-test on command.\n"); if (WC_SIG_IGNORE_BEGIN() >= 0) { ret = wolfCrypt_IntegrityTest_fips(); @@ -1836,7 +1898,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at ret = -1; } if (ret != 0) { - pr_err("ERROR: wolfCrypt_IntegrityTest_fips: error %d", ret); + pr_err("ERROR: wolfCrypt_IntegrityTest_fips: error %d\n", ret); return -EINVAL; } @@ -1855,7 +1917,7 @@ static ssize_t FIPS_rerun_self_test_handler(struct kobject *kobj, struct kobj_at return -EINVAL; } - pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available."); + pr_info("wolfCrypt FIPS re-self-test succeeded: all algorithms verified and available.\n"); return count; } diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 3758552c15..7556594f4b 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -10176,12 +10176,8 @@ void ge_tobytes(unsigned char *s,const ge_p2 *h) s[31] ^= (unsigned char)((unsigned char)fe_isnegative(x) << 7); } -#ifdef HAVE_ED25519_VERIFY -#ifndef CURVED25519_ASM_64BIT - #define fe_invert_nct fe_invert -#endif - -/* ge tobytes */ +#if defined(HAVE_ED25519_VERIFY) && defined(CURVED25519_ASM_64BIT) +/* ge tobytes_nct */ void ge_tobytes_nct(unsigned char *s,const ge_p2 *h) { ge recip; @@ -10194,7 +10190,7 @@ void ge_tobytes_nct(unsigned char *s,const ge_p2 *h) fe_tobytes(s,y); s[31] ^= (unsigned char)((unsigned char)fe_isnegative(x) << 7); } -#endif +#endif /* HAVE_ED25519_VERIFY && CURVED25519_ASM_64BIT */ #endif /* !ED25519_SMALL */ diff --git a/wolfcrypt/src/wc_lms_impl.c b/wolfcrypt/src/wc_lms_impl.c index a6fc89da7f..8681080c94 100644 --- a/wolfcrypt/src/wc_lms_impl.c +++ b/wolfcrypt/src/wc_lms_impl.c @@ -2418,10 +2418,12 @@ static int wc_lms_treehash_update(LmsState* state, LmsPrivState* privState, } } - if (!useRoot && (ret == 0)) { - /* Copy stack back. */ - XMEMCPY(stackCache->stack, stack, params->height * params->hash_len); - stackCache->offset = (word32)((size_t)sp - (size_t)stack); + if (ret == 0) { + if (!useRoot) { + /* Copy stack back. */ + XMEMCPY(stackCache->stack, stack, params->height * params->hash_len); + stackCache->offset = (word32)((size_t)sp - (size_t)stack); + } } WC_FREE_VAR_EX(stack, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfssl/wolfcrypt/ge_operations.h b/wolfssl/wolfcrypt/ge_operations.h index 8496b959b1..0a18a7ebba 100644 --- a/wolfssl/wolfcrypt/ge_operations.h +++ b/wolfssl/wolfcrypt/ge_operations.h @@ -85,11 +85,13 @@ WOLFSSL_LOCAL void sc_reduce(byte* s); WOLFSSL_LOCAL void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c); WOLFSSL_LOCAL void ge_tobytes(unsigned char *s,const ge_p2 *h); -#ifndef ED25519_SMALL +#ifdef HAVE_ED25519_VERIFY +#if !defined(ED25519_SMALL) && defined(CURVED25519_ASM_64BIT) WOLFSSL_LOCAL void ge_tobytes_nct(unsigned char *s,const ge_p2 *h); #else #define ge_tobytes_nct ge_tobytes #endif +#endif /* HAVE_ED25519_VERIFY */ #ifndef GE_P3_TOBYTES_IMPL #define ge_p3_tobytes(s, h) ge_tobytes((s), (const ge_p2 *)(h)) #else