Mercurial > dropbear
comparison ecc.c @ 759:76fba0856749 ecc
More changes for KEX and ECDH. Set up hash descriptors, make ECC code work,
ses.hash and ses.session_id are now buffers (doesn't compile)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 29 Mar 2013 00:28:09 +0800 |
parents | 230666086711 |
children | ac2158e3e403 |
comparison
equal
deleted
inserted
replaced
758:1c607a62d235 | 759:76fba0856749 |
---|---|
1 #include "includes.h" | 1 #include "includes.h" |
2 #include "options.h" | 2 #include "options.h" |
3 #include "ecc.h" | 3 #include "ecc.h" |
4 #include "dbutil.h" | |
5 #include "bignum.h" | |
4 | 6 |
5 #ifdef DROPBEAR_ECC | 7 #ifdef DROPBEAR_ECC |
6 | 8 |
7 // TODO: use raw bytes for the dp rather than the hex strings in libtomcrypt's ecc.c | 9 // TODO: use raw bytes for the dp rather than the hex strings in libtomcrypt's ecc.c |
8 | 10 |
9 #ifdef DROPBEAR_ECC_256 | 11 #ifdef DROPBEAR_ECC_256 |
10 const struct dropbear_ecc_curve ecc_curve_secp256r1 { | 12 const struct dropbear_ecc_curve ecc_curve_secp256r1 = { |
11 .dp = <c_ecc_sets[0], | 13 .dp = <c_ecc_sets[0], |
12 .hash_desc = sha256_desc, | 14 .hash_desc = &sha256_desc, |
13 .name = "secp256r1" | 15 .name = "secp256r1" |
14 }; | 16 }; |
15 #endif | 17 #endif |
16 | |
17 | |
18 #ifdef DROPBEAR_ECC_384 | 18 #ifdef DROPBEAR_ECC_384 |
19 const struct dropbear_ecc_curve ecc_curve_secp384r1 { | 19 const struct dropbear_ecc_curve ecc_curve_secp384r1 = { |
20 .dp = <c_ecc_sets[1], | 20 .dp = <c_ecc_sets[1], |
21 .hash_desc = sha384_desc, | 21 .hash_desc = &sha384_desc, |
22 .name = "secp384r1" | 22 .name = "secp384r1" |
23 }; | 23 }; |
24 #endif | 24 #endif |
25 | |
26 #ifdef DROPBEAR_ECC_521 | 25 #ifdef DROPBEAR_ECC_521 |
27 const struct dropbear_ecc_curve ecc_curve_secp521r1 { | 26 const struct dropbear_ecc_curve ecc_curve_secp521r1 = { |
28 .dp = <c_ecc_sets[2], | 27 .dp = <c_ecc_sets[2], |
29 .hash_desc = sha521_desc, | 28 .hash_desc = &sha512_desc, |
30 .name = "secp521r1" | 29 .name = "secp521r1" |
31 }; | 30 }; |
32 #endif | 31 #endif |
33 | 32 |
33 static ecc_key * new_ecc_key(void) { | |
34 ecc_key *key = m_malloc(sizeof(*key)); | |
35 key->pubkey.x = m_malloc(sizeof(mp_int)); | |
36 key->pubkey.y = m_malloc(sizeof(mp_int)); | |
37 key->pubkey.z = m_malloc(sizeof(mp_int)); | |
38 key->k = m_malloc(sizeof(mp_init)); | |
39 m_mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); | |
40 return key; | |
41 } | |
34 | 42 |
35 void buf_put_ecc_pubkey_string(buffer *buf, ecc_key *key) { | 43 void buf_put_ecc_pubkey_string(buffer *buf, ecc_key *key) { |
36 // XXX point compression | 44 unsigned long len = key->dp->size*2 + 1; |
37 int len = key->dp->size*2 + 1; | 45 buf_putint(buf, len); |
38 buf_putint(len); | |
39 int err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len); | 46 int err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len); |
40 if (err != CRYPT_OK) { | 47 if (err != CRYPT_OK) { |
41 dropbear_exit("ECC error"); | 48 dropbear_exit("ECC error"); |
42 } | 49 } |
43 buf_incrwritepos(buf, len); | 50 buf_incrwritepos(buf, len); |
44 } | 51 } |
45 | 52 |
46 ecc_key * buf_get_ecc_key_string(buffer *buf, const struct dropbear_ecc_curve *curve) { | 53 // Copied from libtomcrypt ecc_import.c (version there is static), modified |
54 // for different mp_int pointer without LTC_SOURCE | |
55 static int ecc_is_point(ecc_key *key) | |
56 { | |
57 mp_int *prime, *b, *t1, *t2; | |
58 int err; | |
59 | |
60 prime = m_malloc(sizeof(mp_int)); | |
61 b = m_malloc(sizeof(mp_int)); | |
62 t1 = m_malloc(sizeof(mp_int)); | |
63 t2 = m_malloc(sizeof(mp_int)); | |
64 | |
65 m_mp_init_multi(prime, b, t1, t2, NULL); | |
66 | |
67 /* load prime and b */ | |
68 if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } | |
69 if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } | |
70 | |
71 /* compute y^2 */ | |
72 if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } | |
73 | |
74 /* compute x^3 */ | |
75 if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } | |
76 if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } | |
77 if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } | |
78 | |
79 /* compute y^2 - x^3 */ | |
80 if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } | |
81 | |
82 /* compute y^2 - x^3 + 3x */ | |
83 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
84 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
85 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
86 if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
87 while (mp_cmp_d(t1, 0) == LTC_MP_LT) { | |
88 if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
89 } | |
90 while (mp_cmp(t1, prime) != LTC_MP_LT) { | |
91 if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
92 } | |
93 | |
94 /* compare to b */ | |
95 if (mp_cmp(t1, b) != LTC_MP_EQ) { | |
96 err = CRYPT_INVALID_PACKET; | |
97 } else { | |
98 err = CRYPT_OK; | |
99 } | |
100 | |
101 error: | |
102 mp_clear_multi(prime, b, t1, t2, NULL); | |
103 m_free(prime); | |
104 m_free(b); | |
105 m_free(t1); | |
106 m_free(t2); | |
107 return err; | |
108 } | |
109 | |
110 ecc_key * buf_get_ecc_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve) { | |
47 ecc_key *key = NULL; | 111 ecc_key *key = NULL; |
48 int ret = DROPBEAR_FAILURE; | 112 int ret = DROPBEAR_FAILURE; |
49 const int size = curve->dp->size; | 113 const int size = curve->dp->size; |
50 unsigned int len = buf_get_string(buf); | 114 buf_setpos(buf, 0); |
51 unsigned char first = buf_get_char(buf); | 115 unsigned int len = buf->len; |
116 unsigned char first = buf_getbyte(buf); | |
52 if (first == 2 || first == 3) { | 117 if (first == 2 || first == 3) { |
53 dropbear_log("Dropbear doesn't support ECC point compression"); | 118 dropbear_log(LOG_WARNING, "Dropbear doesn't support ECC point compression"); |
54 return NULL; | 119 return NULL; |
55 } | 120 } |
56 if (first != 4 || len != 1+2*size) { | 121 if (first != 4 || len != 1+2*size) { |
57 return NULL; | 122 return NULL; |
58 } | 123 } |
59 | 124 |
60 key = m_malloc(sizeof(*key)); | 125 key = new_ecc_key(); |
61 m_mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL); | 126 |
62 | 127 if (mp_read_unsigned_bin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) { |
63 if (mp_read_unsigned_bin(&key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) { | |
64 goto out; | 128 goto out; |
65 } | 129 } |
66 buf_incrpos(buf, size); | 130 buf_incrpos(buf, size); |
67 | 131 |
68 if (mp_read_unsigned_bin(&key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) { | 132 if (mp_read_unsigned_bin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) { |
69 goto out; | 133 goto out; |
70 } | 134 } |
71 buf_incrpos(buf, size); | 135 buf_incrpos(buf, size); |
72 | 136 |
73 if (mp_set(key->pubkey.z, 1) != MP_OKAY) { | 137 mp_set(key->pubkey.z, 1); |
74 goto out; | 138 |
75 } | 139 if (ecc_is_point(key) != CRYPT_OK) { |
76 | |
77 if (is_point(key) != CRYPT_OK) { | |
78 goto out; | 140 goto out; |
79 } | 141 } |
80 | 142 |
81 // SEC1 3.2.3.1 Check that Q != 0 | 143 // SEC1 3.2.3.1 Check that Q != 0 |
82 if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) { | 144 if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) { |
89 ret = DROPBEAR_SUCCESS; | 151 ret = DROPBEAR_SUCCESS; |
90 | 152 |
91 out: | 153 out: |
92 if (ret == DROPBEAR_FAILURE) { | 154 if (ret == DROPBEAR_FAILURE) { |
93 if (key) { | 155 if (key) { |
94 mp_free_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL); | 156 ecc_free(key); |
95 m_free(key); | 157 m_free(key); |
96 key = NULL; | 158 key = NULL; |
97 } | 159 } |
98 } | 160 } |
99 | 161 |
103 | 165 |
104 // a modified version of libtomcrypt's "ecc_shared_secret" to output | 166 // a modified version of libtomcrypt's "ecc_shared_secret" to output |
105 // a mp_int instead. | 167 // a mp_int instead. |
106 mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key) | 168 mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key) |
107 { | 169 { |
108 ecc_point *result = NULL | 170 ecc_point *result = NULL; |
109 mp_int *prime = NULL, *shared_secret = NULL; | 171 mp_int *prime = NULL, *shared_secret = NULL; |
110 int ret = DROPBEAR_FAILURE; | 172 int err = DROPBEAR_FAILURE; |
111 | 173 |
112 /* type valid? */ | 174 /* type valid? */ |
113 if (private_key->type != PK_PRIVATE) { | 175 if (private_key->type != PK_PRIVATE) { |
114 goto done; | 176 goto done; |
115 } | 177 } |
161 if (err == DROPBEAR_FAILURE) { | 223 if (err == DROPBEAR_FAILURE) { |
162 dropbear_exit("ECC error"); | 224 dropbear_exit("ECC error"); |
163 } | 225 } |
164 | 226 |
165 return shared_secret; | 227 return shared_secret; |
166 return err; | 228 } |
167 } | 229 |
168 | 230 #endif |
169 } | |
170 | |
171 #endif |