From 674a60748884dc55ee7091b7c23a41240e75f73c Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 1 Jun 2004 02:46:09 +0000 Subject: Makefile.in contains updated files required --HG-- extra : convert_revision : cc8a8c49dc70e632c352853a39801089b08149be --- genrsa.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 genrsa.c (limited to 'genrsa.c') diff --git a/genrsa.c b/genrsa.c new file mode 100644 index 0000000..330ebf2 --- /dev/null +++ b/genrsa.c @@ -0,0 +1,138 @@ +/* + * Dropbear - a SSH2 server + * + * Copyright (c) 2002,2003 Matt Johnston + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ + +#include "includes.h" +#include "dbutil.h" +#include "bignum.h" +#include "random.h" +#include "rsa.h" +#include "genrsa.h" + +#define RSA_E 65537 + +#ifdef DROPBEAR_RSA + +static void getrsaprime(mp_int* prime, mp_int *primeminus, + mp_int* rsa_e, unsigned int size); + +/* mostly taken from libtomcrypt's rsa key generation routine */ +rsa_key * gen_rsa_priv_key(unsigned int size) { + + rsa_key * key; + mp_int pminus, qminus, lcm; + + key = (rsa_key*)m_malloc(sizeof(rsa_key)); + + key->e = (mp_int*)m_malloc(sizeof(mp_int)); + key->n = (mp_int*)m_malloc(sizeof(mp_int)); + key->d = (mp_int*)m_malloc(sizeof(mp_int)); + key->p = (mp_int*)m_malloc(sizeof(mp_int)); + key->q = (mp_int*)m_malloc(sizeof(mp_int)); + + m_mp_init_multi(key->e, key->n, key->d, key->p, key->q, + &pminus, &lcm, &qminus, NULL); + + seedrandom(); + + if (mp_set_int(key->e, RSA_E) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + + /* PuTTY doesn't like it if the modulus isn't a multiple of 8 bits, + * so we just generate them until we get one which is OK */ + getrsaprime(key->p, &pminus, key->e, size/2); + do { + getrsaprime(key->q, &qminus, key->e, size/2); + + if (mp_mul(key->p, key->q, key->n) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + } while (mp_count_bits(key->n) % 8 != 0); + + /* lcm(p-1, q-1) */ + if (mp_lcm(&pminus, &qminus, &lcm) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + + /* de = 1 mod lcm(p-1,q-1) */ + /* therefore d = (e^-1) mod lcm(p-1,q-1) */ + if (mp_invmod(key->e, &lcm, key->d) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + + mp_clear_multi(&pminus, &qminus, &lcm, NULL); + + return key; +} + +/* return a prime suitable for p or q */ +static void getrsaprime(mp_int* prime, mp_int *primeminus, + mp_int* rsa_e, unsigned int size) { + + unsigned char *buf; + mp_int temp_gcd; + + buf = (unsigned char*)m_malloc(size+1); + + m_mp_init(&temp_gcd); + do { + /* generate a random odd number with MSB set, then find the + the next prime above it */ + genrandom(buf, size+1); + buf[0] |= 0x80; /* MSB set */ + + if (mp_read_unsigned_bin(prime, buf, size+1) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + + /* find the next integer which is prime, 8 round of miller-rabin */ + if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + + /* subtract one to get p-1 */ + if (mp_sub_d(prime, 1, primeminus) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + /* check relative primality to e */ + if (mp_gcd(primeminus, rsa_e, &temp_gcd) != MP_OKAY) { + fprintf(stderr, "rsa generation failed\n"); + exit(1); + } + } while (mp_cmp_d(&temp_gcd, 1) != MP_EQ); /* while gcd(p-1, e) != 1 */ + + /* now we have a good value for result */ + mp_clear(&temp_gcd); + m_burn(buf, size+1); + m_free(buf); +} + +#endif /* DROPBEAR_RSA */ -- cgit v1.2.3 From 4a52217ed410dfbfdceee4688688d756fa0d097e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 17 Aug 2004 10:20:20 +0000 Subject: default initialisers for mp_ints --HG-- extra : convert_revision : af69bacb50a31523e383e8f73844d04681f9e394 --- cli-kex.c | 13 ++++++++++--- common-kex.c | 9 +++++---- dss.c | 16 +++++++++++----- gendss.c | 11 ++++++++--- genrsa.c | 6 ++++-- options.h | 2 +- rsa.c | 5 +++-- svr-kex.c | 6 ++++-- 8 files changed, 46 insertions(+), 22 deletions(-) (limited to 'genrsa.c') diff --git a/cli-kex.c b/cli-kex.c index ca29e7d..90c8d29 100644 --- a/cli-kex.c +++ b/cli-kex.c @@ -45,8 +45,8 @@ void send_msg_kexdh_init() { cli_ses.dh_e = (mp_int*)m_malloc(sizeof(mp_int)); cli_ses.dh_x = (mp_int*)m_malloc(sizeof(mp_int)); - m_mp_init_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); + gen_kexdh_vals(cli_ses.dh_e, cli_ses.dh_x); CHECKCLEARTOWRITE(); @@ -59,13 +59,18 @@ void send_msg_kexdh_init() { /* Handle a diffie-hellman key exchange reply. */ void recv_msg_kexdh_reply() { - mp_int dh_f; + DEF_MP_INT(dh_f); sign_key *hostkey = NULL; unsigned int type, keybloblen; unsigned char* keyblob = NULL; TRACE(("enter recv_msg_kexdh_reply")); + + if (cli_ses.kex_state != KEXDH_INIT_SENT) { + dropbear_exit("Received out-of-order kexdhreply"); + } + m_mp_init(&dh_f); type = ses.newkeys->algo_hostkey; TRACE(("type is %d", type)); @@ -83,7 +88,6 @@ void recv_msg_kexdh_reply() { dropbear_exit("Bad KEX packet"); } - m_mp_init(&dh_f); if (buf_getmpint(ses.payload, &dh_f) != DROPBEAR_SUCCESS) { TRACE(("failed getting mpint")); dropbear_exit("Bad KEX packet"); @@ -91,6 +95,9 @@ void recv_msg_kexdh_reply() { kexdh_comb_key(cli_ses.dh_e, cli_ses.dh_x, &dh_f, hostkey); mp_clear(&dh_f); + mp_clear_multi(cli_ses.dh_e, cli_ses.dh_x, NULL); + m_free(cli_ses.dh_e); + m_free(cli_ses.dh_x); if (buf_verify(ses.payload, hostkey, ses.hash, SHA1_HASH_SIZE) != DROPBEAR_SUCCESS) { diff --git a/common-kex.c b/common-kex.c index f8bfe97..7bb0c82 100644 --- a/common-kex.c +++ b/common-kex.c @@ -464,17 +464,18 @@ void recv_msg_kexinit() { /* Initialises and generate one side of the diffie-hellman key exchange values. * See the ietf-secsh-transport draft, section 6, for details */ -/* dh_pub and dh_priv will be initialised by this function, and should be - * mp_clear()ed after finished */ +/* dh_pub and dh_priv MUST be already initialised */ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { - mp_int dh_p, dh_q, dh_g; + DEF_MP_INT(dh_p); + DEF_MP_INT(dh_q); + DEF_MP_INT(dh_g); unsigned char randbuf[DH_P_LEN]; int dh_q_len; TRACE(("enter send_msg_kexdh_reply")); - m_mp_init_multi(&dh_g, &dh_p, &dh_q, dh_priv, dh_pub, NULL); + m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); /* read the prime and generator*/ if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN) diff --git a/dss.c b/dss.c index 9b56f10..5bd358a 100644 --- a/dss.c +++ b/dss.c @@ -164,7 +164,10 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, unsigned char msghash[SHA1_HASH_SIZE]; hash_state hs; int ret = DROPBEAR_FAILURE; - mp_int val1, val2, val3, val4; + DEF_MP_INT(val1); + DEF_MP_INT(val2); + DEF_MP_INT(val3); + DEF_MP_INT(val4); char * string = NULL; int stringlen; @@ -281,13 +284,16 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data, unsigned char privkeyhash[SHA512_HASH_SIZE]; unsigned char *privkeytmp; unsigned char proto_k[SHA512_HASH_SIZE]; - mp_int dss_protok; + DEF_MP_INT(dss_protok); #else unsigned char kbuf[SHA1_HASH_SIZE]; #endif - mp_int dss_k, dss_m; - mp_int dss_temp1, dss_temp2; - mp_int dss_r, dss_s; + DEF_MP_INT(dss_k); + DEF_MP_INT(dss_m); + DEF_MP_INT(dss_temp1); + DEF_MP_INT(dss_temp2); + DEF_MP_INT(dss_r); + DEF_MP_INT(dss_s); hash_state hs; TRACE(("enter buf_put_dss_sign")); diff --git a/gendss.c b/gendss.c index 5a440a1..e1b502d 100644 --- a/gendss.c +++ b/gendss.c @@ -89,7 +89,10 @@ static void getq(dss_key *key) { static void getp(dss_key *key, unsigned int size) { - mp_int tempX, tempC, tempP, temp2q; + DEF_MP_INT(tempX); + DEF_MP_INT(tempC); + DEF_MP_INT(tempP); + DEF_MP_INT(temp2q); int result; unsigned char *buf; @@ -148,7 +151,9 @@ static void getp(dss_key *key, unsigned int size) { static void getg(dss_key * key) { char printbuf[1000]; - mp_int div, h, val; + DEF_MP_INT(div); + DEF_MP_INT(h); + DEF_MP_INT(val); m_mp_init_multi(&div, &h, &val, NULL); @@ -185,7 +190,7 @@ static void getg(dss_key * key) { static void getx(dss_key *key) { - mp_int val; + DEF_MP_INT(val); char buf[QSIZE]; m_mp_init(&val); diff --git a/genrsa.c b/genrsa.c index 330ebf2..5711519 100644 --- a/genrsa.c +++ b/genrsa.c @@ -40,7 +40,9 @@ static void getrsaprime(mp_int* prime, mp_int *primeminus, rsa_key * gen_rsa_priv_key(unsigned int size) { rsa_key * key; - mp_int pminus, qminus, lcm; + DEF_MP_INT(pminus); + DEF_MP_INT(qminus); + DEF_MP_INT(lcm); key = (rsa_key*)m_malloc(sizeof(rsa_key)); @@ -95,7 +97,7 @@ static void getrsaprime(mp_int* prime, mp_int *primeminus, mp_int* rsa_e, unsigned int size) { unsigned char *buf; - mp_int temp_gcd; + DEF_MP_INT(temp_gcd); buf = (unsigned char*)m_malloc(size+1); diff --git a/options.h b/options.h index 2887c59..9e7d1ee 100644 --- a/options.h +++ b/options.h @@ -139,7 +139,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */ #define ENABLE_CLI_PUBKEY_AUTH /* Random device to use - you must specify _one only_. - * DEV_RANDOM is recommended on hosts with a good /dev/urandom, otherwise use + * DEV_URANDOM is recommended on hosts with a good /dev/urandom, otherwise use * PRNGD and run prngd, specifying the socket. This device must be able to * produce a large amount of random data, so using /dev/random or Entropy * Gathering Daemon (egd) may result in halting, as it waits for more random diff --git a/rsa.c b/rsa.c index 1130e93..7e891e0 100644 --- a/rsa.c +++ b/rsa.c @@ -201,7 +201,8 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data, unsigned int len) { unsigned int slen; - mp_int rsa_s, rsa_mdash; + DEF_MP_INT(rsa_s); + DEF_MP_INT(rsa_mdash); mp_int *rsa_em = NULL; int ret = DROPBEAR_FAILURE; @@ -262,7 +263,7 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, unsigned int nsize, ssize; unsigned int i; - mp_int rsa_s; + DEF_MP_INT(rsa_s); mp_int *rsa_em = NULL; TRACE(("enter buf_put_rsa_sign")); diff --git a/svr-kex.c b/svr-kex.c index 816779c..47c540e 100644 --- a/svr-kex.c +++ b/svr-kex.c @@ -44,7 +44,7 @@ static void send_msg_kexdh_reply(mp_int *dh_e); * that function, then brings the new keys into use */ void recv_msg_kexdh_init() { - mp_int dh_e; + DEF_MP_INT(dh_e); TRACE(("enter recv_msg_kexdh_init")); if (!ses.kexstate.recvkexinit) { @@ -71,9 +71,11 @@ void recv_msg_kexdh_init() { * See the ietf-secsh-transport draft, section 6, for details */ static void send_msg_kexdh_reply(mp_int *dh_e) { - mp_int dh_y, dh_f; + DEF_MP_INT(dh_y); + DEF_MP_INT(dh_f); TRACE(("enter send_msg_kexdh_reply")); + m_mp_init_multi(&dh_y, &dh_f, NULL); gen_kexdh_vals(&dh_f, &dh_y); -- cgit v1.2.3 From cf585ba1dee7a7e1f2fbc90d2251d99b7da66a7e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Thu, 5 May 2005 03:58:21 +0000 Subject: - refactored random mp_int generation and byte->mp_int code - added RSA blinding --HG-- extra : convert_revision : 5d5b4657a24a1c8f53c6fc45d5ec29ddb85fb45a --- bignum.c | 4 +-- bignum.h | 2 +- common-kex.c | 24 +++-------------- dss.c | 30 ++++++--------------- gendss.c | 28 +++----------------- genrsa.c | 5 +--- random.c | 36 +++++++++++++++++++++++++ random.h | 3 +++ rsa.c | 86 +++++++++++++++++++++++++++++++++++++++--------------------- 9 files changed, 115 insertions(+), 103 deletions(-) (limited to 'genrsa.c') diff --git a/bignum.c b/bignum.c index 97901fb..60b5220 100644 --- a/bignum.c +++ b/bignum.c @@ -52,9 +52,9 @@ void m_mp_init_multi(mp_int *mp, ...) va_end(args); } -void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len) { +void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len) { - if (mp_read_unsigned_bin(mp, bytes, len) != MP_OKAY) { + if (mp_read_unsigned_bin(mp, (unsigned char*)bytes, len) != MP_OKAY) { dropbear_exit("mem alloc error"); } } diff --git a/bignum.h b/bignum.h index 2a807af..042f811 100644 --- a/bignum.h +++ b/bignum.h @@ -29,7 +29,7 @@ void m_mp_init(mp_int *mp); void m_mp_init_multi(mp_int *mp, ...); -void bytestomp(mp_int *mp, unsigned char* bytes, unsigned int len); +void bytes_to_mp(mp_int *mp, const unsigned char* bytes, unsigned int len); void sha1_process_mp(hash_state *hs, mp_int *mp); #endif /* _BIGNUM_H_ */ diff --git a/common-kex.c b/common-kex.c index a2336c5..8a8aa93 100644 --- a/common-kex.c +++ b/common-kex.c @@ -469,18 +469,13 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { DEF_MP_INT(dh_p); DEF_MP_INT(dh_q); DEF_MP_INT(dh_g); - unsigned char randbuf[DH_P_LEN]; - int dh_q_len; TRACE(("enter send_msg_kexdh_reply")) m_mp_init_multi(&dh_g, &dh_p, &dh_q, NULL); /* read the prime and generator*/ - if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN) - != MP_OKAY) { - dropbear_exit("Diffie-Hellman error"); - } + bytes_to_mp(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN); if (mp_set_int(&dh_g, DH_G_VAL) != MP_OKAY) { dropbear_exit("Diffie-Hellman error"); @@ -495,16 +490,8 @@ void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv) { dropbear_exit("Diffie-Hellman error"); } - dh_q_len = mp_unsigned_bin_size(&dh_q); - - /* calculate our random value dh_y */ - do { - assert((unsigned int)dh_q_len <= sizeof(randbuf)); - genrandom(randbuf, dh_q_len); - if (mp_read_unsigned_bin(dh_priv, randbuf, dh_q_len) != MP_OKAY) { - dropbear_exit("Diffie-Hellman error"); - } - } while (mp_cmp(dh_priv, &dh_q) == MP_GT || mp_cmp_d(dh_priv, 0) != MP_GT); + /* Generate a private portion 0 < dh_priv < dh_q */ + gen_random_mpint(&dh_q, dh_priv); /* f = g^y mod p */ if (mp_exptmod(&dh_g, dh_priv, &dh_p, dh_pub) != MP_OKAY) { @@ -526,10 +513,7 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them, /* read the prime and generator*/ mp_init(&dh_p); - if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN) - != MP_OKAY) { - dropbear_exit("Diffie-Hellman error"); - } + bytes_to_mp(&dh_p, dh_p_val, DH_P_LEN); /* Check that dh_pub_them (dh_e or dh_f) is in the range [1, p-1] */ if (mp_cmp(dh_pub_them, &dh_p) != MP_LT diff --git a/dss.c b/dss.c index 5cf018d..cb877ca 100644 --- a/dss.c +++ b/dss.c @@ -190,10 +190,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, /* create the signature - s' and r' are the received signatures in buf */ /* w = (s')-1 mod q */ /* let val1 = s' */ - if (mp_read_unsigned_bin(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE) - != MP_OKAY) { - goto out; - } + bytes_to_mp(&val1, &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE); + if (mp_cmp(&val1, key->q) != MP_LT) { TRACE(("verify failed, s' >= q")) goto out; @@ -205,9 +203,8 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, /* u1 = ((SHA(M')w) mod q */ /* let val1 = SHA(M') = msghash */ - if (mp_read_unsigned_bin(&val1, msghash, SHA1_HASH_SIZE) != MP_OKAY) { - goto out; - } + bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE); + /* let val3 = u1 = ((SHA(M')w) mod q */ if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) { goto out; @@ -215,10 +212,7 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data, /* u2 = ((r')w) mod q */ /* let val1 = r' */ - if (mp_read_unsigned_bin(&val1, &string[0], SHA1_HASH_SIZE) - != MP_OKAY) { - goto out; - } + bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE); if (mp_cmp(&val1, key->q) != MP_LT) { TRACE(("verify failed, r' >= q")) goto out; @@ -306,8 +300,6 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data, unsigned char *privkeytmp; unsigned char proto_k[SHA512_HASH_SIZE]; DEF_MP_INT(dss_protok); -#else - unsigned char kbuf[SHA1_HASH_SIZE]; #endif DEF_MP_INT(dss_k); DEF_MP_INT(dss_m); @@ -345,22 +337,16 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data, /* generate k */ m_mp_init(&dss_protok); - bytestomp(&dss_protok, proto_k, SHA512_HASH_SIZE); + bytes_to_mp(&dss_protok, proto_k, SHA512_HASH_SIZE); mp_mod(&dss_protok, key->q, &dss_k); mp_clear(&dss_protok); m_burn(proto_k, SHA512_HASH_SIZE); #else /* DSS_PROTOK not defined*/ - do { - genrandom(kbuf, SHA1_HASH_SIZE); - if (mp_read_unsigned_bin(&dss_k, kbuf, SHA1_HASH_SIZE) != MP_OKAY) { - dropbear_exit("dss error"); - } - } while (mp_cmp(&dss_k, key->q) == MP_GT || mp_cmp_d(&dss_k, 0) != MP_GT); - m_burn(kbuf, SHA1_HASH_SIZE); + gen_random_mpint(key->q, &dss_k); #endif /* now generate the actual signature */ - bytestomp(&dss_m, msghash, SHA1_HASH_SIZE); + bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE); /* g^k mod p */ if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) { diff --git a/gendss.c b/gendss.c index d589722..bf46d3d 100644 --- a/gendss.c +++ b/gendss.c @@ -77,10 +77,7 @@ static void getq(dss_key *key) { buf[0] |= 0x80; /* top bit high */ buf[QSIZE-1] |= 0x01; /* bottom bit high */ - if (mp_read_unsigned_bin(key->q, buf, QSIZE) != MP_OKAY) { - fprintf(stderr, "dss key generation failed\n"); - exit(1); - } + bytes_to_mp(key->q, buf, QSIZE); /* 18 rounds are required according to HAC */ if (mp_prime_next_prime(key->q, 18, 0) != MP_OKAY) { @@ -116,10 +113,7 @@ static void getp(dss_key *key, unsigned int size) { buf[0] |= 0x80; /* set the top bit high */ /* X is a random mp_int */ - if (mp_read_unsigned_bin(&tempX, buf, size) != MP_OKAY) { - fprintf(stderr, "dss key generation failed\n"); - exit(1); - } + bytes_to_mp(&tempX, buf, size); /* C = X mod 2q */ if (mp_mod(&tempX, &temp2q, &tempC) != MP_OKAY) { @@ -147,6 +141,7 @@ static void getp(dss_key *key, unsigned int size) { } while (!result); mp_clear_multi(&tempX, &tempC, &tempP, &temp2q, NULL); + m_burn(buf, size); m_free(buf); } @@ -189,22 +184,7 @@ static void getg(dss_key * key) { static void getx(dss_key *key) { - DEF_MP_INT(val); - char buf[QSIZE]; - - m_mp_init(&val); - - do { - genrandom(buf, QSIZE); - - if (mp_read_unsigned_bin(&val, buf, QSIZE) != MP_OKAY) { - fprintf(stderr, "dss key generation failed\n"); - } - } while ((mp_cmp_d(&val, 1) == MP_GT) && (mp_cmp(&val, key->q) == MP_LT)); - - mp_copy(&val, key->x); - mp_clear(&val); - + gen_random_mpint(key->q, key->x); } static void gety(dss_key *key) { diff --git a/genrsa.c b/genrsa.c index 5711519..73a7984 100644 --- a/genrsa.c +++ b/genrsa.c @@ -108,10 +108,7 @@ static void getrsaprime(mp_int* prime, mp_int *primeminus, genrandom(buf, size+1); buf[0] |= 0x80; /* MSB set */ - if (mp_read_unsigned_bin(prime, buf, size+1) != MP_OKAY) { - fprintf(stderr, "rsa generation failed\n"); - exit(1); - } + bytes_to_mp(prime, buf, size+1); /* find the next integer which is prime, 8 round of miller-rabin */ if (mp_prime_next_prime(prime, 8, 0) != MP_OKAY) { diff --git a/random.c b/random.c index c69f641..2b2777a 100644 --- a/random.c +++ b/random.c @@ -25,6 +25,7 @@ #include "includes.h" #include "buffer.h" #include "dbutil.h" +#include "bignum.h" int donerandinit = 0; @@ -159,3 +160,38 @@ void genrandom(unsigned char* buf, unsigned int len) { } m_burn(hash, sizeof(hash)); } + +/* Generates a random mp_int. + * max is a *mp_int specifying an upper bound. + * rand must be an initialised *mp_int for the result. + * the result rand satisfies: 0 < rand < max + * */ +void gen_random_mpint(mp_int *max, mp_int *rand) { + + unsigned char *randbuf = NULL; + unsigned int len = 0; + const char masks[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; + + const int size_bits = mp_count_bits(max); + + len = size_bits / 8; + if ((size_bits % 8) != 0) { + len += 1; + } + + randbuf = (unsigned char*)m_malloc(len); + do { + genrandom(randbuf, len); + /* Mask out the unrequired bits - mp_read_unsigned_bin expects + * MSB first.*/ + randbuf[0] &= masks[size_bits % 8]; + + bytes_to_mp(rand, randbuf, len); + + /* keep regenerating until we get one satisfying + * 0 < rand < max */ + } while ( ( (max != NULL) && (mp_cmp(rand, max) != MP_LT) ) + || (mp_cmp_d(rand, 0) != MP_GT) ); + m_burn(randbuf, len); + m_free(randbuf); +} diff --git a/random.h b/random.h index 91aa342..5ec1f24 100644 --- a/random.h +++ b/random.h @@ -25,8 +25,11 @@ #ifndef _RANDOM_H_ #define _RANDOM_H_ +struct mp_int; + void seedrandom(); void genrandom(unsigned char* buf, int len); void addrandom(unsigned char* buf, int len); +void gen_random_mpint(mp_int *max, mp_int *rand); #endif /* _RANDOM_H_ */ diff --git a/rsa.c b/rsa.c index 1ac0357..8b24360 100644 --- a/rsa.c +++ b/rsa.c @@ -38,8 +38,9 @@ #ifdef DROPBEAR_RSA -static mp_int * rsa_pad_em(rsa_key * key, - const unsigned char * data, unsigned int len); +static void rsa_pad_em(rsa_key * key, + const unsigned char * data, unsigned int len, + mp_int * rsa_em); /* Load a public rsa key from a buffer, initialising the values. * The key will have the same format as buf_put_rsa_key. @@ -203,14 +204,14 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data, unsigned int slen; DEF_MP_INT(rsa_s); DEF_MP_INT(rsa_mdash); - mp_int *rsa_em = NULL; + DEF_MP_INT(rsa_em); int ret = DROPBEAR_FAILURE; TRACE(("enter buf_rsa_verify")) assert(key != NULL); - m_mp_init_multi(&rsa_mdash, &rsa_s, NULL); + m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL); slen = buf_getint(buf); if (slen != (unsigned int)mp_unsigned_bin_size(key->n)) { @@ -231,29 +232,25 @@ int buf_rsa_verify(buffer * buf, rsa_key *key, const unsigned char* data, } /* create the magic PKCS padded value */ - rsa_em = rsa_pad_em(key, data, len); + rsa_pad_em(key, data, len, &rsa_em); if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) { TRACE(("failed exptmod rsa_s")) goto out; } - if (mp_cmp(rsa_em, &rsa_mdash) == MP_EQ) { + if (mp_cmp(&rsa_em, &rsa_mdash) == MP_EQ) { /* signature is valid */ TRACE(("success!")) ret = DROPBEAR_SUCCESS; } out: - if (rsa_em) { - mp_clear(rsa_em); - m_free(rsa_em); - } - mp_clear_multi(&rsa_mdash, &rsa_s, NULL); + mp_clear_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL); TRACE(("leave buf_rsa_verify: ret %d", ret)) return ret; - } + #endif /* DROPBEAR_SIGNKEY_VERIFY */ /* Sign the data presented with key, writing the signature contents @@ -264,22 +261,56 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, unsigned int nsize, ssize; unsigned int i; DEF_MP_INT(rsa_s); - mp_int *rsa_em = NULL; + DEF_MP_INT(rsa_tmp1); + DEF_MP_INT(rsa_tmp2); + DEF_MP_INT(rsa_tmp3); + unsigned char *tmpbuf; TRACE(("enter buf_put_rsa_sign")) assert(key != NULL); - rsa_em = rsa_pad_em(key, data, len); + m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL); - m_mp_init(&rsa_s); + rsa_pad_em(key, data, len, &rsa_tmp1); /* the actual signing of the padded data */ + +#define RSA_BLINDING +#ifdef RSA_BLINDING + + /* With blinding, s = (r^(-1))((em)*r^e)^d mod n */ + + /* generate the r blinding value */ + /* rsa_tmp2 is r */ + gen_random_mpint(key->n, &rsa_tmp2); + + /* rsa_tmp1 is em */ + /* em' = em * r^e mod n */ + + mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s); /* rsa_s used as a temp var*/ + mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3); + mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2); + + /* rsa_tmp2 is em' */ + /* s' = (em')^d mod n */ + mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1); + + /* rsa_tmp1 is s' */ + /* rsa_tmp3 is r^(-1) mod n */ + /* s = (s')r^(-1) mod n */ + mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s); + +#else + /* s = em^d mod n */ - if (mp_exptmod(rsa_em, key->d, key->n, &rsa_s) != MP_OKAY) { + /* rsa_tmp1 is em */ + if (mp_exptmod(&rsa_tmp1, key->d, key->n, &rsa_s) != MP_OKAY) { dropbear_exit("rsa error"); } - mp_clear(rsa_em); - m_free(rsa_em); + +#endif /* RSA_BLINDING */ + + mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL); /* create the signature to return */ buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN); @@ -318,9 +349,12 @@ void buf_put_rsa_sign(buffer* buf, rsa_key *key, const unsigned char* data, * * prefix is the ASN1 designator prefix, * hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14 + * + * rsa_em must be a pointer to an initialised mp_int. */ -static mp_int * rsa_pad_em(rsa_key * key, - const unsigned char * data, unsigned int len) { +static void rsa_pad_em(rsa_key * key, + const unsigned char * data, unsigned int len, + mp_int * rsa_em) { /* ASN1 designator (including the 0x00 preceding) */ const char rsa_asn1_magic[] = @@ -330,7 +364,6 @@ static mp_int * rsa_pad_em(rsa_key * key, buffer * rsa_EM = NULL; hash_state hs; unsigned int nsize; - mp_int * rsa_em = NULL; assert(key != NULL); assert(data != NULL); @@ -358,16 +391,9 @@ static mp_int * rsa_pad_em(rsa_key * key, /* Create the mp_int from the encoded bytes */ buf_setpos(rsa_EM, 0); - rsa_em = (mp_int*)m_malloc(sizeof(mp_int)); - m_mp_init(rsa_em); - if (mp_read_unsigned_bin(rsa_em, buf_getptr(rsa_EM, rsa_EM->size), - rsa_EM->size) != MP_OKAY) { - dropbear_exit("rsa error"); - } + bytes_to_mp(rsa_em, buf_getptr(rsa_EM, rsa_EM->size), + rsa_EM->size); buf_free(rsa_EM); - - return rsa_em; - } #endif /* DROPBEAR_RSA */ -- cgit v1.2.3