4
* Image loading for s2disk/s2both and resume.
6
* Copyright (C) 2008 Rafael J. Wysocki <rjw@sisk.pl>
8
* This file is released under the GPLv2.
12
#include <sys/types.h>
14
#include <sys/ioctl.h>
26
#ifdef CONFIG_COMPRESS
27
#include <lzo/lzo1x.h>
37
static char verify_checksum;
38
#ifdef CONFIG_COMPRESS
39
unsigned int compress_buf_size;
40
static char do_decompress;
42
#define do_decompress 0
45
static char do_decrypt;
46
static char password[PASSBUF_SIZE];
52
* read_page - Read data from a swap location
53
* @fd: File handle of the resume partition.
54
* @buf: Pointer to the area we're reading into.
55
* @offset: Swap offset of the place to read from.
57
static int read_page(int fd, void *buf, loff_t offset)
65
if (lseek(fd, offset, SEEK_SET) == offset)
66
cnt = read(fd, buf, page_size);
67
if (cnt < (ssize_t)page_size)
74
* The swap_reader structure is used for handling swap in a file-alike way.
76
* @extents: Array of extents used for trackig swap allocations. It is
77
* page_size bytes large and holds at most
78
* (page_size / sizeof(struct extent) - 1) extents. The last slot
79
* must be all zeros and is the end marker.
81
* @cur_extent: The extent currently used as the source of swap pages.
83
* @cur_offset: The offset of the swap page that will be used next.
85
* @total_size: The amount of data to read.
87
* @buffer: Buffer used for storing image data pages.
89
* @read_buffer: If compression is used, the compressed contents of
90
* @buffer are stored here. Otherwise, it is equal to
93
* @fd: File handle associated with the swap.
95
* @ctx: Used for checksum computing, if so configured.
97
* @lzo_work_buffer: Work buffer used for decompression.
99
* @decrypt_buffer: Buffer for storing encrypted pages (page_size bytes).
102
struct extent *extents;
103
struct extent *cur_extent;
111
void *lzo_work_buffer;
112
char *decrypt_buffer;
116
* load_extents_page - load the array of extents
117
* handle: Structure holding the pointer to the array of extents etc.
119
* Read the table of extents from the swap location pointed to by
120
* @handle->next_extents and store it at the address in @handle->extents.
121
* Read the swap location of the next array of extents from the last
122
* element of the array and fill this element with zeros. Initialize
123
* @handle->cur_extent and @handle->cur_offset as appropriate.
125
static int load_extents_page(struct swap_reader *handle)
129
error = read_page(handle->fd, handle->extents, handle->next_extents);
132
n = page_size / sizeof(struct extent) - 1;
133
handle->next_extents = handle->extents[n].start;
134
memset(handle->extents + n, 0, sizeof(struct extent));
135
handle->cur_extent = handle->extents;
136
handle->cur_offset = handle->cur_extent->start;
137
if (posix_fadvise(handle->fd, handle->cur_offset,
138
handle->cur_extent->end - handle->cur_offset,
140
perror("posix_fadvise");
145
* free_swap_reader - free memory allocated for loading the image
146
* @handle: Structure containing pointers to memory buffers to free.
148
static void free_swap_reader(struct swap_reader *handle)
151
freemem(handle->lzo_work_buffer);
152
freemem(handle->read_buffer);
155
freemem(handle->decrypt_buffer);
156
freemem(handle->buffer);
157
freemem(handle->extents);
161
* init_swap_reader - initialize the structure used for loading the image
162
* @handle: Structure to initialize.
163
* @fd: File descriptor associated with the swap.
164
* @start: Swap location (offset) of the first image page.
165
* @image_size: Total size of the image data.
167
* Initialize buffers and related fields of @handle and load the first
170
static int init_swap_reader(struct swap_reader *handle, int fd, loff_t start,
179
handle->total_size = image_size;
181
handle->extents = getmem(page_size);
183
handle->buffer = getmem(buffer_size);
184
handle->read_buffer = handle->buffer;
187
handle->decrypt_buffer = getmem(page_size);
190
handle->read_buffer = getmem(compress_buf_size);
191
handle->lzo_work_buffer = getmem(LZO1X_1_MEM_COMPRESS);
194
/* Read the table of extents */
195
handle->next_extents = start;
196
error = load_extents_page(handle);
198
free_swap_reader(handle);
203
md5_init_ctx(&handle->ctx);
209
* find_next_image_page - find the next swap location holding image data
211
static void find_next_image_page(struct swap_reader *handle)
215
handle->cur_offset += page_size;
216
if (handle->cur_offset < handle->cur_extent->end)
218
/* We have exhausted the current extent. Forward to the next one */
219
handle->cur_extent++;
220
if (handle->cur_extent->start < handle->cur_extent->end) {
221
handle->cur_offset = handle->cur_extent->start;
222
if (posix_fadvise(handle->fd, handle->cur_offset,
223
handle->cur_extent->end - handle->cur_offset,
225
perror("posix_fadvise");
228
/* No more extents. Load the next extents page. */
229
error = load_extents_page(handle);
231
handle->cur_offset = 0;
235
* load_and_decrypt_page - load a page of data from swap and decrypt it,
238
static int load_and_decrypt_page(struct swap_reader *handle, void *dst)
243
if (!handle->cur_offset)
247
buf = handle->decrypt_buffer;
249
error = read_page(handle->fd, buf, handle->cur_offset);
251
#ifdef CONFIG_ENCRYPT
252
if (!error && do_decrypt)
253
error = gcry_cipher_decrypt(cipher_handle, dst, page_size,
258
handle->total_size -= page_size;
259
find_next_image_page(handle);
265
* load_buffer - load (and decrypt, if necessary) a block od data from the
266
* swap, decompress it if necessary and store it in the
269
static ssize_t load_buffer(struct swap_reader *handle)
275
#ifdef CONFIG_COMPRESS
277
struct buf_block *block = handle->read_buffer;
280
/* Read the block size from the first block page. */
281
error = load_and_decrypt_page(handle, block);
287
/* Load the rest of the block pages */
288
while (size < block->size + sizeof(size_t)) {
289
error = load_and_decrypt_page(handle, dst);
295
/* Decompress block */
296
error = lzo1x_decompress((lzo_bytep)block->data, block->size,
297
handle->buffer, &cnt,
298
handle->lzo_work_buffer);
305
dst = handle->buffer;
307
while (size < buffer_size && handle->total_size > 0) {
308
error = load_and_decrypt_page(handle, dst);
317
md5_process_block(handle->buffer, size, &handle->ctx);
323
* load_image - load a hibernation image
324
* @handle: Structure containing image information.
325
* @dev: Special device file to write image data pages to.
326
* @nr_pages: Number of image data pages.
328
static int load_image(struct swap_reader *handle, int dev,
329
unsigned int nr_pages, int verify_only)
336
char message[SPLASH_GENERIC_MESSAGE_SIZE];
338
sprintf(message, "Loading image data pages (%u pages)...", nr_pages);
339
splash.set_caption(message);
340
printf("%s ", message);
349
buf_size = load_buffer(handle);
354
buf = handle->buffer;
356
ret = verify_only ? page_size : write(dev, buf, page_size);
357
if (ret < page_size) {
359
perror("\nError while writing an image page");
365
buf_size -= page_size;
368
printf("\b\b\b\b%3d%%", n / m);
370
splash.progress(n / m);
373
} while (n < nr_pages);
379
static char *print_checksum(char * buf, unsigned char *checksum)
383
for (j = 0; j < 16; j++)
384
buf += sprintf(buf, "%02hhx ", checksum[j]);
389
#ifdef CONFIG_ENCRYPT
390
static int decrypt_key(struct image_header_info *header, unsigned char *key,
393
gcry_ac_handle_t rsa_hd;
394
gcry_ac_data_t rsa_data_set, key_set;
395
gcry_ac_key_t rsa_priv;
397
unsigned char *buf, *out, *key_buf, *ivec_buf;
399
struct RSA_data *rsa;
400
gcry_cipher_hd_t sym_hd;
405
ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
409
ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
414
key_buf = getmem(PK_KEY_SIZE);
415
ivec_buf = getmem(PK_CIPHER_BLOCK);
416
out = getmem(KEY_TEST_SIZE);
418
splash.read_password(password, 0);
419
memset(ivec_buf, 0, PK_CIPHER_BLOCK);
420
strncpy(ivec_buf, password, PK_CIPHER_BLOCK);
422
md5_process_bytes(password, strlen(password), &ctx);
423
md5_finish_ctx(&ctx, key_buf);
424
ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
426
ret = gcry_cipher_setiv(sym_hd, ivec_buf,
430
ret = gcry_cipher_encrypt(sym_hd,
432
KEY_TEST_DATA, KEY_TEST_SIZE);
435
fprintf(stderr, "%s: libgcrypt error: %s\n", my_name,
440
ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE);
443
printf("%s: Wrong passphrase, try again.\n", my_name);
446
gcry_cipher_close(sym_hd);
448
ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
449
GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
453
ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
455
ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK);
457
ret = gcry_ac_data_new(&rsa_data_set);
462
for (j = 0; j < RSA_FIELDS; j++) {
463
size_t s = rsa->size[j];
465
/* We need to decrypt some components */
466
if (j >= RSA_FIELDS_PUB) {
467
/* We use the in-place decryption */
468
ret = gcry_cipher_decrypt(sym_hd, buf, s, NULL, 0);
473
gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL);
474
ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
476
gcry_mpi_release(mpi);
483
ret = gcry_ac_key_init(&rsa_priv, rsa_hd,
484
GCRY_AC_KEY_SECRET, rsa_data_set);
486
goto Destroy_data_set;
488
ret = gcry_ac_data_new(&key_set);
492
gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, header->key.data,
493
header->key.size, NULL);
494
ret = gcry_ac_data_set(key_set, GCRY_AC_FLAG_COPY, "a", mpi);
496
goto Destroy_key_set;
498
gcry_mpi_release(mpi);
499
ret = gcry_ac_data_decrypt(rsa_hd, 0, rsa_priv, &mpi, key_set);
504
gcry_mpi_aprint(GCRYMPI_FMT_USG, &res, &s, mpi);
505
if (s == KEY_SIZE + CIPHER_BLOCK) {
506
memcpy(key, res, KEY_SIZE);
507
memcpy(ivec, res + KEY_SIZE, CIPHER_BLOCK);
515
gcry_mpi_release(mpi);
516
gcry_ac_data_destroy(key_set);
519
gcry_ac_key_destroy(rsa_priv);
522
gcry_ac_data_destroy(rsa_data_set);
525
gcry_cipher_close(sym_hd);
533
gcry_ac_close(rsa_hd);
538
static int restore_key(struct image_header_info *header)
540
static unsigned char key[KEY_SIZE], ivec[CIPHER_BLOCK];
543
if (header->flags & IMAGE_USE_RSA) {
544
error = decrypt_key(header, key, ivec);
548
splash.read_password(password, 0);
549
encrypt_init(key, ivec, password);
550
for (j = 0; j < CIPHER_BLOCK; j++)
551
ivec[j] ^= header->salt[j];
554
error = gcry_cipher_open(&cipher_handle,
555
IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB,
558
error = gcry_cipher_setkey(cipher_handle, key, KEY_SIZE);
560
error = gcry_cipher_setiv(cipher_handle, ivec,
563
gcry_cipher_close(cipher_handle);
569
int read_or_verify(int dev, int fd, struct image_header_info *header,
570
loff_t start, int verify, int test)
572
static struct swap_reader handle;
573
static unsigned char orig_checksum[16], checksum[16];
574
static char csum_buf[48];
575
int error = 0, test_mode = (verify || test);
577
error = read_page(fd, header, start);
581
if ((header->flags & IMAGE_CHECKSUM) || verify) {
582
memcpy(orig_checksum, header->checksum, 16);
583
print_checksum(csum_buf, orig_checksum);
584
printf("%s: MD5 checksum %s\n", my_name, csum_buf);
588
if (header->flags & IMAGE_COMPRESSED) {
589
printf("%s: Compressed image\n", my_name);
590
#ifdef CONFIG_COMPRESS
591
if (lzo_init() == LZO_E_OK) {
594
fprintf(stderr, "%s: Failed to initialize LZO\n",
599
fprintf(stderr, "%s: Compression not supported\n", my_name);
606
if (header->flags & IMAGE_ENCRYPTED) {
607
#ifdef CONFIG_ENCRYPT
608
printf("%s: Encrypted image\n", my_name);
610
gcry_cipher_setiv(cipher_handle, key_data.ivec,
614
fprintf(stderr, "%s: libgcrypt error: %s\n", my_name,
615
gcry_strerror(error));
621
fprintf(stderr, "%s: Encryption not supported\n", my_name);
628
error = init_swap_reader(&handle, fd, header->map_start,
629
header->image_data_size);
631
struct timeval begin, end;
634
gettimeofday(&begin, NULL);
635
error = load_image(&handle, dev, header->pages, test_mode);
636
if (!error && verify_checksum) {
637
md5_finish_ctx(&handle.ctx, checksum);
638
if (memcmp(orig_checksum, checksum, 16)) {
640
"%s: MD5 checksum does not match\n",
642
print_checksum(csum_buf, checksum);
644
"%s: Computed MD5 checksum %s\n",
649
free_swap_reader(&handle);
652
gettimeofday(&end, NULL);
654
timersub(&end, &begin, &end);
655
delta = end.tv_usec / 1000000.0 + end.tv_sec;
656
mb = (header->pages * (page_size / 1024.0)) / 1024.0;
658
printf("wrote %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
659
mb, header->writeout_time, mb / header->writeout_time);
661
printf("read %0.1lf MB in %0.1lf seconds (%0.1lf MB/s)\n",
662
mb, delta, mb / delta);
665
delta += header->writeout_time;
666
printf("total image i/o: %0.1lf MB in %0.1lf seconds "
667
"(%0.1lf MB/s)\n", mb, delta, mb / delta);
670
double real_size = header->image_data_size;
672
printf("%s: Compression ratio %4.2lf\n", my_name,
673
real_size / (header->pages * page_size));
674
real_size /= (1024.0 * 1024.0);
675
delta -= header->writeout_time;
677
printf("wrote %0.1lf MB of compressed data in %0.1lf "
678
"seconds (%0.1lf MB/s)\n", real_size,
679
header->writeout_time,
680
real_size / header->writeout_time);
682
printf("read %0.1lf MB of compressed data in %0.1lf "
683
"seconds (%0.1lf MB/s)\n", real_size,
684
delta, real_size / delta);
687
delta += header->writeout_time;
688
printf("total compressed data i/o: %0.1lf MB in %0.1lf "
689
"seconds (%0.1lf MB/s)\n", real_size, delta,
695
#ifdef CONFIG_ENCRYPT
696
if (do_decrypt && !test_mode)
697
gcry_cipher_close(cipher_handle);