diff --git a/demos/timing.c b/demos/timing.c
index acabf0a69..967ae9f92 100644
--- a/demos/timing.c
+++ b/demos/timing.c
@@ -707,7 +707,7 @@ static void time_rsa(void)
if (ltc_mp.name == NULL) return;
- for (x = 1024; x <= 2048; x += 256) {
+ for (x = 2048; x <= 8192; x <<= 1) {
t2 = 0;
for (y = 0; y < 4; y++) {
t_start();
diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj
index 92a3abc62..7e1cf5327 100644
--- a/libtomcrypt_VS2008.vcproj
+++ b/libtomcrypt_VS2008.vcproj
@@ -2590,10 +2590,6 @@
RelativePath="src\pk\rsa\rsa_exptmod.c"
>
-
-
@@ -2610,6 +2606,10 @@
RelativePath="src\pk\rsa\rsa_import_x509.c"
>
+
+
diff --git a/makefile.mingw b/makefile.mingw
index a9a6ff21f..e67c0cff8 100644
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -200,8 +200,8 @@ src/pk/ed25519/ed25519_verify.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_
src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \
src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
-src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_get_size.o \
-src/pk/rsa/rsa_import.o src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o \
+src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_get_size.o src/pk/rsa/rsa_import.o \
+src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o src/pk/rsa/rsa_key.o \
src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \
src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \
src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_x509.o \
diff --git a/makefile.msvc b/makefile.msvc
index 7bd9d9d6d..5b56c25ad 100644
--- a/makefile.msvc
+++ b/makefile.msvc
@@ -193,8 +193,8 @@ src/pk/ed25519/ed25519_verify.obj src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkc
src/pk/pkcs1/pkcs_1_oaep_decode.obj src/pk/pkcs1/pkcs_1_oaep_encode.obj src/pk/pkcs1/pkcs_1_os2ip.obj \
src/pk/pkcs1/pkcs_1_pss_decode.obj src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/pkcs1/pkcs_1_v1_5_decode.obj \
src/pk/pkcs1/pkcs_1_v1_5_encode.obj src/pk/rsa/rsa_decrypt_key.obj src/pk/rsa/rsa_encrypt_key.obj \
-src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_free.obj src/pk/rsa/rsa_get_size.obj \
-src/pk/rsa/rsa_import.obj src/pk/rsa/rsa_import_pkcs8.obj src/pk/rsa/rsa_import_x509.obj \
+src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_get_size.obj src/pk/rsa/rsa_import.obj \
+src/pk/rsa/rsa_import_pkcs8.obj src/pk/rsa/rsa_import_x509.obj src/pk/rsa/rsa_key.obj \
src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_set.obj src/pk/rsa/rsa_sign_hash.obj \
src/pk/rsa/rsa_sign_saltlen_get.obj src/pk/rsa/rsa_verify_hash.obj src/pk/x25519/x25519_export.obj \
src/pk/x25519/x25519_import.obj src/pk/x25519/x25519_import_pkcs8.obj src/pk/x25519/x25519_import_x509.obj \
diff --git a/makefile.unix b/makefile.unix
index 9ea44360a..39a7a7a49 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -210,8 +210,8 @@ src/pk/ed25519/ed25519_verify.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_
src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \
src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
-src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_get_size.o \
-src/pk/rsa/rsa_import.o src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o \
+src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_get_size.o src/pk/rsa/rsa_import.o \
+src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o src/pk/rsa/rsa_key.o \
src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \
src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \
src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_x509.o \
diff --git a/makefile_include.mk b/makefile_include.mk
index c7d663218..43e9af151 100644
--- a/makefile_include.mk
+++ b/makefile_include.mk
@@ -371,8 +371,8 @@ src/pk/ed25519/ed25519_verify.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_
src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \
src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \
src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \
-src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_free.o src/pk/rsa/rsa_get_size.o \
-src/pk/rsa/rsa_import.o src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o \
+src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_get_size.o src/pk/rsa/rsa_import.o \
+src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o src/pk/rsa/rsa_key.o \
src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \
src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \
src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_x509.o \
diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h
index d080d6c2f..257ae1976 100644
--- a/src/headers/tomcrypt_private.h
+++ b/src/headers/tomcrypt_private.h
@@ -225,6 +225,12 @@ int pk_get_oid(enum ltc_oid_id id, const char **st);
int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen);
int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen);
+/* ---- DH Routines ---- */
+#ifdef LTC_MRSA
+int rsa_init(rsa_key *key);
+void rsa_shrink_key(rsa_key *key);
+#endif /* LTC_MRSA */
+
/* ---- DH Routines ---- */
#ifdef LTC_MDH
extern const ltc_dh_set_type ltc_dh_sets[];
diff --git a/src/pk/rsa/rsa_free.c b/src/pk/rsa/rsa_free.c
deleted file mode 100644
index f2251dd62..000000000
--- a/src/pk/rsa/rsa_free.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- */
-#include "tomcrypt_private.h"
-
-/**
- @file rsa_free.c
- Free an RSA key, Tom St Denis
-*/
-
-#ifdef LTC_MRSA
-
-/**
- Free an RSA key from memory
- @param key The RSA key to free
-*/
-void rsa_free(rsa_key *key)
-{
- LTC_ARGCHKVD(key != NULL);
- mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, NULL);
-}
-
-#endif
-
-/* ref: $Format:%D$ */
-/* git commit: $Format:%H$ */
-/* commit time: $Format:%ai$ */
diff --git a/src/pk/rsa/rsa_import.c b/src/pk/rsa/rsa_import.c
index 69f5b23ce..a98fc275e 100644
--- a/src/pk/rsa/rsa_import.c
+++ b/src/pk/rsa/rsa_import.c
@@ -34,8 +34,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
- if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
- &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ if ((err = rsa_init(key)) != CRYPT_OK) {
return err;
}
@@ -113,7 +112,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
goto LBL_FREE;
LBL_ERR:
- mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+ rsa_free(key);
LBL_FREE:
if (tmpbuf != NULL) {
diff --git a/src/pk/rsa/rsa_import_pkcs8.c b/src/pk/rsa/rsa_import_pkcs8.c
index d4c40a452..37a740f13 100644
--- a/src/pk/rsa/rsa_import_pkcs8.c
+++ b/src/pk/rsa/rsa_import_pkcs8.c
@@ -78,9 +78,9 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
buf2 = XMALLOC(buf2len);
if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
+ if ((err = mp_init_multi(&zero, &iter, NULL)) != CRYPT_OK) { goto LBL_FREE2; }
/* init key */
- err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, &zero, &iter, NULL);
- if (err != CRYPT_OK) { goto LBL_FREE2; }
+ if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE3; }
/* try to decode encrypted priv key */
if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) {
@@ -117,13 +117,14 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
if (err != CRYPT_OK) { goto LBL_ERR; }
key->type = PK_PRIVATE;
err = CRYPT_OK;
- goto LBL_FREE2;
+ goto LBL_FREE3;
LBL_ERR:
rsa_free(key);
-LBL_FREE2:
- if (l) der_free_sequence_flexi(l);
+LBL_FREE3:
mp_clear_multi(iter, zero, NULL);
+ if (l) der_free_sequence_flexi(l);
+LBL_FREE2:
XFREE(buf2);
LBL_FREE1:
XFREE(buf1);
diff --git a/src/pk/rsa/rsa_import_x509.c b/src/pk/rsa/rsa_import_x509.c
index 5220ae389..651badaca 100644
--- a/src/pk/rsa/rsa_import_x509.c
+++ b/src/pk/rsa/rsa_import_x509.c
@@ -40,8 +40,7 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
- if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
- &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ if ((err = rsa_init(key)) != CRYPT_OK) {
return err;
}
diff --git a/src/pk/rsa/rsa_key.c b/src/pk/rsa/rsa_key.c
new file mode 100644
index 000000000..4f92288db
--- /dev/null
+++ b/src/pk/rsa/rsa_key.c
@@ -0,0 +1,113 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt_private.h"
+
+/**
+ @file rsa_key.c
+ Free an RSA key, Tom St Denis
+ Basic operations on an RSA key, Steffen Jaeckel
+*/
+
+#ifdef LTC_MRSA
+#include
+
+static void _mpi_shrink_multi(void **a, ...)
+{
+ void **cur;
+ unsigned n;
+ int err;
+ va_list args;
+ void *tmp[10] = { 0 };
+ void **arg[10] = { 0 };
+
+ /* We re-allocate in the order that we received the varargs */
+ n = 0;
+ err = CRYPT_ERROR;
+ cur = a;
+ va_start(args, a);
+ while (cur != NULL) {
+ if (n >= sizeof(tmp)/sizeof(tmp[0])) {
+ goto out;
+ }
+ if (*cur != NULL) {
+ arg[n] = cur;
+ if ((err = mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) {
+ goto out;
+ }
+ n++;
+ }
+ cur = va_arg(args, void**);
+ }
+ va_end(args);
+
+ /* but we clear the old values in the reverse order */
+ while (n != 0 && arg[--n] != NULL) {
+ mp_clear(*arg[n]);
+ *arg[n] = tmp[n];
+ }
+out:
+ va_end(args);
+ /* clean-up after an error
+ * or after this was called with too many args
+ */
+ if ((err != CRYPT_OK) ||
+ (n >= sizeof(tmp)/sizeof(tmp[0]))) {
+ for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) {
+ if (tmp[n] != NULL) {
+ mp_clear(tmp[n]);
+ }
+ }
+ }
+}
+
+/**
+ This shrinks the allocated memory of a RSA key
+
+ It will use up some more memory temporarily,
+ but then it will free-up the entire sequence that
+ was once allocated when the key was created/populated.
+
+ This only works with libtommath >= 1.2.0 in earlier versions
+ it has the inverse effect due to the way it worked internally.
+ Also works for GNU MP, tomsfastmath naturally shows no effect.
+
+ @param key The RSA key to shrink
+*/
+void rsa_shrink_key(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ _mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+}
+
+/**
+ Init an RSA key
+ @param key The RSA key to free
+ @return CRYPT_OK if successful
+*/
+int rsa_init(rsa_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+}
+
+/**
+ Free an RSA key from memory
+ @param key The RSA key to free
+*/
+void rsa_free(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, NULL);
+}
+
+#endif
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/pk/rsa/rsa_make_key.c b/src/pk/rsa/rsa_make_key.c
index 9226b234f..8146138c7 100644
--- a/src/pk/rsa/rsa_make_key.c
+++ b/src/pk/rsa/rsa_make_key.c
@@ -68,7 +68,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */
/* make key */
- if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ if ((err = rsa_init(key)) != CRYPT_OK) {
goto errkey;
}
@@ -78,8 +78,8 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
/* optimize for CRT now */
/* find d mod q-1 and d mod p-1 */
- if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */
- if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */
+ if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = q-1 */
if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */
if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */
if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */
diff --git a/src/pk/rsa/rsa_set.c b/src/pk/rsa/rsa_set.c
index c89ab2198..93a9e06f2 100644
--- a/src/pk/rsa/rsa_set.c
+++ b/src/pk/rsa/rsa_set.c
@@ -35,8 +35,7 @@ int rsa_set_key(const unsigned char *N, unsigned long Nlen,
LTC_ARGCHK(e != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
- err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
- if (err != CRYPT_OK) return err;
+ if ((err = rsa_init(key)) != CRYPT_OK) return err;
if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; }
if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; }
diff --git a/tests/rsa_test.c b/tests/rsa_test.c
index 5fcac829d..2db1c863b 100644
--- a/tests/rsa_test.c
+++ b/tests/rsa_test.c
@@ -9,6 +9,12 @@
#include
#if defined(LTC_MRSA)
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
+#include
+#define dbg_malloc_stats() do{ malloc_stats(); }while(0)
+#else
+#define dbg_malloc_stats() do{ }while(0)
+#endif
/* These are test keys [see file test.key] that I use to test my import/export against */
static const unsigned char openssl_private_rsa[] = {
@@ -512,6 +518,14 @@ print_hex("q", tmp, len);
DO(rsa_export(tmp, &len2, PK_PUBLIC, &key));
DO(rsa_import(tmp, len2, &pubKey));
+ dbg_malloc_stats();
+ rsa_shrink_key(&key);
+ dbg_malloc_stats();
+ rsa_shrink_key(&pubKey);
+ dbg_malloc_stats();
+ rsa_shrink_key(&privKey);
+ dbg_malloc_stats();
+
/* verify with original */
DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &key));
/* change a byte */