File hmac.patch of Package gnutls

Index: gnutls-3.8.6/lib/fips.c
===================================================================
--- gnutls-3.8.6.orig/lib/fips.c
+++ gnutls-3.8.6/lib/fips.c
@@ -349,6 +349,13 @@ static int load_hmac_file(struct hmac_fi
  *
  * Verify that HMAC from hmac file entry matches HMAC of given library.
  *
+ * This check can fail if any of the dynamically linked libraries
+ * (libgnutls, libnettle, lighogweed or libgmp) gets updated as the
+ * calculated HMAC during build time will differ from the stored
+ * values in the gnutls HMAC file called .libgnutls.so.<soname>.hmac.
+ * In this case, we compare the calculated HMAC with the provided by
+ * each library and named .<libname>.so.<soname>.hmac.
+ *
  * Returns: 0 on successful HMAC verification, a negative error code otherwise
  */
 static int check_lib_hmac(struct hmac_entry *entry, const char *path)
@@ -357,6 +364,9 @@ static int check_lib_hmac(struct hmac_en
 	unsigned prev;
 	uint8_t hmac[HMAC_SIZE];
 	gnutls_datum_t data;
+	char hmac_path[GNUTLS_PATH_MAX];
+	uint8_t lib_hmac[HMAC_SIZE];
+	size_t lib_hmac_size;
 
 	_gnutls_debug_log("Loading: %s\n", path);
 	ret = gnutls_load_file(path, &data);
@@ -379,11 +389,45 @@ static int check_lib_hmac(struct hmac_en
 		return gnutls_assert_val(ret);
 	}
 
-	if (gnutls_memcmp(entry->hmac, hmac, HMAC_SIZE)) {
-		_gnutls_debug_log("Calculated MAC for %s does not match\n",
-				  path);
+	ret = gnutls_memcmp(entry->hmac, hmac, HMAC_SIZE);
+	if (ret) {
+		/* Check now the integrity of the hmac provided by the library */
+		ret = get_hmac_path(hmac_path, sizeof(hmac_path), path);
+		if (ret < 0) {
+			_gnutls_debug_log("Could not get hmac file path: %s\n",
+							  gnutls_strerror(ret));
+			return ret;
+		}
+		_gnutls_debug_log("Loading: %s\n", hmac_path);
+		ret = gnutls_load_file(hmac_path, &data);
+		if (ret < 0) {
+			_gnutls_debug_log("Could not load %s: %s\n", hmac_path,
+							  gnutls_strerror(ret));
+			return gnutls_assert_val(ret);
+		}
+		// lib_hmac_size = HMAC_SIZE;
+		lib_hmac_size = hex_data_size(data.size);
+		/* trim eventual newlines from the end of the data read from file */
+		while ((data.size > 0) && (data.data[data.size - 1] == '\n')) {
+			data.data[data.size - 1] = 0;
+			data.size--;
+		}
+		ret = gnutls_hex_decode(&data, lib_hmac, &lib_hmac_size);
+		gnutls_free(data.data);
+		if (ret < 0) {
+			_gnutls_debug_log("Could not hex decode hmac\n");
+			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+		}
+		ret = gnutls_memcmp(lib_hmac, hmac, HMAC_SIZE);
+		if (ret){
+			_gnutls_debug_log("Calculated MAC for %s does not match\n",
+							  path);
+			gnutls_memset(hmac, 0, HMAC_SIZE);
+			gnutls_memset(lib_hmac, 0, HMAC_SIZE);
+			return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+		}
 		gnutls_memset(hmac, 0, HMAC_SIZE);
-		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+		gnutls_memset(lib_hmac, 0, HMAC_SIZE);
 	}
 	_gnutls_debug_log("Successfully verified MAC for %s\n", path);
 
openSUSE Build Service is sponsored by