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
Suspend-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/suspend-devel

Reply via email to