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