Hi,
This is the version of the libgcrypt patch that I'd like to apply, if there
are no objections.
Of course it makes s2disk/s2both and resume use libgcrypt instead
of openssl, and replaces Blowfish with 128-bit AES (AES appears to 10%
faster, although it is slower than the Blowfish out of openssl).
I've tested it on two x86_64 machines with 1024- and 2048-bit RSA keys
as well as on i386.
NOTE1: libgcrypt requires /dev/random to be present in the resume
initrd (I've added /dev/urandom too, for completness).
NOTE2: Of course the RSA keys have to be regenerated to work with
the patched utilities.
A documentation update will follow.
Greetings,
Rafael
--
Makefile | 9 +
encrypt.c | 17 +--
encrypt.h | 48 ++++++---
keygen.c | 177 +++++++++++++++++++++++++----------
resume.c | 198 ++++++++++++++++++++++++++++++----------
scripts/create-resume-initrd.sh | 2
suspend.c | 193 +++++++++++++++++++++++++++-----------
swsusp.h | 6 -
8 files changed, 463 insertions(+), 187 deletions(-)
Index: suspend/encrypt.h
===================================================================
--- suspend.orig/encrypt.h
+++ suspend/encrypt.h
@@ -11,40 +11,52 @@
*/
#ifdef CONFIG_ENCRYPT
-#include <openssl/blowfish.h>
-#include <openssl/rsa.h>
+#include <gcrypt.h>
+/* Maximum length of a passphrase, in characters */
#define PASS_SIZE 128
+/* Symmetric cipher used for image encryption, the size of its key and its
+ * block, in bytes
+ */
+#define IMAGE_CIPHER GCRY_CIPHER_BLOWFISH
#define KEY_SIZE 16
-#define IVEC_SIZE 8
-#define RSA_DATA_SIZE 1200
-#define KEY_DATA_SIZE 800
+#define CIPHER_BLOCK 8
+/* Symmetric cipher used for encrypting RSA private keys, the size of its key
+ * and its block, in bytes
+ */
+#define PK_CIPHER GCRY_CIPHER_AES
+#define PK_KEY_SIZE 16
+#define PK_CIPHER_BLOCK 16
+/* Auxiliary constants */
+#define RSA_DATA_SIZE 2000
+#define KEY_DATA_SIZE 1000
+#define RSA_FIELDS 6
+#define RSA_FIELDS_PUB 2
#define KEY_TEST_SIZE 8
#define KEY_TEST_DATA (unsigned char *)"12345678"
struct RSA_data {
- unsigned short n_size;
- unsigned short e_size;
- unsigned short d_size;
+ char field[RSA_FIELDS][2];
+ unsigned short size[RSA_FIELDS];
unsigned char key_test[KEY_TEST_SIZE];
unsigned char data[RSA_DATA_SIZE];
};
-struct key_data {
- unsigned char key[KEY_SIZE];
- unsigned char ivec[IVEC_SIZE];
- struct RSA_data rsa_data;
-};
-
struct encrypted_key {
unsigned short size;
unsigned char data[KEY_DATA_SIZE];
};
+struct key_data {
+ unsigned char key[KEY_SIZE];
+ unsigned char ivec[CIPHER_BLOCK];
+ struct RSA_data rsa;
+ struct encrypted_key encrypted_key;
+};
+
void read_password(char *pass_buf, int vrfy);
-void encrypt_init(BF_KEY *key, unsigned char *ivec, int *num,
- char *pass_buf, void *key_buf, int vrfy);
-void get_random_salt(char *salt, size_t size);
+void encrypt_init(unsigned char *, unsigned char *, char *, int);
+void get_random_salt(unsigned char *salt, size_t size);
-#define KEY_FILE "/etc/suspend.key"
+#define KEY_FILE ""
#endif
Index: suspend/keygen.c
===================================================================
--- suspend.orig/keygen.c
+++ suspend/keygen.c
@@ -14,8 +14,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
-#include <openssl/blowfish.h>
-#include <openssl/rsa.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -26,25 +24,38 @@
#define MIN_KEY_BITS 1024
#define MAX_KEY_BITS 4096
-#define MAX_OUT_SIZE 1200
+#define MAX_OUT_SIZE (sizeof(struct RSA_data))
#define MAX_STR_LEN 256
-#define IVEC_SIZE 8
#define DEFAULT_FILE "suspend.key"
static char in_buffer[MAX_STR_LEN];
static char pass_buf[MAX_STR_LEN];
-static struct RSA_data rsa_data;
+static struct RSA_data rsa;
static unsigned char encrypt_buffer[RSA_DATA_SIZE];
int main(int argc, char *argv[])
{
- RSA *rsa;
+ gcry_ac_data_t rsa_data_set;
+ gcry_ac_handle_t rsa_hd;
+ gcry_ac_key_t rsa_priv;
+ gcry_ac_key_pair_t rsa_key_pair;
+ gcry_mpi_t mpi;
+ size_t offset;
int len = MIN_KEY_BITS, ret = EXIT_SUCCESS;
- unsigned char *buf;
struct termios termios;
char *vrfy_buf;
+ struct md5_ctx ctx;
+ unsigned char key_buf[PK_KEY_SIZE];
+ gcry_cipher_hd_t sym_hd;
+ unsigned char ivec[PK_CIPHER_BLOCK];
unsigned short size;
- int fd;
+ int j, fd;
+
+ printf("libgcrypt version: %s\n", gcry_check_version(NULL));
+ gcry_control(GCRYCTL_INIT_SECMEM, 4096, 0);
+ ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
+ if (ret)
+ return ret;
do {
printf("Key bits (between %d and %d inclusive) [%d]: ",
@@ -55,18 +66,51 @@ int main(int argc, char *argv[])
} while (len < MIN_KEY_BITS || len > MAX_KEY_BITS);
Retry:
- printf("Generating %d-bit RSA keys.\n", len);
- rsa = RSA_generate_key(len, RSA_F4, NULL, NULL);
- if (!rsa) {
- fprintf(stderr, "Key generation failed.\n");
+ printf("Generating %d-bit RSA keys. Please wait.\n", len);
+ ret = gcry_ac_key_pair_generate(rsa_hd, len, NULL, &rsa_key_pair, NULL);
+ if (ret) {
+ fprintf(stderr, "Key generation failed: %s\n",
gcry_strerror(ret));
ret = EXIT_FAILURE;
- goto Free_RSA;
+ goto Close_RSA;
}
- if (RSA_check_key(rsa) <= 0) {
+ printf("Testing the private key. Please wait.\n");
+ rsa_priv = gcry_ac_key_pair_extract(rsa_key_pair, GCRY_AC_KEY_SECRET);
+ ret = gcry_ac_key_test(rsa_hd, rsa_priv);
+ if (ret) {
printf("RSA key test failed. Retrying.\n");
goto Retry;
}
+ rsa_data_set = gcry_ac_key_data_get(rsa_priv);
+ if (gcry_ac_data_length(rsa_data_set) != RSA_FIELDS) {
+ fprintf(stderr, "Wrong number of key fields\n");
+ ret = -EINVAL;
+ goto Free_RSA;
+ }
+
+ /* Convert the key length into bytes */
+ size = (len + 7) >> 3;
+ /* Copy the public key components to struct RSA_data */
+ offset = 0;
+ for (j = 0; j < RSA_FIELDS_PUB; j++) {
+ char *str;
+ size_t s;
+
+ if (offset + size >= RSA_DATA_SIZE)
+ goto Free_RSA;
+
+ gcry_ac_data_get_index(rsa_data_set, GCRY_AC_FLAG_COPY, j,
+ (const char **)&str, &mpi);
+ gcry_mpi_print(GCRYMPI_FMT_USG, rsa.data + offset,
+ size, &s, mpi);
+ rsa.field[j][0] = str[0];
+ rsa.field[j][1] = '\0';
+ rsa.size[j] = s;
+ offset += s;
+ gcry_mpi_release(mpi);
+ gcry_free(str);
+ }
+
tcgetattr(0, &termios);
termios.c_lflag &= ~ECHO;
termios.c_lflag |= ICANON | ECHONL;
@@ -88,42 +132,70 @@ Retry:
termios.c_lflag |= ECHO;
tcsetattr(0, TCSANOW, &termios);
- buf = rsa_data.data;
- size = BN_bn2mpi(rsa->n, NULL);
- if (size <= RSA_DATA_SIZE) {
- rsa_data.n_size = BN_bn2mpi(rsa->n, buf);
- buf += rsa_data.n_size;
- }
- size += BN_bn2mpi(rsa->e, NULL);
- if (size <= RSA_DATA_SIZE) {
- rsa_data.e_size = BN_bn2mpi(rsa->e, buf);
- buf += rsa_data.e_size;
- }
- size += BN_bn2mpi(rsa->d, NULL);
- if (size <= RSA_DATA_SIZE) {
- struct md5_ctx ctx;
- unsigned char key_buf[KEY_SIZE];
- BF_KEY key;
- unsigned char ivec[IVEC_SIZE];
- int n = 0;
-
- memset(ivec, 0, IVEC_SIZE);
- strncpy((char *)ivec, pass_buf, IVEC_SIZE);
- md5_init_ctx(&ctx);
- md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
- md5_finish_ctx(&ctx, key_buf);
- BF_set_key(&key, KEY_SIZE, key_buf);
- BF_ecb_encrypt(KEY_TEST_DATA, rsa_data.key_test, &key,
BF_ENCRYPT);
- rsa_data.d_size = BN_bn2mpi(rsa->d, encrypt_buffer);
- BF_cfb64_encrypt(encrypt_buffer, buf, rsa_data.d_size,
- &key, ivec, &n, BF_ENCRYPT);
- }
- if (size > RSA_DATA_SIZE) {
- fprintf(stderr, "Buffer is too small. Giving up.\n");
- ret = EXIT_FAILURE;
+ memset(ivec, 0, PK_CIPHER_BLOCK);
+ strncpy((char *)ivec, pass_buf, PK_CIPHER_BLOCK);
+ md5_init_ctx(&ctx);
+ md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
+ md5_finish_ctx(&ctx, key_buf);
+
+ /* First, we encrypt the key test */
+ ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
+ GCRY_CIPHER_SECURE);
+ if (ret)
goto Free_RSA;
+
+ ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
+ if (!ret)
+ ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK);
+
+ if (!ret)
+ ret = gcry_cipher_encrypt(sym_hd, rsa.key_test, KEY_TEST_SIZE,
+ KEY_TEST_DATA, KEY_TEST_SIZE);
+
+ gcry_cipher_close(sym_hd);
+ if (ret)
+ goto Free_RSA;
+
+ /* Now, we can encrypt the private RSA key */
+ ret = gcry_cipher_open(&sym_hd, PK_CIPHER, GCRY_CIPHER_MODE_CFB,
+ GCRY_CIPHER_SECURE);
+ if (ret)
+ goto Free_RSA;
+
+ ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
+ if (!ret)
+ ret = gcry_cipher_setiv(sym_hd, ivec, PK_CIPHER_BLOCK);
+
+ if (ret)
+ goto Free_sym;
+
+ /* Copy the private key components (encrypted) to struct RSA_data */
+ for (j = RSA_FIELDS_PUB; j < RSA_FIELDS; j++) {
+ char *str;
+ size_t s;
+
+ if (offset + size >= RSA_DATA_SIZE)
+ goto Free_sym;
+
+ gcry_ac_data_get_index(rsa_data_set, GCRY_AC_FLAG_COPY, j,
+ (const char **)&str, &mpi);
+ gcry_mpi_print(GCRYMPI_FMT_USG, rsa.data + offset,
+ size, &s, mpi);
+
+ /* We encrypt the data in place */
+ ret = gcry_cipher_encrypt(sym_hd, rsa.data + offset, s, NULL,
0);
+ if (ret)
+ goto Free_sym;
+
+ rsa.field[j][0] = str[0];
+ rsa.field[j][1] = '\0';
+ rsa.size[j] = s;
+ offset += s;
+ gcry_mpi_release(mpi);
+ gcry_free(str);
}
- size += 3 * sizeof(short) + KEY_TEST_SIZE;
+
+ size = offset + sizeof(struct RSA_data) - RSA_DATA_SIZE;
printf("File name [%s]: ", DEFAULT_FILE);
fgets(in_buffer, MAX_STR_LEN, stdin);
@@ -133,15 +205,18 @@ Retry:
in_buffer[strlen(in_buffer)-1] = '\0';
fd = open(in_buffer, O_RDWR | O_CREAT | O_TRUNC, 00600);
if (fd >= 0) {
- write(fd, &rsa_data, size);
+ write(fd, &rsa, size);
close(fd);
} else {
fprintf(stderr, "Could not open the file %s\n", in_buffer);
ret = EXIT_FAILURE;
}
-
+Free_sym:
+ gcry_cipher_close(sym_hd);
Free_RSA:
- RSA_free(rsa);
+ gcry_ac_data_destroy(rsa_data_set);
+Close_RSA:
+ gcry_ac_close(rsa_hd);
return ret;
}
Index: suspend/suspend.c
===================================================================
--- suspend.orig/suspend.c
+++ suspend/suspend.c
@@ -138,6 +138,7 @@ static unsigned int buffer_size;
static void *mem_pool;
#ifdef CONFIG_ENCRYPT
struct key_data *key_data;
+gcry_cipher_hd_t cipher_handle;
#endif
static inline loff_t check_free_swap(int dev)
@@ -217,9 +218,6 @@ struct swap_map_handle {
struct md5_ctx ctx;
#ifdef CONFIG_ENCRYPT
unsigned char *encrypt_buffer;
- BF_KEY key;
- unsigned char ivec[IVEC_SIZE];
- int num;
#endif
};
@@ -301,17 +299,19 @@ static int try_get_more_swap(struct swap
static int flush_buffer(struct swap_map_handle *handle)
{
void *src = handle->write_buffer;
- int error;
+ int error = 0;
#ifdef CONFIG_ENCRYPT
if (encrypt) {
- BF_cfb64_encrypt(src, handle->encrypt_buffer,
handle->cur_area.size,
- &handle->key, handle->ivec, &handle->num, BF_ENCRYPT);
+ error = gcry_cipher_encrypt(cipher_handle,
+ handle->encrypt_buffer, handle->cur_area.size,
+ src, handle->cur_area.size);
src = handle->encrypt_buffer;
}
#endif
- error = write_area(handle->fd, src, handle->cur_area.offset,
- handle->cur_area.size);
+ if (!error)
+ error = write_area(handle->fd, src, handle->cur_area.offset,
+ handle->cur_area.size);
if (error)
return error;
handle->areas[handle->k].offset = handle->cur_area.offset;
@@ -521,31 +521,52 @@ int write_image(int snapshot_fd, int res
#ifdef CONFIG_ENCRYPT
if (encrypt) {
if (use_RSA) {
- BF_set_key(&handle.key, KEY_SIZE,
key_data->key);
- memcpy(handle.ivec, key_data->ivec, IVEC_SIZE);
- handle.num = 0;
- header->image_flags |= IMAGE_ENCRYPTED |
IMAGE_USE_RSA;
- memcpy(&header->rsa_data, &key_data->rsa_data,
- sizeof(struct RSA_data));
- memcpy(&header->key_data, key_data + 1,
- sizeof(struct encrypted_key));
+ error = gcry_cipher_setkey(cipher_handle,
+ key_data->key, KEY_SIZE);
+ if (error)
+ goto No_RSA;
+
+ error = gcry_cipher_setiv(cipher_handle,
+ key_data->ivec, CIPHER_BLOCK);
+
+ if (error)
+ goto No_RSA;
+
+ header->image_flags |= IMAGE_ENCRYPTED |
+ IMAGE_USE_RSA;
+ memcpy(&header->rsa, &key_data->rsa,
+ sizeof(struct RSA_data));
+ memcpy(&header->key, &key_data->encrypted_key,
+ sizeof(struct encrypted_key));
} else {
int j;
+No_RSA:
chvt(vt_no);
- encrypt_init(&handle.key, handle.ivec,
&handle.num,
- handle.write_buffer,
- handle.encrypt_buffer, 1);
+ encrypt_init(key_data->key, key_data->ivec,
+ handle.write_buffer, 1);
splash.switch_to();
splash.progress(20);
- get_random_salt(header->salt, IVEC_SIZE);
- for (j = 0; j < IVEC_SIZE; j++)
- handle.ivec[j] ^= header->salt[j];
- header->image_flags |= IMAGE_ENCRYPTED;
+ get_random_salt(header->salt, CIPHER_BLOCK);
+ for (j = 0; j < CIPHER_BLOCK; j++)
+ key_data->ivec[j] ^= header->salt[j];
+
+ error = gcry_cipher_setkey(cipher_handle,
+ key_data->key, KEY_SIZE);
+ if (!error)
+ error = gcry_cipher_setiv(cipher_handle,
+ key_data->ivec, CIPHER_BLOCK);
+
+ if (!error)
+ header->image_flags |= IMAGE_ENCRYPTED;
}
+ if (error)
+ printf("suspend: libgcrypt error: %s\n",
+ gcry_strerror(error));
}
#endif
- error = save_image(&handle, header->pages - 1);
+ if (!error)
+ error = save_image(&handle, header->pages - 1);
}
if (!error) {
error = flush_swap_writer(&handle);
@@ -615,7 +636,7 @@ static int reset_signature(int fd)
}
#endif
-static void shutdown(void)
+static void suspend_shutdown(void)
{
power_off();
/* Signature is on disk, it is very dangerous to continue now.
@@ -673,14 +694,14 @@ int suspend_system(int snapshot_fd, int
splash.progress(100);
#ifdef CONFIG_BOTH
if (!s2ram) {
- shutdown();
+ suspend_shutdown();
} else {
/* If we die (and allow system to
continue) between
* now and reset_signature(), very bad
things will
* happen. */
error = suspend_to_ram(snapshot_fd);
if (error)
- shutdown();
+ suspend_shutdown();
reset_signature(resume_fd);
free_swap_pages(snapshot_fd);
free_snapshot(snapshot_fd);
@@ -688,7 +709,7 @@ int suspend_system(int snapshot_fd, int
goto Unfreeze;
}
#else
- shutdown();
+ suspend_shutdown();
#endif
} else {
free_swap_pages(snapshot_fd);
@@ -918,10 +939,14 @@ static inline void close_swappiness(void
#ifdef CONFIG_ENCRYPT
static void generate_key(void)
{
- RSA *rsa;
- int fd, rnd_fd;
- struct RSA_data *rsa_data;
+ gcry_ac_handle_t rsa_hd;
+ gcry_ac_data_t rsa_data_set, key_set;
+ gcry_ac_key_t rsa_pub;
+ gcry_mpi_t mpi;
+ int ret, fd, rnd_fd;
+ struct RSA_data *rsa;
unsigned char *buf;
+ int j;
if (!key_data)
return;
@@ -930,41 +955,79 @@ static void generate_key(void)
if (fd < 0)
return;
- rsa = RSA_new();
- if (!rsa)
+ rsa = &key_data->rsa;
+ if (read(fd, rsa, sizeof(struct RSA_data)) <= 0)
goto Close;
- rsa_data = &key_data->rsa_data;
- if (read(fd, rsa_data, sizeof(struct RSA_data)) <= 0)
- goto Free_rsa;
+ ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
+ if (ret)
+ goto Close;
- buf = rsa_data->data;
- rsa->n = BN_mpi2bn(buf, rsa_data->n_size, NULL);
- buf += rsa_data->n_size;
- rsa->e = BN_mpi2bn(buf, rsa_data->e_size, NULL);
- if (!rsa->n || !rsa->e)
+ buf = rsa->data;
+ ret = gcry_ac_data_new(&rsa_data_set);
+ if (ret)
goto Free_rsa;
- rnd_fd = open("/dev/urandom", O_RDONLY);
- if (rnd_fd > 0) {
- unsigned short size = KEY_SIZE + IVEC_SIZE;
-
- if (read(rnd_fd, key_data->key, size) == size) {
- struct encrypted_key *enc_key;
- int ret;
-
- enc_key = (struct encrypted_key *)(key_data + 1);
- ret = RSA_public_encrypt(size, key_data->key,
- enc_key->data, rsa, RSA_PKCS1_PADDING);
- if (ret > 0) {
- enc_key->size = ret;
- use_RSA = 'y';
- }
+ for (j = 0; j < RSA_FIELDS_PUB; j++) {
+ size_t s = rsa->size[j];
+
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL);
+ ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
+ rsa->field[j], mpi);
+ gcry_mpi_release(mpi);
+ if (ret)
+ break;
+
+ buf += s;
+ }
+ if (!ret)
+ ret = gcry_ac_key_init(&rsa_pub, rsa_hd, GCRY_AC_KEY_PUBLIC,
+ rsa_data_set);
+
+ if (!ret) {
+ unsigned short size;
+
+ ret = gcry_ac_data_new(&key_set);
+ if (ret)
+ goto Destroy_key;
+
+ rnd_fd = open("/dev/urandom", O_RDONLY);
+ if (rnd_fd <= 0)
+ goto Destroy_set;
+
+ size = KEY_SIZE + CIPHER_BLOCK;
+ if (read(rnd_fd, key_data->key, size) != size)
+ goto Close_urandom;
+
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, key_data->key, size, NULL);
+ ret = gcry_ac_data_encrypt(rsa_hd, 0, rsa_pub, mpi, &key_set);
+ gcry_mpi_release(mpi);
+ if (!ret) {
+ struct encrypted_key *key = &key_data->encrypted_key;
+ char *str;
+ size_t s;
+
+ gcry_ac_data_get_index(key_set, GCRY_AC_FLAG_COPY, 0,
+ (const char **)&str, &mpi);
+ gcry_free(str);
+ gcry_mpi_print(GCRYMPI_FMT_USG, key->data,
+ KEY_DATA_SIZE, &s, mpi);
+ gcry_mpi_release(mpi);
+ key->size = s;
+ use_RSA = 'y';
}
+Close_urandom:
close(rnd_fd);
+Destroy_set:
+ gcry_ac_data_destroy(key_set);
+Destroy_key:
+ gcry_ac_key_destroy(rsa_pub);
+ } else {
+ gcry_ac_data_destroy(rsa_data_set);
}
+
Free_rsa:
- RSA_free(rsa);
+ gcry_ac_close(rsa_hd);
Close:
close(fd);
}
@@ -1026,6 +1089,18 @@ int main(int argc, char *argv[])
}
#ifdef CONFIG_ENCRYPT
if (encrypt) {
+ printf("suspend: libgcrypt version: %s\n",
+ gcry_check_version(NULL));
+ gcry_control(GCRYCTL_INIT_SECMEM, page_size, 0);
+ ret = gcry_cipher_open(&cipher_handle, IMAGE_CIPHER,
+ GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
+ if (ret) {
+ fprintf(stderr, "suspend: libgcrypt error %s\n",
+ gcry_strerror(ret));
+ encrypt = 0;
+ }
+ }
+ if (encrypt) {
mem_size -= buffer_size;
key_data = (struct key_data *)((char *)mem_pool + mem_size);
generate_key();
@@ -1138,6 +1213,10 @@ Close_snapshot_fd:
Close_resume_fd:
close(resume_fd);
+#ifdef CONFIG_ENCRYPT
+ if (encrypt)
+ gcry_cipher_close(cipher_handle);
+#endif
free(mem_pool);
return ret;
Index: suspend/swsusp.h
===================================================================
--- suspend.orig/swsusp.h
+++ suspend/swsusp.h
@@ -58,9 +58,9 @@ struct swsusp_info {
uint32_t image_flags;
unsigned char checksum[16];
#ifdef CONFIG_ENCRYPT
- char salt[IVEC_SIZE];
- struct RSA_data rsa_data;
- struct encrypted_key key_data;
+ unsigned char salt[CIPHER_BLOCK];
+ struct RSA_data rsa;
+ struct encrypted_key key;
#endif
};
Index: suspend/encrypt.c
===================================================================
--- suspend.orig/encrypt.c
+++ suspend/encrypt.c
@@ -59,32 +59,31 @@ void read_password(char *pass_buf, int v
* long
*/
-void encrypt_init(BF_KEY *key, unsigned char *ivec, int *num,
- char *pass_buf, void *key_buf, int vrfy)
+void
+encrypt_init(unsigned char *key, unsigned char *ivec, char *pass_buf, int vrfy)
{
struct md5_ctx ctx;
read_password(pass_buf, vrfy);
- memset(ivec, 0, IVEC_SIZE);
- strncpy((char *)ivec, pass_buf, IVEC_SIZE);
+ memset(ivec, 0, CIPHER_BLOCK);
+ strncpy((char *)ivec, pass_buf, CIPHER_BLOCK);
md5_init_ctx(&ctx);
md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
- md5_finish_ctx(&ctx, key_buf);
- BF_set_key(key, KEY_SIZE, key_buf);
- *num = 0;
+ md5_finish_ctx(&ctx, key);
}
-void get_random_salt(char *salt, size_t size)
+void get_random_salt(unsigned char *salt, size_t size)
{
int fd;
memset(salt, 0, size);
- fd = open("/dev/random", O_RDONLY);
+ fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
read(fd, salt, size);
close(fd);
}
}
#endif
+
Index: suspend/resume.c
===================================================================
--- suspend.orig/resume.c
+++ suspend/resume.c
@@ -164,9 +164,7 @@ struct swap_map_handle {
struct md5_ctx ctx;
#ifdef CONFIG_ENCRYPT
char *decrypt_buffer;
- BF_KEY key;
- unsigned char ivec[IVEC_SIZE];
- int num;
+ gcry_cipher_hd_t cipher_handle;
#endif
};
@@ -220,9 +218,9 @@ static int fill_buffer(struct swap_map_h
handle->area_size);
#ifdef CONFIG_ENCRYPT
if (!error && decrypt)
- BF_cfb64_encrypt(dst, (unsigned char *)handle->read_buffer,
- handle->area_size, &handle->key, handle->ivec,
- &handle->num, BF_DECRYPT);
+ error = gcry_cipher_decrypt(handle->cipher_handle,
+ (void *)handle->read_buffer, handle->area_size,
+ dst, handle->area_size);
#endif
return error;
}
@@ -370,63 +368,147 @@ static inline void print_checksum(unsign
}
#ifdef CONFIG_ENCRYPT
-static int decrypt_key(struct swsusp_info *header, BF_KEY *key, unsigned char
*ivec,
- void *buffer)
+static int decrypt_key(struct swsusp_info *header, unsigned char *key,
+ unsigned char *ivec, void *buffer)
{
- RSA *rsa;
- unsigned char *buf, *out, *key_buf;
+ gcry_ac_handle_t rsa_hd;
+ gcry_ac_data_t rsa_data_set, key_set;
+ gcry_ac_key_t rsa_priv;
+ gcry_mpi_t mpi;
+ unsigned char *buf, *out, *key_buf, *ivec_buf;
char *pass_buf;
struct md5_ctx ctx;
- struct RSA_data *rsa_data;
- int n = 0, ret = 0;
+ struct RSA_data *rsa;
+ gcry_cipher_hd_t sym_hd;
+ int j, ret = 0;
- rsa = RSA_new();
- if (!rsa)
- return -ENOMEM;
+ rsa = &header->rsa;
+
+ ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
+ if (ret)
+ return ret;
- rsa_data = &header->rsa_data;
- buf = rsa_data->data;
- rsa->n = BN_mpi2bn(buf, rsa_data->n_size, NULL);
- buf += rsa_data->n_size;
- rsa->e = BN_mpi2bn(buf, rsa_data->e_size, NULL);
- buf += rsa_data->e_size;
+ if (!ret)
+ ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
+ GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
+
+ if (ret)
+ goto Free_rsa;
pass_buf = buffer;
key_buf = (unsigned char *)pass_buf + PASS_SIZE;
+ ivec_buf = key_buf + PK_KEY_SIZE;
+ out = ivec_buf + PK_CIPHER_BLOCK;
do {
read_password(pass_buf, 0);
- memset(ivec, 0, IVEC_SIZE);
- strncpy((char *)ivec, pass_buf, IVEC_SIZE);
+ memset(ivec_buf, 0, PK_CIPHER_BLOCK);
+ strncpy((char *)ivec_buf, pass_buf, PK_CIPHER_BLOCK);
md5_init_ctx(&ctx);
md5_process_bytes(pass_buf, strlen(pass_buf), &ctx);
md5_finish_ctx(&ctx, key_buf);
- BF_set_key(key, KEY_SIZE, key_buf);
- BF_ecb_encrypt(KEY_TEST_DATA, key_buf, key, BF_ENCRYPT);
- ret = memcmp(key_buf, rsa_data->key_test, KEY_TEST_SIZE);
+ ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
+ if (!ret)
+ ret = gcry_cipher_setiv(sym_hd, ivec_buf,
+ PK_CIPHER_BLOCK);
+
+ if (!ret)
+ ret = gcry_cipher_encrypt(sym_hd,
+ out, KEY_TEST_SIZE,
+ KEY_TEST_DATA, KEY_TEST_SIZE);
+
+ if (ret)
+ break;
+
+ ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE);
+
if (ret)
printf("resume: Wrong passphrase, try again.\n");
} while (ret);
- out = key_buf + KEY_SIZE;
- BF_cfb64_encrypt(buf, out, rsa_data->d_size, key, ivec, &n, BF_DECRYPT);
- rsa->d = BN_mpi2bn(out, rsa_data->d_size, NULL);
- if (!rsa->n || !rsa->e || !rsa->d) {
- ret = -EFAULT;
+ gcry_cipher_close(sym_hd);
+ if (!ret)
+ ret = gcry_cipher_open(&sym_hd, PK_CIPHER,
+ GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
+
+ if (ret)
+ goto Free_rsa;
+
+ ret = gcry_cipher_setkey(sym_hd, key_buf, PK_KEY_SIZE);
+ if (!ret)
+ ret = gcry_cipher_setiv(sym_hd, ivec_buf, PK_CIPHER_BLOCK);
+
+ if (!ret)
+ ret = gcry_ac_data_new(&rsa_data_set);
+
+ if (ret) {
+ gcry_cipher_close(sym_hd);
goto Free_rsa;
}
- ret = RSA_private_decrypt(header->key_data.size, header->key_data.data,
- out, rsa, RSA_PKCS1_PADDING);
- if (ret != (int)(KEY_SIZE + IVEC_SIZE)) {
- ret = -ENODATA;
+ buf = rsa->data;
+ for (j = 0; j < RSA_FIELDS; j++) {
+ size_t s = rsa->size[j];
+
+ /* We need to decrypt some components */
+ if (j >= RSA_FIELDS_PUB) {
+ /* We use the in-place decryption */
+ ret = gcry_cipher_decrypt(sym_hd, buf, s, NULL, 0);
+ if (ret)
+ break;
+ }
+
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, buf, s, NULL);
+ ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
+ rsa->field[j], mpi);
+ gcry_mpi_release(mpi);
+ if (ret)
+ break;
+
+ buf += s;
+ }
+ if (!ret)
+ ret = gcry_ac_key_init(&rsa_priv, rsa_hd,
+ GCRY_AC_KEY_SECRET, rsa_data_set);
+
+ if (!ret) {
+ ret = gcry_ac_data_new(&key_set);
+ if (!ret) {
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, header->key.data,
+ header->key.size, NULL);
+ ret = gcry_ac_data_set(key_set, GCRY_AC_FLAG_COPY,
+ "a", mpi);
+ if (!ret) {
+ gcry_mpi_release(mpi);
+ ret = gcry_ac_data_decrypt(rsa_hd, 0, rsa_priv,
+ &mpi, key_set);
+ }
+ if (!ret) {
+ unsigned char *res;
+ size_t s;
+
+ gcry_mpi_aprint(GCRYMPI_FMT_USG, &res, &s, mpi);
+ if (s == KEY_SIZE + CIPHER_BLOCK) {
+ memcpy(key, res, KEY_SIZE);
+ memcpy(ivec, res + KEY_SIZE,
+ CIPHER_BLOCK);
+ } else {
+ ret = -ENODATA;
+ }
+ gcry_free(res);
+ }
+ gcry_mpi_release(mpi);
+ gcry_ac_data_destroy(key_set);
+ }
+ gcry_ac_key_destroy(rsa_priv);
} else {
- BF_set_key(key, KEY_SIZE, out);
- memcpy(ivec, out + KEY_SIZE, IVEC_SIZE);
- ret = 0;
+ gcry_ac_data_destroy(rsa_data_set);
}
+ gcry_cipher_close(sym_hd);
+
Free_rsa:
- RSA_free(rsa);
+ gcry_ac_close(rsa_hd);
+
return ret;
}
#endif
@@ -481,24 +563,41 @@ static int read_image(int dev, char *res
}
if (!error && (header->image_flags & IMAGE_ENCRYPTED)) {
#ifdef CONFIG_ENCRYPT
+ static unsigned char key[KEY_SIZE], ivec[CIPHER_BLOCK];
+
printf("resume: Encrypted image\n");
splash.to_verbose();
if (header->image_flags & IMAGE_USE_RSA) {
- handle.num = 0;
- error = decrypt_key(header, &handle.key,
- handle.ivec, buffer);
+ error = decrypt_key(header, key, ivec, buffer);
} else {
int j;
- encrypt_init(&handle.key, handle.ivec,
&handle.num,
- buffer, buffer + page_size, 0);
- for (j = 0; j < IVEC_SIZE; j++)
- handle.ivec[j] ^= header->salt[j];
+ encrypt_init(key, ivec, buffer, 0);
+ for (j = 0; j < CIPHER_BLOCK; j++)
+ ivec[j] ^= header->salt[j];
}
splash.to_silent();
splash.progress(15);
if (!error)
+ error = gcry_cipher_open(&handle.cipher_handle,
+ IMAGE_CIPHER, GCRY_CIPHER_MODE_CFB,
+ GCRY_CIPHER_SECURE);
+ if (!error) {
decrypt = 1;
+ error = gcry_cipher_setkey(handle.cipher_handle,
+ key, KEY_SIZE);
+ }
+ if (!error)
+ error = gcry_cipher_setiv(handle.cipher_handle,
+ ivec, CIPHER_BLOCK);
+
+ if (error) {
+ if (decrypt)
+ gcry_cipher_close(handle.cipher_handle);
+ decrypt = 0;
+ printf("resume: libgcrypt error: %s\n",
+ gcry_strerror(error));
+ }
#else
printf("resume: Encryption not supported\n");
error = -EINVAL;
@@ -563,6 +662,11 @@ static int read_image(int dev, char *res
}
fsync(fd);
close(fd);
+#ifdef CONFIG_ENCRYPT
+ if (decrypt)
+ gcry_cipher_close(handle.cipher_handle);
+#endif
+
if (!error) {
printf("resume: Image successfully loaded\n");
} else {
@@ -607,6 +711,8 @@ int main(int argc, char *argv[])
buffer_size = BUFFER_PAGES * page_size;
#ifdef CONFIG_ENCRYPT
+ printf("resume: libgcrypt version: %s\n", gcry_check_version(NULL));
+ gcry_control(GCRYCTL_INIT_SECMEM, page_size, 0);
mem_size = 3 * page_size + 2 * buffer_size;
#else
mem_size = 3 * page_size + buffer_size;
Index: suspend/Makefile
===================================================================
--- suspend.orig/Makefile
+++ suspend/Makefile
@@ -11,8 +11,11 @@ CC_FLAGS += -DCONFIG_COMPRESS
LD_FLAGS += -llzf
endif
ifdef CONFIG_ENCRYPT
+GCRYPT_CC_FLAGS := $(shell libgcrypt-config --cflags)
+GCRYPT_LD_FLAGS := $(shell libgcrypt-config --libs)
CC_FLAGS += -DCONFIG_ENCRYPT
-LD_FLAGS += -lcrypto
+CC_FLAGS += $(GCRYPT_CC_FLAGS)
+LD_FLAGS += $(GCRYPT_LD_FLAGS)
endif
SUSPEND_DIR=/usr/local/sbin
@@ -93,8 +96,8 @@ resume: md5.o encrypt.o config.o resume.
$(CC) -Wall $(CC_FLAGS) md5.o encrypt.o config.o vt.o resume.c
$(SPLASHOBJ) -static -o resume $(LD_FLAGS)
ifdef CONFIG_ENCRYPT
-suspend-keygen: md5.o encrypt.o keygen.c encrypt.h md5.h
- $(CC) -Wall -DHAVE_INTTYPES_H -DHAVE_STDINT_H -DCONFIG_ENCRYPT md5.o
keygen.c -o suspend-keygen -lcrypto
+suspend-keygen: md5.o keygen.c encrypt.h md5.h
+ $(CC) -Wall -DHAVE_INTTYPES_H -DHAVE_STDINT_H $(CC_FLAGS) md5.o
keygen.c -o suspend-keygen $(LD_FLAGS)
install-suspend: $(S2DISK) $(S2BOTH) suspend-keygen conf/$(CONFIGFILE)
if [ ! -c /dev/snapshot ]; then mknod /dev/snapshot c 10 231; fi
Index: suspend/scripts/create-resume-initrd.sh
===================================================================
--- suspend.orig/scripts/create-resume-initrd.sh
+++ suspend/scripts/create-resume-initrd.sh
@@ -43,6 +43,8 @@ if [ -f $RESUME -a -d $MOUNT_POINT -a -b
mkdir $MOUNT_POINT/dev
cp -r /dev/console $MOUNT_POINT/dev/
cp -r /dev/snapshot $MOUNT_POINT/dev/
+ cp -r /dev/random $MOUNT_POINT/dev/
+ cp -r /dev/urandom $MOUNT_POINT/dev/
cp -r $RESUME_DEVICE $MOUNT_POINT/dev/
mkdir $MOUNT_POINT/proc
mkdir $MOUNT_POINT/etc
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Suspend-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/suspend-devel