On Mon, Apr 12, 2021 at 10:09:32AM -0400, Chris von Recklinghausen wrote:
Suspend fails on a system in fips mode because md5 is used for the e820This still doesn't actually explain why a non-cryptographic checksum is
integrity check and is not available. Use crc32 instead.
This patch changes the integrity check algorithm from md5 to crc32.
The purpose of the integrity check is to detect possible differences
between the memory map used at the time when the hibernation image is
about to be loaded into memory and the memory map used at the image
creation time, because it is generally unsafe to load the image if the
current memory map doesn't match the one used when it was created. so
it is not intended as a cryptographic integrity check.
sufficient. "Detection of possible differences" could very well require
cryptographic authentication; it depends on whether malicious changes need to be
detected or not.
Fixes: 62a03defeabd ("PM / hibernate: Verify the consistent of e820 memory mapcrypto/hash.h is no longer needed.
by md5 digest")
Signed-off-by: Chris von Recklinghausen <crecklin@xxxxxxxxxx>
---
v1 -> v2
bump up RESTORE_MAGIC
v2 -> v3
move embelishment from cover letter to commit comments (no code change)
v3 -> v4
add note to comments that md5 isn't used for encryption here.
v4 -> v5
reword comment per Simo's suggestion
v5 -> v6
use wording from Eric Biggers, use crc32_le instead of crc32 from crypto
framework (crc32_le is in the core API and removes need for #defines)
arch/x86/power/hibernate.c | 76 +++++++++++---------------------------
1 file changed, 22 insertions(+), 54 deletions(-)
diff --git a/arch/x86/power/hibernate.c b/arch/x86/power/hibernate.c
index cd3914fc9f3d..f39e507e34ca 100644
--- a/arch/x86/power/hibernate.c
+++ b/arch/x86/power/hibernate.c
@@ -13,6 +13,8 @@
#include <linux/kdebug.h>
#include <linux/cpu.h>
#include <linux/pgtable.h>
+#include <linux/types.h>
+#include <linux/crc32.h>
#include <crypto/hash.h>
@@ -55,94 +57,60 @@ int pfn_is_nosave(unsigned long pfn)It would be simpler to just make this field 'unsigned long'. Then there would
}
-#define MD5_DIGEST_SIZE 16
+#define CRC32_DIGEST_SIZE (sizeof (u32))
struct restore_data_record {
unsigned long jump_address;
unsigned long jump_address_phys;
unsigned long cr3;
unsigned long magic;
- u8 e820_digest[MD5_DIGEST_SIZE];
+ u8 e820_digest[CRC32_DIGEST_SIZE];
};
be no need to deal with memcpy().
-#if IS_BUILTIN(CONFIG_CRYPTO_MD5)Calling this "compute_e820_crc32()" would avoid confusion with retrieving the
/**
- * get_e820_md5 - calculate md5 according to given e820 table
+ * get_e820_crc32 - calculate crc32 according to given e820 table
previously-stored crc32 value.
+ ret = crc32_le(0, (unsigned char const *)table, size);It would be better to do ~crc32_le(~0, ...) (i.e., invert at beginning and end)
to match the recommended usage of CRC-32. Unfortunately the library function
doesn't do the inversions by default.
static int hibernation_e820_save(void *buf)This should be inlined into arch_hibernation_header_save(). Also note that it
{
- return get_e820_md5(e820_table_firmware, buf);
+ return get_e820_crc32(e820_table_firmware, buf);
}
can no longer fail.
static bool hibernation_e820_mismatch(void *buf)This should be inlined into arch_hibernation_header_restore().
{
int ret;There's no need to handle the "no digest" case anymore, right? Since crc32_le()
- u8 result[MD5_DIGEST_SIZE];
+ u8 result[CRC32_DIGEST_SIZE];
- memset(result, 0, MD5_DIGEST_SIZE);
+ memset(result, 0, CRC32_DIGEST_SIZE);
/* If there is no digest in suspend kernel, let it go. */
- if (!memcmp(result, buf, MD5_DIGEST_SIZE))
+ if (!memcmp(result, buf, CRC32_DIGEST_SIZE))
return false;
is always available.
- Eric