* SOFTWARE. */
#include "includes.h"
-#include "util.h"
+#include "dbutil.h"
#include "bignum.h"
#include "dss.h"
#include "buffer.h"
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
+ TRACE(("enter buf_get_dss_pub_key"))
assert(key != NULL);
key->p = m_malloc(sizeof(mp_int));
key->q = m_malloc(sizeof(mp_int));
|| buf_getmpint(buf, key->q) == DROPBEAR_FAILURE
|| buf_getmpint(buf, key->g) == DROPBEAR_FAILURE
|| buf_getmpint(buf, key->y) == DROPBEAR_FAILURE) {
+ TRACE(("leave buf_get_dss_pub_key: failed reading mpints"))
return DROPBEAR_FAILURE;
}
+ if (mp_count_bits(key->p) < MIN_DSS_KEYLEN) {
+ dropbear_log(LOG_WARNING, "DSS key too short");
+ TRACE(("leave buf_get_dss_pub_key: short key"))
+ return DROPBEAR_FAILURE;
+ }
+
+ TRACE(("leave buf_get_dss_pub_key: success"))
return DROPBEAR_SUCCESS;
}
/* Clear and free the memory used by a public or private key */
void dss_key_free(dss_key *key) {
- TRACE(("enter dsa_key_free"));
+ TRACE(("enter dsa_key_free"))
if (key == NULL) {
- TRACE(("enter dsa_key_free: key == NULL"));
+ TRACE(("enter dsa_key_free: key == NULL"))
return;
}
if (key->p) {
m_free(key->x);
}
m_free(key);
- TRACE(("leave dsa_key_free"));
+ TRACE(("leave dsa_key_free"))
}
/* put the dss public key into the buffer in the required format:
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;
- TRACE(("enter buf_dss_verify"));
+ TRACE(("enter buf_dss_verify"))
assert(key != NULL);
+ m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
+
/* get blob, check length */
string = buf_getstring(buf, &stringlen);
if (stringlen != 2*SHA1_HASH_SIZE) {
sha1_process(&hs, data, len);
sha1_done(&hs, msghash);
- m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
-
/* 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) {
+ 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;
}
/* let val2 = w = (s')^-1 mod q*/
/* 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;
/* u2 = ((r')w) mod q */
/* let val1 = r' */
- if (mp_read_unsigned_bin(&val1, &string[0], SHA1_HASH_SIZE)
- != MP_OKAY) {
+ bytes_to_mp(&val1, &string[0], SHA1_HASH_SIZE);
+ if (mp_cmp(&val1, key->q) != MP_LT) {
+ TRACE(("verify failed, r' >= q"))
goto out;
}
/* let val4 = u2 = ((r')w) mod q */
}
#endif /* DROPBEAR_SIGNKEY_VERIFY */
+#ifdef DSS_PROTOK
+/* convert an unsigned mp into an array of bytes, malloced.
+ * This array must be freed after use, len contains the length of the array,
+ * if len != NULL */
+static unsigned char* mptobytes(mp_int *mp, int *len) {
+
+ unsigned char* ret;
+ int size;
+
+ size = mp_unsigned_bin_size(mp);
+ ret = m_malloc(size);
+ if (mp_to_unsigned_bin(mp, ret) != MP_OKAY) {
+ dropbear_exit("mem alloc error");
+ }
+ if (len != NULL) {
+ *len = size;
+ }
+ return ret;
+}
+#endif
+
/* Sign the data presented with key, writing the signature contents
* to the buffer
*
unsigned char privkeyhash[SHA512_HASH_SIZE];
unsigned char *privkeytmp;
unsigned char proto_k[SHA512_HASH_SIZE];
- mp_int dss_protok;
-#else
- unsigned char kbuf[SHA1_HASH_SIZE];
+ DEF_MP_INT(dss_protok);
#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"));
+ TRACE(("enter buf_put_dss_sign"))
assert(key != NULL);
/* hash the 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) {
mp_clear(&dss_s);
buf_incrwritepos(buf, writelen);
- mp_clear_multi(&dss_k, &dss_temp1, &dss_temp1, &dss_r, &dss_s,
+ mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
&dss_m, NULL);
/* create the signature to return */
- TRACE(("leave buf_put_dss_sign"));
+ TRACE(("leave buf_put_dss_sign"))
}
#endif /* DROPBEAR_DSS */