Skip to content

Commit 4e28b92

Browse files
committed
add rsa_shrink_key()
1 parent 6fa98be commit 4e28b92

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

doc/crypt.tex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,6 +4362,15 @@ \subsection{RSA Key Size}
43624362
\end{verbatim}
43634363
This can be used to determine the modulus size of an RSA key.
43644364

4365+
\subsection{RSA Key Shrinking}
4366+
To shrink an RSA key, use the following function:
4367+
\index{rsa\_shrink\_key()}
4368+
\begin{verbatim}
4369+
void rsa_shrink_key(rsa_key *key);
4370+
\end{verbatim}
4371+
This can be used to shrink a key to its minimal memory requirements
4372+
e.g. in cases where you have a long-lived RSA key in a memory-constrained system.
4373+
43654374
\mysection{RSA Key Encryption}
43664375
Normally RSA is used to encrypt short symmetric keys which are then used in block ciphers to encrypt a message.
43674376
To facilitate encrypting short keys the following functions have been provided.

src/headers/tomcrypt_pk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen,
6060

6161
void rsa_free(rsa_key *key);
6262

63+
void rsa_shrink_key(rsa_key *key);
64+
6365
/* These use PKCS #1 v2.0 padding */
6466
#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, _key) \
6567
rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _prng, _prng_idx, _hash_idx, LTC_PKCS_1_OAEP, _key)

src/pk/rsa/rsa_key.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,75 @@
1515
*/
1616

1717
#ifdef LTC_MRSA
18+
#include <stdarg.h>
19+
20+
static void _mpi_shrink_multi(void **a, ...)
21+
{
22+
void **cur;
23+
unsigned n;
24+
int err;
25+
va_list args;
26+
void *tmp[10] = { 0 };
27+
void **arg[10] = { 0 };
28+
29+
/* We re-allocate in the order that we received the varargs */
30+
n = 0;
31+
err = CRYPT_ERROR;
32+
cur = a;
33+
va_start(args, a);
34+
while (cur != NULL) {
35+
if (n >= sizeof(tmp)/sizeof(tmp[0])) {
36+
goto out;
37+
}
38+
if (*cur != NULL) {
39+
arg[n] = cur;
40+
if ((err = mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) {
41+
goto out;
42+
}
43+
n++;
44+
}
45+
cur = va_arg(args, void**);
46+
}
47+
va_end(args);
48+
49+
/* but we clear the old values in the reverse order */
50+
while (n != 0 && arg[--n] != NULL) {
51+
mp_clear(*arg[n]);
52+
*arg[n] = tmp[n];
53+
}
54+
out:
55+
va_end(args);
56+
/* clean-up after an error
57+
* or after this was called with too many args
58+
*/
59+
if ((err != CRYPT_OK) ||
60+
(n >= sizeof(tmp)/sizeof(tmp[0]))) {
61+
for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) {
62+
if (tmp[n] != NULL) {
63+
mp_clear(tmp[n]);
64+
}
65+
}
66+
}
67+
}
68+
69+
/**
70+
This shrinks the allocated memory of a RSA key
71+
72+
It will use up some more memory temporarily,
73+
but then it will free-up the entire sequence that
74+
was once allocated when the key was created/populated.
75+
76+
This only works with libtommath >= 1.2.0 in earlier versions
77+
it has the inverse effect due to the way it worked internally.
78+
Also works for GNU MP, tomsfastmath naturally shows no effect.
79+
80+
@param key The RSA key to shrink
81+
*/
82+
void rsa_shrink_key(rsa_key *key)
83+
{
84+
LTC_ARGCHKVD(key != NULL);
85+
_mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
86+
}
1887

1988
/**
2089
Init an RSA key

tests/rsa_test.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
#include <tomcrypt_test.h>
1010

1111
#if defined(LTC_MRSA)
12+
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
13+
#include <malloc.h>
14+
#define dbg_malloc_stats() do{ malloc_stats(); }while(0)
15+
#else
16+
#define dbg_malloc_stats() do{ }while(0)
17+
#endif
1218

1319
/* These are test keys [see file test.key] that I use to test my import/export against */
1420
static const unsigned char openssl_private_rsa[] = {
@@ -512,6 +518,14 @@ print_hex("q", tmp, len);
512518
DO(rsa_export(tmp, &len2, PK_PUBLIC, &key));
513519
DO(rsa_import(tmp, len2, &pubKey));
514520

521+
dbg_malloc_stats();
522+
rsa_shrink_key(&key);
523+
dbg_malloc_stats();
524+
rsa_shrink_key(&pubKey);
525+
dbg_malloc_stats();
526+
rsa_shrink_key(&privKey);
527+
dbg_malloc_stats();
528+
515529
/* verify with original */
516530
DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &key));
517531
/* change a byte */

0 commit comments

Comments
 (0)