Browse Source

Merge pull request #505 from libtom/rsa-improvements

Add rsa_init() and rsa_shrink_key()
Steffen Jaeckel 6 years ago
parent
commit
25410c7524

+ 1 - 1
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();

+ 4 - 4
libtomcrypt_VS2008.vcproj

@@ -2590,10 +2590,6 @@
 					RelativePath="src\pk\rsa\rsa_exptmod.c"
 					>
 				</File>
-				<File
-					RelativePath="src\pk\rsa\rsa_free.c"
-					>
-				</File>
 				<File
 					RelativePath="src\pk\rsa\rsa_get_size.c"
 					>
@@ -2610,6 +2606,10 @@
 					RelativePath="src\pk\rsa\rsa_import_x509.c"
 					>
 				</File>
+				<File
+					RelativePath="src\pk\rsa\rsa_key.c"
+					>
+				</File>
 				<File
 					RelativePath="src\pk\rsa\rsa_make_key.c"
 					>

+ 2 - 2
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 \

+ 2 - 2
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 \

+ 2 - 2
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 \

+ 2 - 2
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 \

+ 6 - 0
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[];

+ 0 - 32
src/pk/rsa/rsa_free.c

@@ -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$ */

+ 2 - 3
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) {

+ 6 - 5
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);

+ 1 - 2
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;
    }
 

+ 113 - 0
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 <stdarg.h>
+
+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$ */

+ 3 - 3
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 */

+ 1 - 2
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; }

+ 14 - 0
tests/rsa_test.c

@@ -9,6 +9,12 @@
 #include <tomcrypt_test.h>
 
 #if defined(LTC_MRSA)
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
+#include <malloc.h>
+#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 */