- refactored random mp_int generation and byte->mp_int code

- added RSA blinding

--HG--
extra : convert_revision : 5d5b4657a24a1c8f53c6fc45d5ec29ddb85fb45a
This commit is contained in:
Matt Johnston 2005-05-05 03:58:21 +00:00
parent 298a5717bc
commit cf585ba1de
9 changed files with 115 additions and 103 deletions

View File

@ -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");
}
}

View File

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

View File

@ -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

30
dss.c
View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}

View File

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

86
rsa.c
View File

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