aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/swsusp.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2006-01-06 03:12:24 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:40 -0500
commitf2d97f02961e8b1f8a24befb88ab0e5c886586ff (patch)
tree2b8909cf8024413134785cba06df858c0ede4bca /kernel/power/swsusp.c
parent0595bf3bca9d9932a05b06dd438f40f01d27cd33 (diff)
[PATCH] swsusp: remove encryption
This patch removes the image encryption that is only used by swsusp instead of zeroing the image after resume in order to prevent someone from reading some confidential data from it in the future and it does not protect the image from being read by an unauthorized person before resume. The functionality it provides should really belong to the user space and will possibly be reimplemented after the swap-handling functionality of swsusp is moved to the user space. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@suse.cz> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/power/swsusp.c')
-rw-r--r--kernel/power/swsusp.c163
1 files changed, 4 insertions, 159 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index c05f46e7348f..bd3097c583bf 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -30,9 +30,6 @@
30 * Alex Badea <vampire@go.ro>: 30 * Alex Badea <vampire@go.ro>:
31 * Fixed runaway init 31 * Fixed runaway init
32 * 32 *
33 * Andreas Steinmetz <ast@domdv.de>:
34 * Added encrypted suspend option
35 *
36 * More state savers are welcome. Especially for the scsi layer... 33 * More state savers are welcome. Especially for the scsi layer...
37 * 34 *
38 * For TODOs,FIXMEs also look in Documentation/power/swsusp.txt 35 * For TODOs,FIXMEs also look in Documentation/power/swsusp.txt
@@ -67,10 +64,6 @@
67#include <asm/tlbflush.h> 64#include <asm/tlbflush.h>
68#include <asm/io.h> 65#include <asm/io.h>
69 66
70#include <linux/random.h>
71#include <linux/crypto.h>
72#include <asm/scatterlist.h>
73
74#include "power.h" 67#include "power.h"
75 68
76#ifdef CONFIG_HIGHMEM 69#ifdef CONFIG_HIGHMEM
@@ -81,10 +74,6 @@ static int save_highmem(void) { return 0; }
81static int restore_highmem(void) { return 0; } 74static int restore_highmem(void) { return 0; }
82#endif 75#endif
83 76
84#define CIPHER "aes"
85#define MAXKEY 32
86#define MAXIV 32
87
88extern char resume_file[]; 77extern char resume_file[];
89 78
90/* Local variables that should not be affected by save */ 79/* Local variables that should not be affected by save */
@@ -102,8 +91,7 @@ suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
102#define SWSUSP_SIG "S1SUSPEND" 91#define SWSUSP_SIG "S1SUSPEND"
103 92
104static struct swsusp_header { 93static struct swsusp_header {
105 char reserved[PAGE_SIZE - 20 - MAXKEY - MAXIV - sizeof(swp_entry_t)]; 94 char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
106 u8 key_iv[MAXKEY+MAXIV];
107 swp_entry_t swsusp_info; 95 swp_entry_t swsusp_info;
108 char orig_sig[10]; 96 char orig_sig[10];
109 char sig[10]; 97 char sig[10];
@@ -123,131 +111,6 @@ static struct swsusp_info swsusp_info;
123static unsigned short swapfile_used[MAX_SWAPFILES]; 111static unsigned short swapfile_used[MAX_SWAPFILES];
124static unsigned short root_swap; 112static unsigned short root_swap;
125 113
126static int write_page(unsigned long addr, swp_entry_t *loc);
127static int bio_read_page(pgoff_t page_off, void *page);
128
129static u8 key_iv[MAXKEY+MAXIV];
130
131#ifdef CONFIG_SWSUSP_ENCRYPT
132
133static int crypto_init(int mode, void **mem)
134{
135 int error = 0;
136 int len;
137 char *modemsg;
138 struct crypto_tfm *tfm;
139
140 modemsg = mode ? "suspend not possible" : "resume not possible";
141
142 tfm = crypto_alloc_tfm(CIPHER, CRYPTO_TFM_MODE_CBC);
143 if(!tfm) {
144 printk(KERN_ERR "swsusp: no tfm, %s\n", modemsg);
145 error = -EINVAL;
146 goto out;
147 }
148
149 if(MAXKEY < crypto_tfm_alg_min_keysize(tfm)) {
150 printk(KERN_ERR "swsusp: key buffer too small, %s\n", modemsg);
151 error = -ENOKEY;
152 goto fail;
153 }
154
155 if (mode)
156 get_random_bytes(key_iv, MAXKEY+MAXIV);
157
158 len = crypto_tfm_alg_max_keysize(tfm);
159 if (len > MAXKEY)
160 len = MAXKEY;
161
162 if (crypto_cipher_setkey(tfm, key_iv, len)) {
163 printk(KERN_ERR "swsusp: key setup failure, %s\n", modemsg);
164 error = -EKEYREJECTED;
165 goto fail;
166 }
167
168 len = crypto_tfm_alg_ivsize(tfm);
169
170 if (MAXIV < len) {
171 printk(KERN_ERR "swsusp: iv buffer too small, %s\n", modemsg);
172 error = -EOVERFLOW;
173 goto fail;
174 }
175
176 crypto_cipher_set_iv(tfm, key_iv+MAXKEY, len);
177
178 *mem=(void *)tfm;
179
180 goto out;
181
182fail: crypto_free_tfm(tfm);
183out: return error;
184}
185
186static __inline__ void crypto_exit(void *mem)
187{
188 crypto_free_tfm((struct crypto_tfm *)mem);
189}
190
191static __inline__ int crypto_write(struct pbe *p, void *mem)
192{
193 int error = 0;
194 struct scatterlist src, dst;
195
196 src.page = virt_to_page(p->address);
197 src.offset = 0;
198 src.length = PAGE_SIZE;
199 dst.page = virt_to_page((void *)&swsusp_header);
200 dst.offset = 0;
201 dst.length = PAGE_SIZE;
202
203 error = crypto_cipher_encrypt((struct crypto_tfm *)mem, &dst, &src,
204 PAGE_SIZE);
205
206 if (!error)
207 error = write_page((unsigned long)&swsusp_header,
208 &(p->swap_address));
209 return error;
210}
211
212static __inline__ int crypto_read(struct pbe *p, void *mem)
213{
214 int error = 0;
215 struct scatterlist src, dst;
216
217 error = bio_read_page(swp_offset(p->swap_address), (void *)p->address);
218 if (!error) {
219 src.offset = 0;
220 src.length = PAGE_SIZE;
221 dst.offset = 0;
222 dst.length = PAGE_SIZE;
223 src.page = dst.page = virt_to_page((void *)p->address);
224
225 error = crypto_cipher_decrypt((struct crypto_tfm *)mem, &dst,
226 &src, PAGE_SIZE);
227 }
228 return error;
229}
230#else
231static __inline__ int crypto_init(int mode, void *mem)
232{
233 return 0;
234}
235
236static __inline__ void crypto_exit(void *mem)
237{
238}
239
240static __inline__ int crypto_write(struct pbe *p, void *mem)
241{
242 return write_page(p->address, &(p->swap_address));
243}
244
245static __inline__ int crypto_read(struct pbe *p, void *mem)
246{
247 return bio_read_page(swp_offset(p->swap_address), (void *)p->address);
248}
249#endif
250
251static int mark_swapfiles(swp_entry_t prev) 114static int mark_swapfiles(swp_entry_t prev)
252{ 115{
253 int error; 116 int error;
@@ -259,7 +122,6 @@ static int mark_swapfiles(swp_entry_t prev)
259 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { 122 !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
260 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); 123 memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
261 memcpy(swsusp_header.sig,SWSUSP_SIG, 10); 124 memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
262 memcpy(swsusp_header.key_iv, key_iv, MAXKEY+MAXIV);
263 swsusp_header.swsusp_info = prev; 125 swsusp_header.swsusp_info = prev;
264 error = rw_swap_page_sync(WRITE, 126 error = rw_swap_page_sync(WRITE,
265 swp_entry(root_swap, 0), 127 swp_entry(root_swap, 0),
@@ -405,10 +267,6 @@ static int data_write(void)
405 int error = 0, i = 0; 267 int error = 0, i = 0;
406 unsigned int mod = nr_copy_pages / 100; 268 unsigned int mod = nr_copy_pages / 100;
407 struct pbe *p; 269 struct pbe *p;
408 void *tfm;
409
410 if ((error = crypto_init(1, &tfm)))
411 return error;
412 270
413 if (!mod) 271 if (!mod)
414 mod = 1; 272 mod = 1;
@@ -417,14 +275,11 @@ static int data_write(void)
417 for_each_pbe (p, pagedir_nosave) { 275 for_each_pbe (p, pagedir_nosave) {
418 if (!(i%mod)) 276 if (!(i%mod))
419 printk( "\b\b\b\b%3d%%", i / mod ); 277 printk( "\b\b\b\b%3d%%", i / mod );
420 if ((error = crypto_write(p, tfm))) { 278 if ((error = write_page(p->address, &p->swap_address)))
421 crypto_exit(tfm);
422 return error; 279 return error;
423 }
424 i++; 280 i++;
425 } 281 }
426 printk("\b\b\b\bdone\n"); 282 printk("\b\b\b\bdone\n");
427 crypto_exit(tfm);
428 return error; 283 return error;
429} 284}
430 285
@@ -550,7 +405,6 @@ static int write_suspend_image(void)
550 if ((error = close_swap())) 405 if ((error = close_swap()))
551 goto FreePagedir; 406 goto FreePagedir;
552 Done: 407 Done:
553 memset(key_iv, 0, MAXKEY+MAXIV);
554 return error; 408 return error;
555 FreePagedir: 409 FreePagedir:
556 free_pagedir_entries(); 410 free_pagedir_entries();
@@ -812,8 +666,6 @@ static int check_sig(void)
812 return error; 666 return error;
813 if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { 667 if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
814 memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); 668 memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
815 memcpy(key_iv, swsusp_header.key_iv, MAXKEY+MAXIV);
816 memset(swsusp_header.key_iv, 0, MAXKEY+MAXIV);
817 669
818 /* 670 /*
819 * Reset swap signature now. 671 * Reset swap signature now.
@@ -840,10 +692,6 @@ static int data_read(struct pbe *pblist)
840 int error = 0; 692 int error = 0;
841 int i = 0; 693 int i = 0;
842 int mod = swsusp_info.image_pages / 100; 694 int mod = swsusp_info.image_pages / 100;
843 void *tfm;
844
845 if ((error = crypto_init(0, &tfm)))
846 return error;
847 695
848 if (!mod) 696 if (!mod)
849 mod = 1; 697 mod = 1;
@@ -855,15 +703,13 @@ static int data_read(struct pbe *pblist)
855 if (!(i % mod)) 703 if (!(i % mod))
856 printk("\b\b\b\b%3d%%", i / mod); 704 printk("\b\b\b\b%3d%%", i / mod);
857 705
858 if ((error = crypto_read(p, tfm))) { 706 if ((error = bio_read_page(swp_offset(p->swap_address),
859 crypto_exit(tfm); 707 (void *)p->address)))
860 return error; 708 return error;
861 }
862 709
863 i++; 710 i++;
864 } 711 }
865 printk("\b\b\b\bdone\n"); 712 printk("\b\b\b\bdone\n");
866 crypto_exit(tfm);
867 return error; 713 return error;
868} 714}
869 715
@@ -986,7 +832,6 @@ int swsusp_read(void)
986 832
987 error = read_suspend_image(); 833 error = read_suspend_image();
988 blkdev_put(resume_bdev); 834 blkdev_put(resume_bdev);
989 memset(key_iv, 0, MAXKEY+MAXIV);
990 835
991 if (!error) 836 if (!error)
992 pr_debug("swsusp: Reading resume file was successful\n"); 837 pr_debug("swsusp: Reading resume file was successful\n");