123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- #include "includes.h"
- #include "dbutil.h"
- #include "bignum.h"
- #include "dss.h"
- #include "buffer.h"
- #include "ssh.h"
- #include "dbrandom.h"
- #if DROPBEAR_DSS
- int buf_get_dss_pub_key(buffer* buf, dropbear_dss_key *key) {
- int ret = DROPBEAR_FAILURE;
- TRACE(("enter buf_get_dss_pub_key"))
- dropbear_assert(key != NULL);
- m_mp_alloc_init_multi(&key->p, &key->q, &key->g, &key->y, NULL);
- key->x = NULL;
- buf_incrpos(buf, 4+SSH_SIGNKEY_DSS_LEN);
- if (buf_getmpint(buf, key->p) == DROPBEAR_FAILURE
- || 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"))
- ret = DROPBEAR_FAILURE;
- goto out;
- }
- if (mp_count_bits(key->p) != DSS_P_BITS) {
- dropbear_log(LOG_WARNING, "Bad DSS p");
- ret = DROPBEAR_FAILURE;
- goto out;
- }
- if (mp_count_bits(key->q) != DSS_Q_BITS) {
- dropbear_log(LOG_WARNING, "Bad DSS q");
- ret = DROPBEAR_FAILURE;
- goto out;
- }
-
- if (mp_cmp_d(key->g, 1) != MP_GT) {
- dropbear_log(LOG_WARNING, "Bad DSS g");
- ret = DROPBEAR_FAILURE;
- goto out;
- }
- if (mp_cmp(key->g, key->p) != MP_LT) {
- dropbear_log(LOG_WARNING, "Bad DSS g");
- ret = DROPBEAR_FAILURE;
- goto out;
- }
- ret = DROPBEAR_SUCCESS;
- TRACE(("leave buf_get_dss_pub_key: success"))
- out:
- if (ret == DROPBEAR_FAILURE) {
- m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, NULL);
- }
- return ret;
- }
- int buf_get_dss_priv_key(buffer* buf, dropbear_dss_key *key) {
- int ret = DROPBEAR_FAILURE;
- dropbear_assert(key != NULL);
- ret = buf_get_dss_pub_key(buf, key);
- if (ret == DROPBEAR_FAILURE) {
- return DROPBEAR_FAILURE;
- }
- m_mp_alloc_init_multi(&key->x, NULL);
- ret = buf_getmpint(buf, key->x);
- if (ret == DROPBEAR_FAILURE) {
- m_mp_free_multi(&key->x, NULL);
- }
- return ret;
- }
-
- void dss_key_free(dropbear_dss_key *key) {
- TRACE2(("enter dsa_key_free"))
- if (key == NULL) {
- TRACE2(("enter dsa_key_free: key == NULL"))
- return;
- }
- m_mp_free_multi(&key->p, &key->q, &key->g, &key->y, &key->x, NULL);
- m_free(key);
- TRACE2(("leave dsa_key_free"))
- }
- void buf_put_dss_pub_key(buffer* buf, const dropbear_dss_key *key) {
- dropbear_assert(key != NULL);
- buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
- buf_putmpint(buf, key->p);
- buf_putmpint(buf, key->q);
- buf_putmpint(buf, key->g);
- buf_putmpint(buf, key->y);
- }
- void buf_put_dss_priv_key(buffer* buf, const dropbear_dss_key *key) {
- dropbear_assert(key != NULL);
- buf_put_dss_pub_key(buf, key);
- buf_putmpint(buf, key->x);
- }
- #if DROPBEAR_SIGNKEY_VERIFY
- int buf_dss_verify(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
- unsigned char msghash[SHA1_HASH_SIZE];
- hash_state hs;
- int ret = DROPBEAR_FAILURE;
- DEF_MP_INT(val1);
- DEF_MP_INT(val2);
- DEF_MP_INT(val3);
- DEF_MP_INT(val4);
- char * string = NULL;
- unsigned int stringlen;
- TRACE(("enter buf_dss_verify"))
- dropbear_assert(key != NULL);
- m_mp_init_multi(&val1, &val2, &val3, &val4, NULL);
-
- string = buf_getstring(buf, &stringlen);
- if (stringlen != 2*SHA1_HASH_SIZE) {
- goto out;
- }
- #if DEBUG_DSS_VERIFY
- printmpint("dss verify p", key->p);
- printmpint("dss verify q", key->q);
- printmpint("dss verify g", key->g);
- printmpint("dss verify y", key->y);
- #endif
-
- sha1_init(&hs);
- sha1_process(&hs, data_buf->data, data_buf->len);
- sha1_done(&hs, msghash);
-
-
-
- bytes_to_mp(&val1, (const unsigned char*) &string[SHA1_HASH_SIZE], SHA1_HASH_SIZE);
- #if DEBUG_DSS_VERIFY
- printmpint("dss verify s'", &val1);
- #endif
- if (mp_cmp(&val1, key->q) != MP_LT) {
- TRACE(("verify failed, s' >= q"))
- goto out;
- }
- if (mp_cmp_d(&val1, 0) != MP_GT) {
- TRACE(("verify failed, s' <= 0"))
- goto out;
- }
-
- if (mp_invmod(&val1, key->q, &val2) != MP_OKAY) {
- goto out;
- }
-
-
- bytes_to_mp(&val1, msghash, SHA1_HASH_SIZE);
- #if DEBUG_DSS_VERIFY
- printmpint("dss verify r'", &val1);
- #endif
-
- if (mp_mulmod(&val1, &val2, key->q, &val3) != MP_OKAY) {
- goto out;
- }
-
-
- bytes_to_mp(&val1, (const unsigned char*) &string[0], SHA1_HASH_SIZE);
- if (mp_cmp(&val1, key->q) != MP_LT) {
- TRACE(("verify failed, r' >= q"))
- goto out;
- }
- if (mp_cmp_d(&val1, 0) != MP_GT) {
- TRACE(("verify failed, r' <= 0"))
- goto out;
- }
-
- if (mp_mulmod(&val1, &val2, key->q, &val4) != MP_OKAY) {
- goto out;
- }
-
-
- if (mp_exptmod(key->g, &val3, key->p, &val2) != MP_OKAY) {
- goto out;
- }
-
- if (mp_exptmod(key->y, &val4, key->p, &val3) != MP_OKAY) {
- goto out;
- }
-
- if (mp_mulmod(&val2, &val3, key->p, &val4) != MP_OKAY) {
- goto out;
- }
-
- if (mp_mod(&val4, key->q, &val2) != MP_OKAY) {
- goto out;
- }
-
-
- if (mp_cmp(&val2, &val1) == MP_EQ) {
-
- ret = DROPBEAR_SUCCESS;
- }
- out:
- mp_clear_multi(&val1, &val2, &val3, &val4, NULL);
- m_free(string);
- return ret;
- }
- #endif
- void buf_put_dss_sign(buffer* buf, const dropbear_dss_key *key, const buffer *data_buf) {
- unsigned char msghash[SHA1_HASH_SIZE];
- unsigned int writelen;
- unsigned int i;
- size_t written;
- 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"))
- dropbear_assert(key != NULL);
-
-
- sha1_init(&hs);
- sha1_process(&hs, data_buf->data, data_buf->len);
- sha1_done(&hs, msghash);
- m_mp_init_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
- &dss_m, NULL);
-
- gen_random_mpint(key->q, &dss_k);
-
- bytes_to_mp(&dss_m, msghash, SHA1_HASH_SIZE);
-
- if (mp_exptmod(key->g, &dss_k, key->p, &dss_temp1) != MP_OKAY) {
- dropbear_exit("DSS error");
- }
-
- if (mp_mod(&dss_temp1, key->q, &dss_r) != MP_OKAY) {
- dropbear_exit("DSS error");
- }
-
- if (mp_mulmod(&dss_r, key->x, key->q, &dss_temp1) != MP_OKAY) {
- dropbear_exit("DSS error");
- }
-
- if (mp_addmod(&dss_m, &dss_temp1, key->q, &dss_temp2) != MP_OKAY) {
- dropbear_exit("DSS error");
- }
-
-
- if (mp_invmod(&dss_k, key->q, &dss_temp1) != MP_OKAY) {
- dropbear_exit("DSS error");
- }
-
- if (mp_mulmod(&dss_temp1, &dss_temp2, key->q, &dss_s) != MP_OKAY) {
- dropbear_exit("DSS error");
- }
- buf_putstring(buf, SSH_SIGNKEY_DSS, SSH_SIGNKEY_DSS_LEN);
- buf_putint(buf, 2*SHA1_HASH_SIZE);
- writelen = mp_ubin_size(&dss_r);
- dropbear_assert(writelen <= SHA1_HASH_SIZE);
-
- for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
- buf_putbyte(buf, 0);
- }
- if (mp_to_ubin(&dss_r, buf_getwriteptr(buf, writelen), writelen, &written)
- != MP_OKAY) {
- dropbear_exit("DSS error");
- }
- mp_clear(&dss_r);
- buf_incrwritepos(buf, written);
- writelen = mp_ubin_size(&dss_s);
- dropbear_assert(writelen <= SHA1_HASH_SIZE);
-
- for (i = 0; i < SHA1_HASH_SIZE - writelen; i++) {
- buf_putbyte(buf, 0);
- }
- if (mp_to_ubin(&dss_s, buf_getwriteptr(buf, writelen), writelen, &written)
- != MP_OKAY) {
- dropbear_exit("DSS error");
- }
- mp_clear(&dss_s);
- buf_incrwritepos(buf, written);
- mp_clear_multi(&dss_k, &dss_temp1, &dss_temp2, &dss_r, &dss_s,
- &dss_m, NULL);
-
-
- TRACE(("leave buf_put_dss_sign"))
- }
- #endif
|