Rafael J. Wysocki wrote:
Hm, as far as I remember, key_data is not just plain key and it can be
greater than 512 bytes. And that would explain one bug report related to
the encryption with RSA.
(struct encrypted_key).data contains the encrypted pair (k, i). The
session key (k) is 16 bytes and the initialization vector (i) is 8
bytes. The result can't be greater than the 512 bytes long RSA modulus.
Frankly, I have to check the code, but that will need to wait for a couple of
days.
Now, I think we can fix all that by using two pages for the header, but it
would complicate things a bit (not too much, but still).
BTW, I played with shrinking the header even more. I realized that we
don't really need all the RSA components (n, e, d, p, q, u) for
decryption. Only the modulus (n) and the private exponent (d) are
absolutely necessary. It is nice to have the public exponent (e) too,
for RSA blinding (anyway, libgcrypt always generates 65537 for (e),
unless told otherwise).
You can take a look at the attached patch, which shrinks struct
swsusp_info to 2028 bytes on i386. This is achieved by only saving the
components (n, e, d).
I am _not_ proposing to merge this one, because it requires a slightly
modified libgcrypt to work. Original libgcrypt insists on knowing all
the six components, even though it doesn't really need them. I consider
that a bug in libgcrypt.
Michal
Index: encrypt.c
===================================================================
RCS file: /cvsroot/suspend/suspend/encrypt.c,v
retrieving revision 1.8
diff -u -p -r1.8 encrypt.c
--- encrypt.c 14 Sep 2006 14:18:58 -0000 1.8
+++ encrypt.c 20 Jan 2007 01:29:04 -0000
@@ -88,5 +88,20 @@ void get_random_salt(unsigned char *salt
close(fd);
}
}
+
+int find_RSA_field(struct RSA_data *rsa, char field, unsigned char **pdata)
+{
+ int i;
+ unsigned char *data;
+ data = rsa->data;
+ for (i=0; i<RSA_FIELDS; i++) {
+ if (field == rsa->field[i][0]) {
+ *pdata = data;
+ return i;
+ }
+ data += rsa->size[i];
+ }
+ return -1;
+}
#endif
Index: encrypt.h
===================================================================
RCS file: /cvsroot/suspend/suspend/encrypt.h,v
retrieving revision 1.6
diff -u -p -r1.6 encrypt.h
--- encrypt.h 11 Dec 2006 20:42:46 -0000 1.6
+++ encrypt.h 20 Jan 2007 01:29:04 -0000
@@ -28,10 +28,12 @@
#define PK_KEY_SIZE 16
#define PK_CIPHER_BLOCK 16
/* Auxiliary constants */
-#define RSA_DATA_SIZE 3072
-#define KEY_DATA_SIZE 1000
+#define RSA_MAX_KEY_LEN 512
+#define RSA_PUB_EXP_LEN 16
+#define KEY_DATA_SIZE 512
#define RSA_FIELDS 6
#define RSA_FIELDS_PUB 2
+#define RSA_DATA_SIZE (RSA_FIELDS*RSA_MAX_KEY_LEN)
#define KEY_TEST_SIZE 8
#define KEY_TEST_DATA (unsigned char *)"12345678"
@@ -42,6 +44,19 @@ struct RSA_data {
unsigned char data[RSA_DATA_SIZE];
};
+struct RSA_decrypt_key {
+ /* public part */
+ unsigned short key_len;
+ unsigned char modulus[RSA_MAX_KEY_LEN];
+ /* public exponent is not strictly necessary for decryption,
+ * but it's useful for blinding */
+ unsigned short pub_exp_len;
+ unsigned char pub_exponent[RSA_PUB_EXP_LEN];
+ /* secret part */
+ unsigned short exp_len;
+ unsigned char exponent[RSA_MAX_KEY_LEN];
+};
+
struct encrypted_key {
unsigned short size;
unsigned char data[KEY_DATA_SIZE];
@@ -57,6 +72,7 @@ struct key_data {
void read_password(char *pass_buf, int vrfy);
void encrypt_init(unsigned char *, unsigned char *, char *);
void get_random_salt(unsigned char *salt, size_t size);
+int find_RSA_field(struct RSA_data *, char field, unsigned char **);
#define KEY_FILE ""
#endif
Index: resume.c
===================================================================
RCS file: /cvsroot/suspend/suspend/resume.c,v
retrieving revision 1.37
diff -u -p -r1.37 resume.c
--- resume.c 3 Dec 2006 11:29:59 -0000 1.37
+++ resume.c 20 Jan 2007 01:29:05 -0000
@@ -393,14 +393,14 @@ static int decrypt_key(struct swsusp_inf
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;
+ unsigned char *out, *key_buf, *ivec_buf;
char *pass_buf;
struct md5_ctx ctx;
- struct RSA_data *rsa;
+ struct RSA_decrypt_key *rsa_key;
gcry_cipher_hd_t sym_hd;
- int j, ret = 0;
+ int ret = 0;
- rsa = &header->rsa;
+ rsa_key = &header->secret_key;
ret = gcry_ac_open(&rsa_hd, GCRY_AC_RSA, 0);
if (ret)
@@ -437,7 +437,7 @@ static int decrypt_key(struct swsusp_inf
if (ret)
break;
- ret = memcmp(out, rsa->key_test, KEY_TEST_SIZE);
+ ret = memcmp(out, header->key_test, KEY_TEST_SIZE);
if (ret)
printf("resume: Wrong passphrase, try again.\n");
@@ -463,27 +463,31 @@ static int decrypt_key(struct swsusp_inf
goto Free_rsa;
}
- 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);
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, &rsa_key->modulus,
+ rsa_key->key_len, NULL);
+ ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
+ "n", mpi);
+ gcry_mpi_release(mpi);
+
+ if (!ret) {
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, &rsa_key->pub_exponent,
+ rsa_key->pub_exp_len, NULL);
ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
- rsa->field[j], mpi);
+ "e", mpi);
gcry_mpi_release(mpi);
- if (ret)
- break;
+ }
- buf += s;
+ if (!ret)
+ ret = gcry_cipher_decrypt(sym_hd, &rsa_key->exponent,
+ rsa_key->exp_len, NULL, 0);
+ if (!ret) {
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG, &rsa_key->exponent,
+ rsa_key->exp_len, NULL);
+ ret = gcry_ac_data_set(rsa_data_set, GCRY_AC_FLAG_COPY,
+ "d", mpi);
+ gcry_mpi_release(mpi);
}
+
if (!ret)
ret = gcry_ac_key_init(&rsa_priv, rsa_hd,
GCRY_AC_KEY_SECRET, rsa_data_set);
@@ -491,8 +495,8 @@ static int decrypt_key(struct swsusp_inf
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);
+ gcry_mpi_scan(&mpi, GCRYMPI_FMT_USG,
header->session_key.data,
+ header->session_key.size, NULL);
ret = gcry_ac_data_set(key_set, GCRY_AC_FLAG_COPY,
"a", mpi);
if (!ret) {
@@ -513,8 +517,8 @@ static int decrypt_key(struct swsusp_inf
ret = -ENODATA;
}
gcry_free(res);
+ gcry_mpi_release(mpi);
}
- gcry_mpi_release(mpi);
gcry_ac_data_destroy(key_set);
}
gcry_ac_key_destroy(rsa_priv);
Index: suspend.c
===================================================================
RCS file: /cvsroot/suspend/suspend/suspend.c,v
retrieving revision 1.66
diff -u -p -r1.66 suspend.c
--- suspend.c 10 Jan 2007 14:16:45 -0000 1.66
+++ suspend.c 20 Jan 2007 01:29:06 -0000
@@ -593,6 +593,8 @@ int write_image(int snapshot_fd, int res
#ifdef CONFIG_ENCRYPT
if (encrypt) {
if (use_RSA) {
+ unsigned char *data;
+ int index;
error = gcry_cipher_setkey(cipher_handle,
key_data->key, KEY_SIZE);
if (error)
@@ -606,10 +608,29 @@ int write_image(int snapshot_fd, int res
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));
+ index = find_RSA_field(&key_data->rsa, 'n',
&data);
+ if (index<0)
+ goto No_RSA;
+ header->secret_key.key_len =
key_data->rsa.size[index];
+ memcpy(&header->secret_key.modulus, data,
+ header->secret_key.key_len);
+
+ index = find_RSA_field(&key_data->rsa, 'e',
&data);
+ if (index<0)
+ goto No_RSA;
+ header->secret_key.pub_exp_len =
key_data->rsa.size[index];
+ memcpy(&header->secret_key.pub_exponent, data,
+ header->secret_key.pub_exp_len);
+
+ index = find_RSA_field(&key_data->rsa, 'd',
&data);
+ if (index<0)
+ goto No_RSA;
+ header->secret_key.exp_len =
key_data->rsa.size[index];
+ memcpy(&header->secret_key.exponent, data,
+ header->secret_key.exp_len);
+
+ memcpy(&header->key_test,
&key_data->rsa.key_test, sizeof(header->key_test));
+ header->session_key = key_data->encrypted_key;
} else {
int j;
@@ -1107,11 +1128,13 @@ static void generate_key(void)
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,
+ ret = gcry_mpi_print(GCRYMPI_FMT_USG, key->data,
KEY_DATA_SIZE, &s, mpi);
gcry_mpi_release(mpi);
- key->size = s;
- use_RSA = 'y';
+ if (!ret) {
+ key->size = s;
+ use_RSA = 'y';
+ }
}
Close_urandom:
close(rnd_fd);
Index: swsusp.h
===================================================================
RCS file: /cvsroot/suspend/suspend/swsusp.h,v
retrieving revision 1.33
diff -u -p -r1.33 swsusp.h
--- swsusp.h 7 Nov 2006 10:42:49 -0000 1.33
+++ swsusp.h 20 Jan 2007 01:29:06 -0000
@@ -72,8 +72,9 @@ struct swsusp_info {
unsigned char checksum[16];
#ifdef CONFIG_ENCRYPT
unsigned char salt[CIPHER_BLOCK];
- struct RSA_data rsa;
- struct encrypted_key key;
+ struct RSA_decrypt_key secret_key;
+ unsigned char key_test[KEY_TEST_SIZE];
+ struct encrypted_key session_key;
#endif
double writeout_time;
};
-------------------------------------------------------------------------
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