diff --git a/libica-sles15sp2-FIPS-introduce-HMAC-based-library-integrity-check.patch.20200505 b/libica-sles15sp2-FIPS-introduce-HMAC-based-library-integrity-check.patch.20200505 deleted file mode 100644 index d143191..0000000 --- a/libica-sles15sp2-FIPS-introduce-HMAC-based-library-integrity-check.patch.20200505 +++ /dev/null @@ -1,354 +0,0 @@ -From 231bba3b32bd246d8286f1c7dc231d836ea92bd9 Mon Sep 17 00:00:00 2001 -From: Joerg Schmidbauer -Date: Mon, 27 Apr 2020 11:18:26 +0200 -Subject: [PATCH] FIPS: introduce HMAC based library integrity check - -When in FIPS mode, perform an integrity check on libica.so by calculating -an HMAC from the file contents using a static HMAC key, and comparing it -to a pre-calculated HMAC in a separate file. The HMAC key and HMAC file -may be provided by a Distributor when building the packet. The test -succeeds if the HMAC file is not present. - -Signed-off-by: Joerg Schmidbauer ---- - include/ica_api.h | 2 +- - src/Makefile.am | 4 +- - src/fips.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++- - src/include/fips.h | 4 +- - test/fips_test.c | 4 + - 5 files changed, 232 insertions(+), 6 deletions(-) - -diff --git a/include/ica_api.h b/include/ica_api.h -index 91bf0be..8221f55 100644 ---- a/include/ica_api.h -+++ b/include/ica_api.h -@@ -216,7 +216,7 @@ typedef ica_adapter_handle_t ICA_ADAPTER_HANDLE; - */ - /* Cryptographic algorithm test (KAT or pair-wise consistency test) */ - #define ICA_FIPS_CRYPTOALG 2 --/* Software/Firmware integrity test (not implemented yet) */ -+/* Software/Firmware integrity test */ - #define ICA_FIPS_INTEGRITY 4 - /* Critical functions test (N/A) */ - #define ICA_FIPS_CRITICALFUNC 8 -diff --git a/src/Makefile.am b/src/Makefile.am -index 65f471f..9e4ef52 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -9,7 +9,7 @@ - libica_la_CFLAGS = ${AM_CFLAGS} -I${srcdir}/include -I${srcdir}/../include \ - -fvisibility=hidden - libica_la_CCASFLAGS = ${AM_CFLAGS} --libica_la_LIBADD = @LIBS@ -lrt -lcrypto -+libica_la_LIBADD = @LIBS@ -lrt -lcrypto -ldl - libica_la_LDFLAGS = -Wl,--version-script=${srcdir}/../libica.map \ - -version-number ${VERSION} - libica_la_SOURCES = ica_api.c init.c icastats_shared.c s390_rsa.c \ -@@ -53,7 +53,7 @@ - -DICA_INTERNAL_TEST \ - -DICA_INTERNAL_TEST_EC - internal_tests_ec_internal_test_CCASFLAGS = ${AM_CFLAGS} --internal_tests_ec_internal_test_LDADD = @LIBS@ -lrt -lcrypto -lpthread -+internal_tests_ec_internal_test_LDADD = @LIBS@ -lrt -lcrypto -lpthread -ldl - internal_tests_ec_internal_test_SOURCES = \ - ica_api.c init.c icastats_shared.c s390_rsa.c \ - s390_crypto.c s390_ecc.c s390_prng.c s390_sha.c \ -diff --git a/src/fips.c b/src/fips.c -index d09a553..bab00db 100644 ---- a/src/fips.c -+++ b/src/fips.c -@@ -13,11 +13,13 @@ - - #include - #include -+#include - #include - #include - #include - #include - #include -+#include - - #include - #ifdef OPENSSL_FIPS -@@ -28,6 +30,24 @@ - #include "ica_api.h" - #include "test_vec.h" - -+#ifndef PATH_MAX -+#define PATH_MAX 4096 -+#endif -+ -+#define HMAC_PREFIX "." -+#define HMAC_SUFFIX ".hmac" -+#define READ_BUFFER_LENGTH 16384 -+ -+/* -+ * The hard-coded HMAC key to be optionally provided for the library -+ * integrity test. The recommended key size for HMAC-SHA256 is 64 bytes. -+ * The known HMAC is supposed to be provided as hex string in a file -+ * libica.so.MAJOR.hmac in the same directory as the .so module. -+ */ -+static const char hmackey[] = -+ "0000000000000000000000000000000000000000000000000000000000000000" -+ "0000000000000000000000000000000000000000000000000000000000000000"; -+ - int fips; - - static int aes_ecb_kat(void); -@@ -101,6 +121,206 @@ fips_init(void) - FIPS_mode_set(1); - } - } -+static int get_library_path(const char *libname, const char *symbolname, -+ char *path, size_t pathlen) -+{ -+ Dl_info info; -+ void *dl, *sym; -+ int rc = -1; -+ -+ dl = dlopen(libname, RTLD_LAZY); -+ if (dl == NULL) -+ goto done; -+ -+ sym = dlsym(dl, symbolname); -+ if (sym != NULL && dladdr(sym, &info)) { -+ if (strlen(info.dli_fname) < pathlen) -+ strcpy(path, info.dli_fname); -+ else -+ goto done; -+ } -+ -+ rc = 0; -+ -+done: -+ if (dl != NULL) -+ dlclose(dl); -+ -+ return rc; -+} -+ -+static char *make_hmac_path(const char *origpath) -+{ -+ char *path; -+ const char *fn; -+ -+ path = calloc(1,sizeof(HMAC_PREFIX) + sizeof(HMAC_SUFFIX) + strlen(origpath) + 1); -+ if (path == NULL) -+ return NULL; -+ -+ fn = strrchr(origpath, '/'); -+ if (fn == NULL) { -+ fn = origpath; -+ } else { -+ ++fn; -+ } -+ -+ strncpy(path, origpath, fn - origpath); -+ strcat(path, HMAC_PREFIX); -+ strcat(path, fn); -+ strcat(path, HMAC_SUFFIX); -+ -+ return path; -+} -+ -+static int compute_file_hmac(const char *path, void **buf, size_t *hmaclen) -+{ -+ FILE *fp = NULL; -+ int rc = -1; -+ unsigned char rbuf[READ_BUFFER_LENGTH]; -+ unsigned char *keybuf; -+ EVP_MD_CTX *mdctx = NULL; -+ EVP_PKEY *pkey = NULL; -+ size_t hlen, len; -+ long keylen; -+ -+ keybuf = OPENSSL_hexstr2buf(hmackey, &keylen); -+ pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, keybuf, (int)keylen); -+ if (!pkey) -+ goto end; -+ -+ mdctx = EVP_MD_CTX_create(); -+ if (!mdctx) -+ goto end; -+ -+ fp = fopen(path, "r"); -+ if (fp == NULL) -+ goto end; -+ -+ if (EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey) <= 0) -+ goto end; -+ -+ while ((len = fread(rbuf, 1, sizeof(rbuf), fp)) != 0) { -+ if (EVP_DigestSignUpdate(mdctx, rbuf, len) <= 0) { -+ goto end; -+ } -+ } -+ -+ if (EVP_DigestSignFinal(mdctx, rbuf, &hlen) <= 0) -+ goto end; -+ -+ *buf = malloc(hlen); -+ if (*buf == NULL) -+ goto end; -+ -+ *hmaclen = hlen; -+ -+ memcpy(*buf, rbuf, hlen); -+ -+ rc = 0; -+ -+end: -+ -+ if (pkey != NULL) -+ EVP_PKEY_free(pkey); -+ -+ free(keybuf); -+ EVP_MD_CTX_destroy(mdctx); -+ if (fp) -+ fclose(fp); -+ -+ return rc; -+} -+ -+/** -+ * Performs the FIPS check. -+ * -+ * @return 1 if check succeeded -+ * 0 otherwise -+ */ -+static int FIPSCHECK_verify(const char *path) -+{ -+ int rc = 0; -+ FILE *fp; -+ unsigned char *hmac_buf = NULL; -+ long hmaclen; -+ char *hmacpath, *p; -+ char *hmac_str = NULL; -+ size_t n, buflen; -+ void *buf = NULL; -+ -+ hmacpath = make_hmac_path(path); -+ if (hmacpath == NULL) -+ return 0; -+ -+ fp = fopen(hmacpath, "r"); -+ if (fp == NULL) { -+ rc = 1; -+ goto end; -+ } -+ -+ if (getline(&hmac_str, &n, fp) <= 0) -+ goto end; -+ -+ if ((p = strchr(hmac_str, '\n')) != NULL) -+ *p = '\0'; -+ -+ hmac_buf = OPENSSL_hexstr2buf(hmac_str, &hmaclen); -+ -+ if (compute_file_hmac(path, &buf, &buflen) != 0) -+ goto end; -+ -+ if (memcmp(buf, hmac_buf, hmaclen) != 0) -+ goto end; -+ -+ rc = 1; -+ -+end: -+ -+ free(buf); -+ free(hmac_str); -+ free(hmacpath); -+ -+ OPENSSL_free(hmac_buf); -+ -+ if (fp) -+ fclose(fp); -+ -+ return rc; -+} -+ -+static const char msg1[] = "Libica FIPS library integrity check failed. Cannot determine library path.\n"; -+static const char msg2[] = "Libica FIPS library integrity check failed. Module %s probably corrupted.\n"; -+static const char msg3[] = "Libica FIPS library integrity check passed.\n"; -+ -+/* -+ * Perform an integrity check on libica.so by calculating an HMAC from -+ * the file contents using a static HMAC key, and comparing it to a -+ * pre-calculated HMAC in a separate file. The HMAC key and HMAC file -+ * may be provided by a Distributor when building the packet. -+ */ -+static void fips_lib_integrity_check(void) -+{ -+ int rc; -+ char path[PATH_MAX]; -+ const char *libname = "libica.so"; -+ const char *symbolname = "ica_sha256"; -+ -+ rc = get_library_path(libname, symbolname, path, sizeof(path)); -+ if (rc != 0) { -+ syslog(LOG_ERR, msg1); -+ fips |= ICA_FIPS_INTEGRITY; -+ return; -+ } -+ -+ if (!FIPSCHECK_verify(path)) { -+ syslog(LOG_ERR, msg2, path); -+ fips |= ICA_FIPS_INTEGRITY; -+ return; -+ } -+ -+ syslog(LOG_INFO, msg3); -+} - - void - fips_powerup_tests(void) -@@ -117,6 +337,9 @@ fips_powerup_tests(void) - fips |= ICA_FIPS_CRYPTOALG; - return; - } -+ -+ /* Library integrity test */ -+ fips_lib_integrity_check(); - } - - static int -@@ -933,5 +1156,4 @@ _err_: - syslog(LOG_ERR, "Libica RSA test failed."); - return 1; - } -- - #endif /* FIPS_H */ -diff --git a/src/include/fips.h b/src/include/fips.h -index 421be4c..0ffdef6 100644 ---- a/src/include/fips.h -+++ b/src/include/fips.h -@@ -27,8 +27,8 @@ extern int fips; /* module status */ - void fips_init(void); - - /* -- * Powerup tests: crypto algorithm test, SW/FW integrity test (not implemented -- * yet), critical function test (no critical functions). The tests set the -+ * Powerup tests: crypto algorithm test, SW/FW integrity test, critical -+ * function test (no critical functions). The tests set the - * corresponding status flags. - */ - void fips_powerup_tests(void); -diff --git a/test/fips_test.c b/test/fips_test.c -index 06563e3..0f1940d 100644 ---- a/test/fips_test.c -+++ b/test/fips_test.c -@@ -57,6 +57,10 @@ main(void) - printf("Libica FIPS powerup test failed.\n"); - rv = EXIT_FAILURE; - } -+ if (fips & ICA_FIPS_INTEGRITY) { -+ printf("Libica FIPS integrity check failed.\n"); -+ rv = EXIT_FAILURE; -+ } - #endif /* ICA_FIPS */ - - printf("OpenSSL version is '%s'.\n", OPENSSL_VERSION_TEXT); --- -2.16.4 - diff --git a/libica.spec b/libica.spec index e8d0cfb..2b40da2 100644 --- a/libica.spec +++ b/libica.spec @@ -1,7 +1,7 @@ # # spec file for package libica # -# Copyright (c) 2018-2020 SUSE LLC +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed