[PATCH v2 2/2] fips: Fix self-check compiled with clang

Clemens Lang cllang at redhat.com
Mon Feb 14 18:50:00 CET 2022

* src/fips.c [ENABLE_HMAC_BINARY_CHECK] (hmac256_check): Prevent
  constant propagation of a 0 HMAC value.


clang 13 assumes that the static const unsigned char[32]
hmac_for_the_implementation is zero, propagates this constant into its
use in hmac256_check and replaces with invocation of memcmp(3) with
assembly instructions that compare the computed digest with 0.

clang is able to make this assumption, because a 0-initialized static
const variable should never change its value, but this assumption is
invalid as soon as objcpy(1) changes the HMAC in the binary.

Apply a suggestion from [1] to prevent this optimization.

 [1]: https://bugzilla.redhat.com/show_bug.cgi?id=2034320#c22

Signed-off-by: Clemens Lang <cllang at redhat.com>
 src/Makefile.am |  4 ++--
 src/fips.c      | 11 ++++++++++-
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index b0a196a3..b799e52d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -143,14 +143,14 @@ if USE_HMAC_BINARY_CHECK
 CLEANFILES += libgcrypt.so.hmac
 libgcrypt.la.done: libgcrypt.so.hmac
-	$(OBJCOPY) --update-section .rodata1=libgcrypt.so.hmac \
+	$(OBJCOPY) --update-section .rodata_fips_hmac=libgcrypt.so.hmac \
 	  .libs/libgcrypt.so .libs/libgcrypt.so.new
 	mv -f .libs/libgcrypt.so.new .libs/libgcrypt.so.*.*
 	@touch libgcrypt.la.done
 libgcrypt.so.hmac: hmac256 libgcrypt.la
 	dd if=/dev/zero of=libgcrypt.so.hmac.empty bs=32 count=1
-	$(OBJCOPY) --update-section .rodata1=libgcrypt.so.hmac.empty \
+	$(OBJCOPY) --update-section .rodata_fips_hmac=libgcrypt.so.hmac.empty \
 	  .libs/libgcrypt.so .libs/libgcrypt.so.empty-hmac
 	./hmac256 --stdkey --binary .libs/libgcrypt.so.empty-hmac > $@
 	$(RM) libgcrypt.so.hmac.empty .libs/libgcrypt.so.empty-hmac
diff --git a/src/fips.c b/src/fips.c
index c40274d9..35546b8c 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -593,9 +593,18 @@ run_random_selftests (void)
 # endif
 #define HMAC_LEN 32
-static const unsigned char __attribute__ ((section (".rodata1")))
+extern const unsigned char __attribute__ ((visibility ("hidden")))
+__asm (".hidden hmac_for_the_implementation\n\t"
+       ".type hmac_for_the_implementation, %object\n\t"
+       ".size hmac_for_the_implementation, 32\n\t"
+       ".section .rodata_fips_hmac,\"a\"\n\t"
+       ".balign 16\n"
+       "hmac_for_the_implementation:\n\t"
+       ".zero 32\n\t"
+       ".previous");
  * Determine the offset of the given virtual address in the ELF file opened as
  * fp and return it in offset. Rewinds fp to the beginning on success.

More information about the Gcrypt-devel mailing list