]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
fips: simplify library integrity checking
authorDaiki Ueno <ueno@gnu.org>
Thu, 31 Mar 2022 12:28:32 +0000 (14:28 +0200)
committerDaiki Ueno <ueno@gnu.org>
Thu, 31 Mar 2022 12:34:40 +0000 (14:34 +0200)
This removes code duplication by grouping the path and hmac fields in
hmac_file structure.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/fips.c
lib/fipshmac.c

index 33c903b10e70c1436e7e629b2af49311a58e4548..77b461c22e01199a7668a260535fd4318f9fa3fa 100644 (file)
@@ -25,7 +25,7 @@
 #include <unistd.h>
 #include "errors.h"
 #include "file.h"
-#include "inih/ini.h" 
+#include "inih/ini.h"
 #include <fips.h>
 #include <gnutls/self-test.h>
 #include <stdio.h>
@@ -107,7 +107,7 @@ unsigned _gnutls_fips_mode_enabled(void)
        if (fd != NULL) {
                f1p = fgetc(fd);
                fclose(fd);
-               
+
                if (f1p == '1') f1p = 1;
                else f1p = 0;
        }
@@ -156,17 +156,19 @@ void _gnutls_fips_mode_reset_zombie(void)
 #define HMAC_FILE_NAME ".gnutls.hmac"
 #define HMAC_FORMAT_VERSION 1
 
+struct hmac_entry
+{
+       char path[GNUTLS_PATH_MAX];
+       uint8_t hmac[HMAC_SIZE];
+};
+
 typedef struct
 {
        int version;
-       char gnutls_path[GNUTLS_PATH_MAX];
-       char nettle_path[GNUTLS_PATH_MAX];
-       char hogweed_path[GNUTLS_PATH_MAX];
-       char gmp_path[GNUTLS_PATH_MAX];
-       uint8_t gnutls_hmac[HMAC_SIZE];
-       uint8_t nettle_hmac[HMAC_SIZE];
-       uint8_t hogweed_hmac[HMAC_SIZE];
-       uint8_t gmp_hmac[HMAC_SIZE];
+       struct hmac_entry gnutls;
+       struct hmac_entry nettle;
+       struct hmac_entry hogweed;
+       struct hmac_entry gmp;
 } hmac_file;
 
 static int get_library_path(const char* lib, const char* symbol, char* path, size_t path_size)
@@ -184,13 +186,13 @@ static int get_library_path(const char* lib, const char* symbol, char* path, siz
                ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
                goto cleanup;
        }
-       
+
        ret = dladdr(sym, &info);
        if (ret == 0) {
                ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
                goto cleanup;
        }
-       
+
        ret = snprintf(path, path_size, "%s", info.dli_fname);
        if ((size_t)ret >= path_size) {
                ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
@@ -213,16 +215,10 @@ static int get_hmac(uint8_t *dest, const char *value)
        gnutls_datum_t data;
 
        data.size = strlen(value);
-       if (hex_data_size(data.size) != HMAC_SIZE)
-               return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
-
-       data.data = (uint8_t *)gnutls_strdup(value);
-       if (data.data == NULL)
-               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+       data.data = value;
 
        hmac_size = HMAC_SIZE;
        ret = gnutls_hex_decode(&data, dest, &hmac_size);
-       gnutls_free(data.data);
        if (ret < 0)
                return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
 
@@ -232,6 +228,21 @@ static int get_hmac(uint8_t *dest, const char *value)
        return 0;
 }
 
+static int
+lib_handler(struct hmac_entry *entry,
+           const char *section, const char *name, const char *value)
+{
+       if (!strcmp(name, "path")) {
+               snprintf(entry->path, GNUTLS_PATH_MAX, "%s", value);
+       } else if (!strcmp(name, "hmac")) {
+               if (get_hmac(entry->hmac, value) < 0)
+                       return 0;
+       } else {
+               return 0;
+       }
+       return 1;
+}
+
 static int handler(void *user, const char *section, const char *name, const char *value)
 {
        hmac_file *p = (hmac_file *)user;
@@ -243,41 +254,13 @@ static int handler(void *user, const char *section, const char *name, const char
                        return 0;
                }
        } else if (!strcmp(section, GNUTLS_LIBRARY_NAME)) {
-               if (!strcmp(name, "path")) {
-                       snprintf(p->gnutls_path, GNUTLS_PATH_MAX, "%s", value);
-               } else if (!strcmp(name, "hmac")) {
-                       if (get_hmac(p->gnutls_hmac, value) < 0)
-                               return 0;
-               } else {
-                       return 0;
-               }
+               return lib_handler(&p->gnutls, section, name, value);
        } else if (!strcmp(section, NETTLE_LIBRARY_NAME)) {
-               if (!strcmp(name, "path")) {
-                       snprintf(p->nettle_path, GNUTLS_PATH_MAX, "%s", value);
-               } else if (!strcmp(name, "hmac")) {
-                       if (get_hmac(p->nettle_hmac, value) < 0)
-                               return 0;
-               } else {
-                       return 0;
-               }
+               return lib_handler(&p->nettle, section, name, value);
        } else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) {
-               if (!strcmp(name, "path")) {
-                       snprintf(p->hogweed_path, GNUTLS_PATH_MAX, "%s", value);
-               } else if (!strcmp(name, "hmac")) {
-                       if (get_hmac(p->hogweed_hmac, value) < 0)
-                               return 0;
-               } else {
-                       return 0;
-               }
+               return lib_handler(&p->hogweed, section, name, value);
        } else if (!strcmp(section, GMP_LIBRARY_NAME)) {
-               if (!strcmp(name, "path")) {
-                       snprintf(p->gmp_path, GNUTLS_PATH_MAX, "%s", value);
-               } else if (!strcmp(name, "hmac")) {
-                       if (get_hmac(p->gmp_hmac, value) < 0)
-                               return 0;
-               } else {
-                       return 0;
-               }
+               return lib_handler(&p->gmp, section, name, value);
        } else {
                return 0;
        }
@@ -350,38 +333,30 @@ static int load_hmac_file(hmac_file *p)
        return 0;
 }
 
-static int check_lib_path(const char path[GNUTLS_PATH_MAX],
+/* Run an HMAC using the key above on the library binary data.
+ * Returns 0 on success and negative value on error.
+ */
+static int check_lib_hmac(struct hmac_entry *entry,
                          const char *lib, const char *sym)
 {
        int ret;
-       char new_path[GNUTLS_PATH_MAX];
-       
-       ret = get_library_path(lib, sym, new_path, sizeof(new_path));
+       unsigned prev;
+       char path[GNUTLS_PATH_MAX];
+       uint8_t hmac[HMAC_SIZE];
+       gnutls_datum_t data;
+
+       ret = get_library_path(lib, sym, path, sizeof(path));
        if (ret < 0) {
                _gnutls_debug_log("Could not get lib path for %s: %s\n",
                                  lib, gnutls_strerror(ret));
                return gnutls_assert_val(ret);
        }
 
-       if (strncmp(path, new_path, GNUTLS_PATH_MAX)) {
+       if (strncmp(entry->path, path, GNUTLS_PATH_MAX)) {
                _gnutls_debug_log("Library path for %s does not match with HMAC file\n", lib);
                return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
        }
 
-       return 0;
-}
-
-/* Run an HMAC using the key above on the library binary data. 
- * Returns 0 on success and negative value on error.
- */
-static int check_lib_hmac(const char path[GNUTLS_PATH_MAX],
-                         const uint8_t hmac[HMAC_SIZE])
-{
-       int ret;
-       unsigned prev;
-       uint8_t new_hmac[HMAC_SIZE];
-       gnutls_datum_t data;
-       
        _gnutls_debug_log("Loading: %s\n", path);
        ret = gnutls_load_file(path, &data);
        if (ret < 0) {
@@ -393,7 +368,7 @@ static int check_lib_hmac(const char path[GNUTLS_PATH_MAX],
        prev = _gnutls_get_lib_state();
        _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
        ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY)-1,
-               data.data, data.size, new_hmac);
+                              data.data, data.size, hmac);
        _gnutls_switch_lib_state(prev);
 
        gnutls_free(data.data);
@@ -403,12 +378,12 @@ static int check_lib_hmac(const char path[GNUTLS_PATH_MAX],
                return gnutls_assert_val(ret);
        }
 
-       if (gnutls_memcmp(hmac, new_hmac, HMAC_SIZE)) {
+       if (gnutls_memcmp(entry->hmac, hmac, HMAC_SIZE)) {
                _gnutls_debug_log("Calculated MAC for %s does not match\n", path);
                return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
        }
        _gnutls_debug_log("Successfully verified MAC for %s\n", path);
-       
+
        return 0;
 }
 
@@ -424,28 +399,16 @@ static int check_binary_integrity(void)
                return ret;
        }
 
-       ret = check_lib_path(file.gnutls_path, GNUTLS_LIBRARY_NAME, "gnutls_global_init");
-       if (ret < 0)
-               return ret;
-       ret = check_lib_hmac(file.gnutls_path, file.gnutls_hmac);
-       if (ret < 0)
-               return ret;
-       ret = check_lib_path(file.nettle_path, NETTLE_LIBRARY_NAME, "nettle_aes_set_encrypt_key");
-       if (ret < 0)
-               return ret;
-       ret = check_lib_hmac(file.nettle_path, file.nettle_hmac);
-       if (ret < 0)
-               return ret;
-       ret = check_lib_path(file.hogweed_path, HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
+       ret = check_lib_hmac(&file.gnutls, GNUTLS_LIBRARY_NAME, "gnutls_global_init");
        if (ret < 0)
                return ret;
-       ret = check_lib_hmac(file.hogweed_path, file.hogweed_hmac);
+       ret = check_lib_hmac(&file.nettle, NETTLE_LIBRARY_NAME, "nettle_aes_set_encrypt_key");
        if (ret < 0)
                return ret;
-       ret = check_lib_path(file.gmp_path, GMP_LIBRARY_NAME, "__gmpz_init");
+       ret = check_lib_hmac(&file.hogweed, HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
        if (ret < 0)
                return ret;
-       ret = check_lib_hmac(file.gmp_path, file.gmp_hmac);
+       ret = check_lib_hmac(&file.gmp, GMP_LIBRARY_NAME, "__gmpz_init");
        if (ret < 0)
                return ret;
 
index a75035fd73905b5337464289293d4f8a40a2ecbd..91ee1d6579b9581417f6a0d2d53b4947988965cb 100644 (file)
@@ -50,13 +50,13 @@ static int get_path(const char *lib, const char *symbol, char *path, size_t path
                ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
                goto cleanup;
        }
-       
+
        ret = dladdr(sym, &info);
        if (ret == 0) {
                ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
                goto cleanup;
        }
-       
+
        ret = snprintf(path, path_size, "%s", info.dli_fname);
        if ((size_t)ret >= path_size) {
                ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);