www.usr.com/support/gpl/USR9107_release.1.4.tar.gz
[bcm963xx.git] / userapps / opensource / sshd / dss.c
index 1c31ca8..cb877ca 100755 (executable)
@@ -23,7 +23,7 @@
  * SOFTWARE. */
 
 #include "includes.h"
-#include "util.h"
+#include "dbutil.h"
 #include "bignum.h"
 #include "dss.h"
 #include "buffer.h"
@@ -45,6 +45,7 @@
  * 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));
@@ -58,9 +59,17 @@ int buf_get_dss_pub_key(buffer* buf, dss_key *key) {
         || 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;
 }
 
@@ -89,9 +98,9 @@ int buf_get_dss_priv_key(buffer* buf, dss_key *key) {
 /* 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) {
@@ -115,7 +124,7 @@ void dss_key_free(dss_key *key) {
                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:
@@ -155,13 +164,18 @@ 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;
 
-       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) {
@@ -173,13 +187,13 @@ int buf_dss_verify(buffer* buf, dss_key *key, const unsigned char* data,
        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*/
@@ -189,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;
@@ -199,8 +212,9 @@ 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) {
+       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 */
@@ -241,6 +255,27 @@ out:
 }
 #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
  *
@@ -264,16 +299,17 @@ 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;
-#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 */
@@ -301,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) {
@@ -375,12 +405,12 @@ void buf_put_dss_sign(buffer* buf, dss_key *key, const unsigned char* data,
        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 */