diff --git a/arch/x86/power/hibernate_keys.c b/arch/x86/power/hibernate_keys.c
index f44823e..5e92101 100644
--- a/arch/x86/power/hibernate_keys.c
+++ b/arch/x86/power/hibernate_keys.c
@@ -19,6 +19,15 @@ static u64 keys_phys_addr;
 /* A page used to keep hibernation keys */
 static struct hibernation_keys *hibernation_keys;
 
+/* Forward information and keys from boot kernel to image kernel */
+struct forward_info {
+	bool            sig_enforce;
+	int             sig_verify_ret;
+	struct hibernation_keys hibernation_keys;
+};
+
+static struct forward_info *forward_buff;
+
 void __init parse_hibernation_keys(u64 phys_addr, u32 data_len)
 {
 	struct setup_data *hibernation_setup_data;
@@ -62,6 +71,55 @@ bool swsusp_page_is_keys(struct page *page)
 	return ret;
 }
 
+unsigned long get_forward_buff_pfn(void)
+{
+	if (!forward_buff)
+		return 0;
+
+	return page_to_pfn(virt_to_page(forward_buff));
+}
+
+void fill_forward_info(void *forward_buff_page, int verify_ret)
+{
+	struct forward_info *info;
+
+	if (!forward_buff_page)
+		return;
+
+	memset(forward_buff_page, 0, PAGE_SIZE);
+	info = (struct forward_info *)forward_buff_page;
+	info->sig_verify_ret = verify_ret;
+
+	if (hibernation_keys && !hibernation_keys->hkey_status) {
+		info->hibernation_keys = *hibernation_keys;
+		memset(hibernation_keys, 0, PAGE_SIZE);
+	} else
+		pr_info("PM: Fill hibernation keys failed\n");
+
+	pr_info("PM: Filled sign information to forward buffer\n");
+}
+
+void restore_sig_forward_info(void)
+{
+	if (!forward_buff) {
+		pr_warn("PM: Did not allocate forward buffer\n");
+		return;
+	}
+
+	if (forward_buff->sig_verify_ret)
+		pr_warn("PM: Signature verifying failed: %d\n",
+			forward_buff->sig_verify_ret);
+
+	if (hibernation_keys) {
+		memset(hibernation_keys, 0, PAGE_SIZE);
+		*hibernation_keys = forward_buff->hibernation_keys;
+		pr_info("PM: Restored hibernation keys\n");
+	}
+
+	/* clean forward information buffer for next round */
+	memset(forward_buff, 0, PAGE_SIZE);
+}
+
 static int __init init_hibernation_keys(void)
 {
 	struct hibernation_keys *keys;
@@ -76,6 +134,11 @@ static int __init init_hibernation_keys(void)
 	hibernation_keys = (struct hibernation_keys *)get_zeroed_page(GFP_KERNEL);
 	if (hibernation_keys) {
 		*hibernation_keys = *keys;
+		forward_buff = (struct forward_info *)get_zeroed_page(GFP_KERNEL);
+		if (!forward_buff) {
+			pr_err("PM: Allocate forward buffer failed\n");
+			ret = -ENOMEM;
+		}
 	} else {
 		pr_err("PM: Allocate hibernation keys page failed\n");
 		ret = -ENOMEM;
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 690f78f..640ca8a 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -702,6 +702,7 @@ int hibernate(void)
 		pm_restore_gfp_mask();
 	} else {
 		pr_debug("PM: Image restored successfully.\n");
+		restore_sig_forward_info();
 	}
 
  Free_bitmaps:
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 6d1d406..1ea3513 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -13,6 +13,7 @@ struct swsusp_info {
 	unsigned long		image_pages;
 	unsigned long		pages;
 	unsigned long		size;
+	unsigned long		forward_buff_pfn;
 	u8                      signature[HIBERNATION_DIGEST_SIZE];
 } __aligned(PAGE_SIZE);
 
@@ -20,8 +21,13 @@ struct swsusp_info {
 /* arch/x86/power/hibernate_keys.c */
 extern int get_hibernation_key(u8 **hkey);
 extern bool swsusp_page_is_keys(struct page *page);
+extern unsigned long get_forward_buff_pfn(void);
+extern void fill_forward_info(void *forward_buff_page, int verify_ret);
+extern void restore_sig_forward_info(void);
 #else
 static inline bool swsusp_page_is_keys(struct page *page) { return false; }
+static inline unsigned long get_forward_buff_pfn(void) { return 0; }
+static inline void restore_sig_forward_info(void) {}
 #endif
 
 /* kernel/power/snapshot.c */
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 5522028..3629249 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -1281,6 +1281,14 @@ static unsigned int nr_copy_pages;
  */
 static u8 signature[HIBERNATION_DIGEST_SIZE];
 
+/*
+ * Keep the pfn of forwarding information buffer from resume target.
+ * Writing hibernation keys to this buffer in snapshot image before restoring.
+ */
+unsigned long forward_buff_pfn;
+
+void *forward_buff;
+
 /* Buffer point array for collecting address of page buffers */
 void **h_buf;
 
@@ -1383,13 +1391,24 @@ error_key:
 	return ret;
 }
 
+static void snapshot_fill_sig_forward_info(int verify_ret)
+{
+	if (!forward_buff_pfn || !forward_buff) {
+		pr_err("PM: Did not find forward buffer\n");
+		return;
+	}
+
+	/* Fill hibernation keys to snapshot in memory for next round */
+	fill_forward_info(forward_buff, verify_ret);
+}
+
 int snapshot_image_verify(void)
 {
 	struct crypto_shash *tfm;
 	struct shash_desc *desc;
 	u8 *key, *digest;
 	size_t digest_size, desc_size;
-	int ret, i;
+	int i, ret = 0;
 
 	if (!h_buf)
 		return 0;
@@ -1450,6 +1469,7 @@ error_digest:
 forward_ret:
 	if (ret)
 		pr_warn("PM: Signature verifying failed: %d\n", ret);
+	snapshot_fill_sig_forward_info(ret);
 	return ret;
 }
 
@@ -2126,6 +2146,7 @@ static int init_header(struct swsusp_info *info)
 	info->pages = snapshot_get_image_size();
 	info->size = info->pages;
 	info->size <<= PAGE_SHIFT;
+	info->forward_buff_pfn = get_forward_buff_pfn();
 	memcpy(info->signature, signature, HIBERNATION_DIGEST_SIZE);
 	return init_header_complete(info);
 }
@@ -2289,6 +2310,7 @@ load_header(struct swsusp_info *info)
 	if (!error) {
 		nr_copy_pages = info->image_pages;
 		nr_meta_pages = info->pages - info->image_pages - 1;
+		forward_buff_pfn = info->forward_buff_pfn;
 		memset(signature, 0, HIBERNATION_DIGEST_SIZE);
 		memcpy(signature, info->signature, HIBERNATION_DIGEST_SIZE);
 	}
@@ -2757,6 +2779,9 @@ int snapshot_write_next(struct snapshot_handle *handle)
 			handle->sync_read = 0;
 		if (h_buf)
 			*(h_buf + (handle->cur - nr_meta_pages - 1)) = handle->buffer;
+		/* Keep the buffer of hibernation keys in snapshot */
+		if (forward_buff_pfn && pfn == forward_buff_pfn)
+			forward_buff = handle->buffer;
 	}
 	handle->cur++;
 	return PAGE_SIZE;
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 9b891d5..ffd327a 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -241,6 +241,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
 		if (!data->frozen || data->ready)
 			break;
 		pm_restore_gfp_mask();
+		restore_sig_forward_info();
 		free_basic_memory_bitmaps();
 		data->free_bitmaps = false;
 		thaw_processes();
