summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bignum.c4
-rw-r--r--bignum.h2
-rw-r--r--common-kex.c24
-rw-r--r--dss.c30
-rw-r--r--gendss.c28
-rw-r--r--genrsa.c5
-rw-r--r--random.c36
-rw-r--r--random.h3
-rw-r--r--rsa.c86
9 files changed, 115 insertions, 103 deletions
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 */