diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2006-01-06 03:12:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:33:40 -0500 |
commit | f2d97f02961e8b1f8a24befb88ab0e5c886586ff (patch) | |
tree | 2b8909cf8024413134785cba06df858c0ede4bca /kernel/power/swsusp.c | |
parent | 0595bf3bca9d9932a05b06dd438f40f01d27cd33 (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.c | 163 |
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; } | |||
81 | static int restore_highmem(void) { return 0; } | 74 | static 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 | |||
88 | extern char resume_file[]; | 77 | extern 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 | ||
104 | static struct swsusp_header { | 93 | static 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; | |||
123 | static unsigned short swapfile_used[MAX_SWAPFILES]; | 111 | static unsigned short swapfile_used[MAX_SWAPFILES]; |
124 | static unsigned short root_swap; | 112 | static unsigned short root_swap; |
125 | 113 | ||
126 | static int write_page(unsigned long addr, swp_entry_t *loc); | ||
127 | static int bio_read_page(pgoff_t page_off, void *page); | ||
128 | |||
129 | static u8 key_iv[MAXKEY+MAXIV]; | ||
130 | |||
131 | #ifdef CONFIG_SWSUSP_ENCRYPT | ||
132 | |||
133 | static 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 | |||
182 | fail: crypto_free_tfm(tfm); | ||
183 | out: return error; | ||
184 | } | ||
185 | |||
186 | static __inline__ void crypto_exit(void *mem) | ||
187 | { | ||
188 | crypto_free_tfm((struct crypto_tfm *)mem); | ||
189 | } | ||
190 | |||
191 | static __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 | |||
212 | static __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 | ||
231 | static __inline__ int crypto_init(int mode, void *mem) | ||
232 | { | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static __inline__ void crypto_exit(void *mem) | ||
237 | { | ||
238 | } | ||
239 | |||
240 | static __inline__ int crypto_write(struct pbe *p, void *mem) | ||
241 | { | ||
242 | return write_page(p->address, &(p->swap_address)); | ||
243 | } | ||
244 | |||
245 | static __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 | |||
251 | static int mark_swapfiles(swp_entry_t prev) | 114 | static 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"); |