1313#include <linux/kdebug.h>
1414#include <linux/cpu.h>
1515#include <linux/pgtable.h>
16-
17- #include <crypto/hash .h>
16+ #include <linux/types.h>
17+ #include <linux/crc32 .h>
1818
1919#include <asm/e820/api.h>
2020#include <asm/init.h>
@@ -54,95 +54,33 @@ int pfn_is_nosave(unsigned long pfn)
5454 return pfn >= nosave_begin_pfn && pfn < nosave_end_pfn ;
5555}
5656
57-
58- #define MD5_DIGEST_SIZE 16
59-
6057struct restore_data_record {
6158 unsigned long jump_address ;
6259 unsigned long jump_address_phys ;
6360 unsigned long cr3 ;
6461 unsigned long magic ;
65- u8 e820_digest [ MD5_DIGEST_SIZE ] ;
62+ unsigned long e820_checksum ;
6663};
6764
68- #if IS_BUILTIN (CONFIG_CRYPTO_MD5 )
6965/**
70- * get_e820_md5 - calculate md5 according to given e820 table
66+ * compute_e820_crc32 - calculate crc32 of a given e820 table
7167 *
7268 * @table: the e820 table to be calculated
73- * @buf: the md5 result to be stored to
69+ *
70+ * Return: the resulting checksum
7471 */
75- static int get_e820_md5 (struct e820_table * table , void * buf )
72+ static inline u32 compute_e820_crc32 (struct e820_table * table )
7673{
77- struct crypto_shash * tfm ;
78- struct shash_desc * desc ;
79- int size ;
80- int ret = 0 ;
81-
82- tfm = crypto_alloc_shash ("md5" , 0 , 0 );
83- if (IS_ERR (tfm ))
84- return - ENOMEM ;
85-
86- desc = kmalloc (sizeof (struct shash_desc ) + crypto_shash_descsize (tfm ),
87- GFP_KERNEL );
88- if (!desc ) {
89- ret = - ENOMEM ;
90- goto free_tfm ;
91- }
92-
93- desc -> tfm = tfm ;
94-
95- size = offsetof(struct e820_table , entries ) +
74+ int size = offsetof(struct e820_table , entries ) +
9675 sizeof (struct e820_entry ) * table -> nr_entries ;
9776
98- if (crypto_shash_digest (desc , (u8 * )table , size , buf ))
99- ret = - EINVAL ;
100-
101- kfree_sensitive (desc );
102-
103- free_tfm :
104- crypto_free_shash (tfm );
105- return ret ;
106- }
107-
108- static int hibernation_e820_save (void * buf )
109- {
110- return get_e820_md5 (e820_table_firmware , buf );
111- }
112-
113- static bool hibernation_e820_mismatch (void * buf )
114- {
115- int ret ;
116- u8 result [MD5_DIGEST_SIZE ];
117-
118- memset (result , 0 , MD5_DIGEST_SIZE );
119- /* If there is no digest in suspend kernel, let it go. */
120- if (!memcmp (result , buf , MD5_DIGEST_SIZE ))
121- return false;
122-
123- ret = get_e820_md5 (e820_table_firmware , result );
124- if (ret )
125- return true;
126-
127- return memcmp (result , buf , MD5_DIGEST_SIZE ) ? true : false;
128- }
129- #else
130- static int hibernation_e820_save (void * buf )
131- {
132- return 0 ;
133- }
134-
135- static bool hibernation_e820_mismatch (void * buf )
136- {
137- /* If md5 is not builtin for restore kernel, let it go. */
138- return false;
77+ return ~crc32_le (~0 , (unsigned char const * )table , size );
13978}
140- #endif
14179
14280#ifdef CONFIG_X86_64
143- #define RESTORE_MAGIC 0x23456789ABCDEF01UL
81+ #define RESTORE_MAGIC 0x23456789ABCDEF02UL
14482#else
145- #define RESTORE_MAGIC 0x12345678UL
83+ #define RESTORE_MAGIC 0x12345679UL
14684#endif
14785
14886/**
@@ -179,7 +117,8 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size)
179117 */
180118 rdr -> cr3 = restore_cr3 & ~CR3_PCID_MASK ;
181119
182- return hibernation_e820_save (rdr -> e820_digest );
120+ rdr -> e820_checksum = compute_e820_crc32 (e820_table_firmware );
121+ return 0 ;
183122}
184123
185124/**
@@ -200,7 +139,7 @@ int arch_hibernation_header_restore(void *addr)
200139 jump_address_phys = rdr -> jump_address_phys ;
201140 restore_cr3 = rdr -> cr3 ;
202141
203- if (hibernation_e820_mismatch ( rdr -> e820_digest )) {
142+ if (rdr -> e820_checksum != compute_e820_crc32 ( e820_table_firmware )) {
204143 pr_crit ("Hibernate inconsistent memory map detected!\n" );
205144 return - ENODEV ;
206145 }
0 commit comments