123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #include "includes.h"
- #include "ecc.h"
- #include "dbutil.h"
- #include "bignum.h"
- #if DROPBEAR_ECC
- /* .dp members are filled out by dropbear_ecc_fill_dp() at startup */
- #if DROPBEAR_ECC_256
- struct dropbear_ecc_curve ecc_curve_nistp256 = {
- 32, /* .ltc_size */
- NULL, /* .dp */
- &sha256_desc, /* .hash_desc */
- "nistp256" /* .name */
- };
- #endif
- #if DROPBEAR_ECC_384
- struct dropbear_ecc_curve ecc_curve_nistp384 = {
- 48, /* .ltc_size */
- NULL, /* .dp */
- &sha384_desc, /* .hash_desc */
- "nistp384" /* .name */
- };
- #endif
- #if DROPBEAR_ECC_521
- struct dropbear_ecc_curve ecc_curve_nistp521 = {
- 66, /* .ltc_size */
- NULL, /* .dp */
- &sha512_desc, /* .hash_desc */
- "nistp521" /* .name */
- };
- #endif
- struct dropbear_ecc_curve *dropbear_ecc_curves[] = {
- #if DROPBEAR_ECC_256
- &ecc_curve_nistp256,
- #endif
- #if DROPBEAR_ECC_384
- &ecc_curve_nistp384,
- #endif
- #if DROPBEAR_ECC_521
- &ecc_curve_nistp521,
- #endif
- NULL
- };
- void dropbear_ecc_fill_dp() {
- struct dropbear_ecc_curve **curve;
- /* libtomcrypt guarantees they're ordered by size */
- const ltc_ecc_set_type *dp = ltc_ecc_sets;
- for (curve = dropbear_ecc_curves; *curve; curve++) {
- for (;dp->size > 0; dp++) {
- if (dp->size == (*curve)->ltc_size) {
- (*curve)->dp = dp;
- break;
- }
- }
- if (!(*curve)->dp) {
- dropbear_exit("Missing ECC params %s", (*curve)->name);
- }
- }
- }
- struct dropbear_ecc_curve* curve_for_dp(const ltc_ecc_set_type *dp) {
- struct dropbear_ecc_curve **curve = NULL;
- for (curve = dropbear_ecc_curves; *curve; curve++) {
- if ((*curve)->dp == dp) {
- break;
- }
- }
- assert(*curve);
- return *curve;
- }
- ecc_key * new_ecc_key(void) {
- ecc_key *key = m_malloc(sizeof(*key));
- m_mp_alloc_init_multi((mp_int**)&key->pubkey.x, (mp_int**)&key->pubkey.y,
- (mp_int**)&key->pubkey.z, (mp_int**)&key->k, NULL);
- return key;
- }
- /* Copied from libtomcrypt ecc_import.c (version there is static), modified
- for different mp_int pointer without LTC_SOURCE */
- static int ecc_is_point(const ecc_key *key)
- {
- mp_int *prime, *b, *t1, *t2;
- int err;
-
- m_mp_alloc_init_multi(&prime, &b, &t1, &t2, NULL);
-
- /* load prime and b */
- if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; }
- if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; }
-
- /* compute y^2 */
- if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; }
-
- /* compute x^3 */
- if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; }
- if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; }
- if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; }
-
- /* compute y^2 - x^3 */
- if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; }
-
- /* compute y^2 - x^3 + 3x */
- if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
- if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
- if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
- if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; }
- while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
- if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; }
- }
- while (mp_cmp(t1, prime) != LTC_MP_LT) {
- if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; }
- }
-
- /* compare to b */
- if (mp_cmp(t1, b) != LTC_MP_EQ) {
- err = CRYPT_INVALID_PACKET;
- } else {
- err = CRYPT_OK;
- }
-
- error:
- mp_clear_multi(prime, b, t1, t2, NULL);
- m_free(prime);
- m_free(b);
- m_free(t1);
- m_free(t2);
- return err;
- }
- /* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */
- void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key) {
- unsigned long len = key->dp->size*2 + 1;
- int err;
- buf_putint(buf, len);
- err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len);
- if (err != CRYPT_OK) {
- dropbear_exit("ECC error");
- }
- buf_incrwritepos(buf, len);
- }
- /* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */
- ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve) {
- ecc_key *key = NULL;
- int ret = DROPBEAR_FAILURE;
- const unsigned int size = curve->dp->size;
- unsigned char first;
- TRACE(("enter buf_get_ecc_raw_pubkey"))
- buf_setpos(buf, 0);
- first = buf_getbyte(buf);
- if (first == 2 || first == 3) {
- dropbear_log(LOG_WARNING, "Dropbear doesn't support ECC point compression");
- return NULL;
- }
- if (first != 4 || buf->len != 1+2*size) {
- TRACE(("leave, wrong size"))
- return NULL;
- }
- key = new_ecc_key();
- key->dp = curve->dp;
- if (mp_from_ubin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) {
- TRACE(("failed to read x"))
- goto out;
- }
- buf_incrpos(buf, size);
- if (mp_from_ubin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) {
- TRACE(("failed to read y"))
- goto out;
- }
- buf_incrpos(buf, size);
- mp_set(key->pubkey.z, 1);
- if (ecc_is_point(key) != CRYPT_OK) {
- TRACE(("failed, not a point"))
- goto out;
- }
- /* SEC1 3.2.3.1 Check that Q != 0 */
- if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) {
- TRACE(("failed, x == 0"))
- goto out;
- }
- if (mp_cmp_d(key->pubkey.y, 0) == LTC_MP_EQ) {
- TRACE(("failed, y == 0"))
- goto out;
- }
- ret = DROPBEAR_SUCCESS;
- out:
- if (ret == DROPBEAR_FAILURE) {
- if (key) {
- ecc_free(key);
- m_free(key);
- key = NULL;
- }
- }
- return key;
- }
- /* a modified version of libtomcrypt's "ecc_shared_secret" to output
- a mp_int instead. */
- mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, const ecc_key *private_key)
- {
- ecc_point *result = NULL;
- mp_int *prime = NULL, *shared_secret = NULL;
- int err = DROPBEAR_FAILURE;
- /* type valid? */
- if (private_key->type != PK_PRIVATE) {
- goto out;
- }
- if (private_key->dp != public_key->dp) {
- goto out;
- }
- /* make new point */
- result = ltc_ecc_new_point();
- if (result == NULL) {
- goto out;
- }
- prime = m_malloc(sizeof(*prime));
- m_mp_init(prime);
- if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) {
- goto out;
- }
- if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) {
- goto out;
- }
- shared_secret = m_malloc(sizeof(*shared_secret));
- m_mp_init(shared_secret);
- if (mp_copy(result->x, shared_secret) != CRYPT_OK) {
- goto out;
- }
- mp_clear(prime);
- m_free(prime);
- ltc_ecc_del_point(result);
- err = DROPBEAR_SUCCESS;
- out:
- if (err == DROPBEAR_FAILURE) {
- dropbear_exit("ECC error");
- }
- return shared_secret;
- }
- #endif
|