Mercurial > dropbear
comparison ecc.c @ 910:89555751c489 asm
merge up to 2013.63, improve ASM makefile rules a bit
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 27 Feb 2014 21:35:58 +0800 |
parents | 30ab30e46452 |
children | 063c38ea622b |
comparison
equal
deleted
inserted
replaced
909:e4b75744acab | 910:89555751c489 |
---|---|
1 #include "includes.h" | |
2 #include "options.h" | |
3 #include "ecc.h" | |
4 #include "dbutil.h" | |
5 #include "bignum.h" | |
6 | |
7 #ifdef DROPBEAR_ECC | |
8 | |
9 /* .dp members are filled out by dropbear_ecc_fill_dp() at startup */ | |
10 #ifdef DROPBEAR_ECC_256 | |
11 struct dropbear_ecc_curve ecc_curve_nistp256 = { | |
12 32, /* .ltc_size */ | |
13 NULL, /* .dp */ | |
14 &sha256_desc, /* .hash_desc */ | |
15 "nistp256" /* .name */ | |
16 }; | |
17 #endif | |
18 #ifdef DROPBEAR_ECC_384 | |
19 struct dropbear_ecc_curve ecc_curve_nistp384 = { | |
20 48, /* .ltc_size */ | |
21 NULL, /* .dp */ | |
22 &sha384_desc, /* .hash_desc */ | |
23 "nistp384" /* .name */ | |
24 }; | |
25 #endif | |
26 #ifdef DROPBEAR_ECC_521 | |
27 struct dropbear_ecc_curve ecc_curve_nistp521 = { | |
28 66, /* .ltc_size */ | |
29 NULL, /* .dp */ | |
30 &sha512_desc, /* .hash_desc */ | |
31 "nistp521" /* .name */ | |
32 }; | |
33 #endif | |
34 | |
35 struct dropbear_ecc_curve *dropbear_ecc_curves[] = { | |
36 #ifdef DROPBEAR_ECC_256 | |
37 &ecc_curve_nistp256, | |
38 #endif | |
39 #ifdef DROPBEAR_ECC_384 | |
40 &ecc_curve_nistp384, | |
41 #endif | |
42 #ifdef DROPBEAR_ECC_521 | |
43 &ecc_curve_nistp521, | |
44 #endif | |
45 NULL | |
46 }; | |
47 | |
48 void dropbear_ecc_fill_dp() { | |
49 struct dropbear_ecc_curve **curve; | |
50 /* libtomcrypt guarantees they're ordered by size */ | |
51 const ltc_ecc_set_type *dp = ltc_ecc_sets; | |
52 for (curve = dropbear_ecc_curves; *curve; curve++) { | |
53 for (;dp->size > 0; dp++) { | |
54 if (dp->size == (*curve)->ltc_size) { | |
55 (*curve)->dp = dp; | |
56 break; | |
57 } | |
58 } | |
59 if (!(*curve)->dp) { | |
60 dropbear_exit("Missing ECC params %s", (*curve)->name); | |
61 } | |
62 } | |
63 } | |
64 | |
65 struct dropbear_ecc_curve* curve_for_dp(const ltc_ecc_set_type *dp) { | |
66 struct dropbear_ecc_curve **curve = NULL; | |
67 for (curve = dropbear_ecc_curves; *curve; curve++) { | |
68 if ((*curve)->dp == dp) { | |
69 break; | |
70 } | |
71 } | |
72 assert(*curve); | |
73 return *curve; | |
74 } | |
75 | |
76 ecc_key * new_ecc_key(void) { | |
77 ecc_key *key = m_malloc(sizeof(*key)); | |
78 m_mp_alloc_init_multi((mp_int**)&key->pubkey.x, (mp_int**)&key->pubkey.y, | |
79 (mp_int**)&key->pubkey.z, (mp_int**)&key->k, NULL); | |
80 return key; | |
81 } | |
82 | |
83 /* Copied from libtomcrypt ecc_import.c (version there is static), modified | |
84 for different mp_int pointer without LTC_SOURCE */ | |
85 static int ecc_is_point(ecc_key *key) | |
86 { | |
87 mp_int *prime, *b, *t1, *t2; | |
88 int err; | |
89 | |
90 prime = m_malloc(sizeof(mp_int)); | |
91 b = m_malloc(sizeof(mp_int)); | |
92 t1 = m_malloc(sizeof(mp_int)); | |
93 t2 = m_malloc(sizeof(mp_int)); | |
94 | |
95 m_mp_alloc_init_multi(&prime, &b, &t1, &t2, NULL); | |
96 | |
97 /* load prime and b */ | |
98 if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } | |
99 if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } | |
100 | |
101 /* compute y^2 */ | |
102 if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } | |
103 | |
104 /* compute x^3 */ | |
105 if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } | |
106 if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } | |
107 if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } | |
108 | |
109 /* compute y^2 - x^3 */ | |
110 if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } | |
111 | |
112 /* compute y^2 - x^3 + 3x */ | |
113 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
114 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
115 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
116 if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
117 while (mp_cmp_d(t1, 0) == LTC_MP_LT) { | |
118 if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
119 } | |
120 while (mp_cmp(t1, prime) != LTC_MP_LT) { | |
121 if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
122 } | |
123 | |
124 /* compare to b */ | |
125 if (mp_cmp(t1, b) != LTC_MP_EQ) { | |
126 err = CRYPT_INVALID_PACKET; | |
127 } else { | |
128 err = CRYPT_OK; | |
129 } | |
130 | |
131 error: | |
132 mp_clear_multi(prime, b, t1, t2, NULL); | |
133 m_free(prime); | |
134 m_free(b); | |
135 m_free(t1); | |
136 m_free(t2); | |
137 return err; | |
138 } | |
139 | |
140 /* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */ | |
141 void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key) { | |
142 unsigned long len = key->dp->size*2 + 1; | |
143 int err; | |
144 buf_putint(buf, len); | |
145 err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len); | |
146 if (err != CRYPT_OK) { | |
147 dropbear_exit("ECC error"); | |
148 } | |
149 buf_incrwritepos(buf, len); | |
150 } | |
151 | |
152 /* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */ | |
153 ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve) { | |
154 ecc_key *key = NULL; | |
155 int ret = DROPBEAR_FAILURE; | |
156 const unsigned int size = curve->dp->size; | |
157 unsigned char first; | |
158 | |
159 TRACE(("enter buf_get_ecc_raw_pubkey")) | |
160 | |
161 buf_setpos(buf, 0); | |
162 first = buf_getbyte(buf); | |
163 if (first == 2 || first == 3) { | |
164 dropbear_log(LOG_WARNING, "Dropbear doesn't support ECC point compression"); | |
165 return NULL; | |
166 } | |
167 if (first != 4 || buf->len != 1+2*size) { | |
168 TRACE(("leave, wrong size")) | |
169 return NULL; | |
170 } | |
171 | |
172 key = new_ecc_key(); | |
173 key->dp = curve->dp; | |
174 | |
175 if (mp_read_unsigned_bin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) { | |
176 TRACE(("failed to read x")) | |
177 goto out; | |
178 } | |
179 buf_incrpos(buf, size); | |
180 | |
181 if (mp_read_unsigned_bin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) { | |
182 TRACE(("failed to read y")) | |
183 goto out; | |
184 } | |
185 buf_incrpos(buf, size); | |
186 | |
187 mp_set(key->pubkey.z, 1); | |
188 | |
189 if (ecc_is_point(key) != CRYPT_OK) { | |
190 TRACE(("failed, not a point")) | |
191 goto out; | |
192 } | |
193 | |
194 /* SEC1 3.2.3.1 Check that Q != 0 */ | |
195 if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) { | |
196 TRACE(("failed, x == 0")) | |
197 goto out; | |
198 } | |
199 if (mp_cmp_d(key->pubkey.y, 0) == LTC_MP_EQ) { | |
200 TRACE(("failed, y == 0")) | |
201 goto out; | |
202 } | |
203 | |
204 ret = DROPBEAR_SUCCESS; | |
205 | |
206 out: | |
207 if (ret == DROPBEAR_FAILURE) { | |
208 if (key) { | |
209 ecc_free(key); | |
210 m_free(key); | |
211 key = NULL; | |
212 } | |
213 } | |
214 | |
215 return key; | |
216 | |
217 } | |
218 | |
219 /* a modified version of libtomcrypt's "ecc_shared_secret" to output | |
220 a mp_int instead. */ | |
221 mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key) | |
222 { | |
223 ecc_point *result = NULL; | |
224 mp_int *prime = NULL, *shared_secret = NULL; | |
225 int err = DROPBEAR_FAILURE; | |
226 | |
227 /* type valid? */ | |
228 if (private_key->type != PK_PRIVATE) { | |
229 goto done; | |
230 } | |
231 | |
232 if (private_key->dp != public_key->dp) { | |
233 goto done; | |
234 } | |
235 | |
236 /* make new point */ | |
237 result = ltc_ecc_new_point(); | |
238 if (result == NULL) { | |
239 goto done; | |
240 } | |
241 | |
242 prime = m_malloc(sizeof(*prime)); | |
243 m_mp_init(prime); | |
244 | |
245 if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) { | |
246 goto done; | |
247 } | |
248 if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) { | |
249 goto done; | |
250 } | |
251 | |
252 err = DROPBEAR_SUCCESS; | |
253 done: | |
254 if (err == DROPBEAR_SUCCESS) { | |
255 shared_secret = m_malloc(sizeof(*shared_secret)); | |
256 m_mp_init(shared_secret); | |
257 mp_copy(result->x, shared_secret); | |
258 } | |
259 | |
260 if (prime) { | |
261 mp_clear(prime); | |
262 m_free(prime); | |
263 } | |
264 if (result) | |
265 { | |
266 ltc_ecc_del_point(result); | |
267 } | |
268 | |
269 if (err == DROPBEAR_FAILURE) { | |
270 dropbear_exit("ECC error"); | |
271 } | |
272 return shared_secret; | |
273 } | |
274 | |
275 #endif |