Hi,

On Wednesday 19 July 2006 21:09, Fabio Comolli wrote:
> On 7/19/06, Rafael J. Wysocki <[EMAIL PROTECTED]> wrote:
> > The appended patch makes s2disk/s2both and resume use libgcrypt instead
> > of openssl.  It also replaces Blowfish with AES (128bit).
> >
> 
> It works perfectly (only tested suspend-to-disk). Great work, as usual.

Thanks! :-)

> > The libgcrypt's AES seems to be significantly slower than the openssl's
> > Blowfish, but well.  Also IMHO libgcrypt is less convenient than openssl
> > and the documentation sucks.  Still it's GPLed and works on SUSE 10.1
> > (for me).
> >
> 
> Well, it seems slower even with 2.6.18-rc1-mm1 (that is normally
> sensibly faster compared with 2.6.17) but, well, it's just your first
> revision ;-).

Appended is another one.  It uses Blowfish for encrypting the image and
AES for encrypting the RSA private key and contains some random
cleanups.

It doesn't seem to be faster than the previous one, so apparently libgcrypt is
just slower than openssl.  However now I can use just about any 128-bit cipher
for image encryption, although I'd like it to be hardcoded, at least for now.

Greetings,
Rafael


-- 
 Makefile                        |    9 +
 encrypt.c                       |   17 +--
 encrypt.h                       |   29 +++--
 keygen.c                        |  177 +++++++++++++++++++++++++----------
 resume.c                        |  198 ++++++++++++++++++++++++++++++----------
 scripts/create-resume-initrd.sh |    2 
 suspend.c                       |  194 +++++++++++++++++++++++++++------------
 swsusp.h                        |    6 -
 8 files changed, 449 insertions(+), 183 deletions(-)

Index: suspend/encrypt.h
===================================================================
--- suspend.orig/encrypt.h
+++ suspend/encrypt.h
@@ -11,29 +11,31 @@
  */
 
 #ifdef CONFIG_ENCRYPT
-#include <openssl/blowfish.h>
-#include <openssl/rsa.h>
+#include <gcrypt.h>
 
 #define PASS_SIZE      128
 #define KEY_SIZE       16
-#define IVEC_SIZE      8
-#define RSA_DATA_SIZE  1200
-#define KEY_DATA_SIZE  800
+#define CIPHER_BLOCK   8
+#define PK_KEY_SIZE    16
+#define PK_CIPHER_BLOCK        16
+#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;
+       unsigned char   ivec[CIPHER_BLOCK];
+       struct RSA_data rsa;
 };
 
 struct encrypted_key {
@@ -42,9 +44,8 @@ struct 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 aes_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(&aes_hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB,
+                               GCRY_CIPHER_SECURE);
+       if (ret)
                goto Free_RSA;
+
+       ret = gcry_cipher_setkey(aes_hd, key_buf, PK_KEY_SIZE);
+       if (!ret)
+               ret = gcry_cipher_setiv(aes_hd, ivec, PK_CIPHER_BLOCK);
+
+       if (!ret)
+               ret = gcry_cipher_encrypt(aes_hd, rsa.key_test, KEY_TEST_SIZE,
+                                       KEY_TEST_DATA, KEY_TEST_SIZE);
+
+       gcry_cipher_close(aes_hd);
+       if (ret)
+               goto Free_RSA;
+
+       /* Now, we can encrypt the private RSA key */
+       ret = gcry_cipher_open(&aes_hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB,
+                               GCRY_CIPHER_SECURE);
+       if (ret)
+               goto Free_RSA;
+
+       ret = gcry_cipher_setkey(aes_hd, key_buf, PK_KEY_SIZE);
+       if (!ret)
+               ret = gcry_cipher_setiv(aes_hd, ivec, PK_CIPHER_BLOCK);
+
+       if (ret)
+               goto Free_AES;
+
+       /* 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_AES;
+
+               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(aes_hd, rsa.data + offset, s, NULL, 
0);
+               if (ret)
+                       goto Free_AES;
+
+               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_AES:
+       gcry_cipher_close(aes_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,51 @@ 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)
+                                       error = gcry_cipher_setiv(cipher_handle,
+                                               key_data->ivec, CIPHER_BLOCK);
+
+                               if (!error) {
+                                       struct encrypted_key *key;
+
+                                       header->image_flags |= IMAGE_ENCRYPTED |
+                                                               IMAGE_USE_RSA;
+                                       memcpy(&header->rsa, &key_data->rsa,
+                                               sizeof(struct RSA_data));
+                                       key = (struct encrypted_key *)(key_data 
+ 1);
+                                       memcpy(&header->key, key,
+                                               sizeof(struct encrypted_key));
+                               }
                        } else {
                                int j;
 
                                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 +635,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 +693,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 +708,7 @@ int suspend_system(int snapshot_fd, int 
                                        goto Unfreeze;
                                }
 #else
-                               shutdown();
+                               suspend_shutdown();
 #endif
                        } else {
                                free_swap_pages(snapshot_fd);
@@ -918,10 +938,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 +954,80 @@ 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;
+                       char *str;
+                       size_t s;
+
+                       key = (struct encrypted_key *)(key_data + 1);
+                       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,19 @@ 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,
+                               GCRY_CIPHER_BLOWFISH, 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 +1214,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 aes_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(&aes_hd, GCRY_CIPHER_AES,
+                               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(aes_hd, key_buf, PK_KEY_SIZE);
+               if (!ret)
+                       ret = gcry_cipher_setiv(aes_hd, ivec_buf,
+                                               PK_CIPHER_BLOCK);
+
+               if (!ret)
+                       ret = gcry_cipher_encrypt(aes_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(aes_hd);
+       if (!ret)
+               ret = gcry_cipher_open(&aes_hd, GCRY_CIPHER_AES,
+                               GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
+
+       if (ret)
+               goto Free_rsa;
+
+       ret = gcry_cipher_setkey(aes_hd, key_buf, PK_KEY_SIZE);
+       if (!ret)
+               ret = gcry_cipher_setiv(aes_hd, ivec_buf, PK_CIPHER_BLOCK);
+
+       if (!ret)
+               ret = gcry_ac_data_new(&rsa_data_set);
+
+       if (ret) {
+               gcry_cipher_close(aes_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(aes_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(aes_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,
+                                       GCRY_CIPHER_BLOWFISH, 
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