comparison src/pk/ecc/ecc.c @ 191:1c15b283127b libtomcrypt-orig

Import of libtomcrypt 1.02 with manual path rename rearrangement etc
author Matt Johnston <matt@ucc.asn.au>
date Fri, 06 May 2005 13:23:02 +0000
parents
children 39d5d58461d6
comparison
equal deleted inserted replaced
143:5d99163f7e32 191:1c15b283127b
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11
12 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
13 *
14 * All curves taken from NIST recommendation paper of July 1999
15 * Available at http://csrc.nist.gov/cryptval/dss.htm
16 */
17 #include "tomcrypt.h"
18
19 /**
20 @file ecc.c
21 ECC Crypto, Tom St Denis
22 */
23
24 #ifdef MECC
25
26 /* size of our temp buffers for exported keys */
27 #define ECC_BUF_SIZE 160
28
29 /* max private key size */
30 #define ECC_MAXSIZE 66
31
32 /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
33 static const struct {
34 int size;
35 char *name, *prime, *B, *order, *Gx, *Gy;
36 } sets[] = {
37 #ifdef ECC160
38 {
39 20,
40 "ECC-160",
41 /* prime */
42 "G00000000000000000000000007",
43 /* B */
44 "1oUV2vOaSlWbxr6",
45 /* order */
46 "G0000000000004sCQUtDxaqDUN5",
47 /* Gx */
48 "jpqOf1BHus6Yd/pyhyVpP",
49 /* Gy */
50 "D/wykuuIFfr+vPyx7kQEPu8MixO",
51 },
52 #endif
53 #ifdef ECC192
54 {
55 24,
56 "ECC-192",
57 /* prime */
58 "/////////////////////l//////////",
59
60 /* B */
61 "P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
62
63 /* order */
64 "////////////////cTxuDXHhoR6qqYWn",
65
66 /* Gx */
67 "68se3h0maFPylo3hGw680FJ/2ls2/n0I",
68
69 /* Gy */
70 "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
71 },
72 #endif
73 #ifdef ECC224
74 {
75 28,
76 "ECC-224",
77
78 /* prime */
79 "400000000000000000000000000000000000BV",
80
81 /* B */
82 "21HkWGL2CxJIp",
83
84 /* order */
85 "4000000000000000000Kxnixk9t8MLzMiV264/",
86
87 /* Gx */
88 "jpqOf1BHus6Yd/pyhyVpP",
89
90 /* Gy */
91 "3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck",
92 },
93 #endif
94 #ifdef ECC256
95 {
96 32,
97 "ECC-256",
98 /* Prime */
99 "F////y000010000000000000000////////////////",
100
101 /* B */
102 "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
103
104 /* Order */
105 "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
106
107 /* Gx */
108 "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
109
110 /* Gy */
111 "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
112 },
113 #endif
114 #ifdef ECC384
115 {
116 48,
117 "ECC-384",
118 /* prime */
119 "//////////////////////////////////////////x/////00000000003/"
120 "////",
121
122 /* B */
123 "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
124 "x2hl",
125
126 /* Order */
127 "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
128 "nIbp",
129
130 /* Gx and Gy */
131 "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
132 "TWgt",
133
134 "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
135 "wWvV"
136 },
137 #endif
138 #ifdef ECC521
139 {
140 65,
141 "ECC-521",
142 /* prime */
143 "V///////////////////////////////////////////////////////////"
144 "///////////////////////////",
145
146 /* B */
147 "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
148 "JknlmSrSz+8FImqyUz57zHhK3y0",
149
150 /* Order */
151 "V//////////////////////////////////////////+b66XuE/BvPhVym1I"
152 "FS9fT0xjScuYPn7hhjljnwHE6G9",
153
154 /* Gx and Gy */
155 "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
156 "wB/gDupIBF1XMf2c/b+VZ72vRrc",
157
158 "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
159 "J+j1s4rF726edB2G8Y+b7QVqMPG",
160 },
161 #endif
162 {
163 0,
164 NULL, NULL, NULL, NULL, NULL, NULL
165 }
166 };
167
168 #if 0
169
170 /* you plug in a prime and B value and it finds a pseudo-random base point */
171 void ecc_find_base(void)
172 {
173 static char *prime = "26959946667150639794667015087019630673637144422540572481103610249951";
174 static char *order = "26959946667150639794667015087019637467111563745054605861463538557247";
175 static char *b = "9538957348957353489587";
176 mp_int pp, p, r, B, tmp1, tmp2, tx, ty, x, y;
177 char buf[4096];
178 int i;
179
180 mp_init_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
181 mp_read_radix(&p, prime, 10);
182 mp_read_radix(&r, order, 10);
183 mp_read_radix(&B, b, 10);
184
185 /* get (p+1)/4 */
186 mp_add_d(&p, 1, &pp);
187 mp_div_2(&pp, &pp);
188 mp_div_2(&pp, &pp);
189
190 buf[0] = 0;
191 do {
192 printf("."); fflush(stdout);
193 /* make a random value of x */
194 for (i = 0; i < 16; i++) buf[i+1] = rand() & 255;
195 mp_read_raw(&x, buf, 17);
196 mp_copy(&x, &tx);
197
198 /* now compute x^3 - 3x + b */
199 mp_expt_d(&x, 3, &tmp1);
200 mp_mul_d(&x, 3, &tmp2);
201 mp_sub(&tmp1, &tmp2, &tmp1);
202 mp_add(&tmp1, &B, &tmp1);
203 mp_mod(&tmp1, &p, &tmp1);
204
205 /* now compute sqrt via x^((p+1)/4) */
206 mp_exptmod(&tmp1, &pp, &p, &tmp2);
207 mp_copy(&tmp2, &ty);
208
209 /* now square it */
210 mp_sqrmod(&tmp2, &p, &tmp2);
211
212 /* tmp2 should equal tmp1 */
213 } while (mp_cmp(&tmp1, &tmp2));
214
215 /* now output values in way that libtomcrypt wants */
216 mp_todecimal(&p, buf);
217 printf("\n\np==%s\n", buf);
218 mp_tohex(&B, buf);
219 printf("b==%s\n", buf);
220 mp_todecimal(&r, buf);
221 printf("r==%s\n", buf);
222 mp_tohex(&tx, buf);
223 printf("Gx==%s\n", buf);
224 mp_tohex(&ty, buf);
225 printf("Gy==%s\n", buf);
226
227 mp_clear_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
228 }
229
230 #endif
231
232 static int is_valid_idx(int n)
233 {
234 int x;
235
236 for (x = 0; sets[x].size != 0; x++);
237 if ((n < 0) || (n >= x)) {
238 return 0;
239 }
240 return 1;
241 }
242
243 static ecc_point *new_point(void)
244 {
245 ecc_point *p;
246 p = XMALLOC(sizeof(ecc_point));
247 if (p == NULL) {
248 return NULL;
249 }
250 if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != MP_OKAY) {
251 XFREE(p);
252 return NULL;
253 }
254 return p;
255 }
256
257 static void del_point(ecc_point *p)
258 {
259 /* prevents free'ing null arguments */
260 if (p != NULL) {
261 mp_clear_multi(&p->x, &p->y, &p->z, NULL);
262 XFREE(p);
263 }
264 }
265
266 static int ecc_map(ecc_point *P, mp_int *modulus, mp_int *mu)
267 {
268 mp_int t1, t2;
269 int err;
270
271 if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
272 return CRYPT_MEM;
273 }
274
275 /* get 1/z */
276 if ((err = mp_invmod(&P->z, modulus, &t1)) != MP_OKAY) { goto error; }
277
278 /* get 1/z^2 and 1/z^3 */
279 if ((err = mp_sqr(&t1, &t2)) != MP_OKAY) { goto error; }
280 if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; }
281 if ((err = mp_mul(&t1, &t2, &t1)) != MP_OKAY) { goto error; }
282 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
283
284 /* multiply against x/y */
285 if ((err = mp_mul(&P->x, &t2, &P->x)) != MP_OKAY) { goto error; }
286 if ((err = mp_reduce(&P->x, modulus, mu)) != MP_OKAY) { goto error; }
287 if ((err = mp_mul(&P->y, &t1, &P->y)) != MP_OKAY) { goto error; }
288 if ((err = mp_reduce(&P->y, modulus, mu)) != MP_OKAY) { goto error; }
289 mp_set(&P->z, 1);
290
291 err = CRYPT_OK;
292 goto done;
293 error:
294 err = mpi_to_ltc_error(err);
295 done:
296 mp_clear_multi(&t1, &t2, NULL);
297 return err;
298
299 }
300
301
302 /* double a point R = 2P, R can be P*/
303 static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu)
304 {
305 mp_int t1, t2;
306 int err;
307
308 if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {
309 return mpi_to_ltc_error(err);
310 }
311
312 if ((err = mp_copy(&P->x, &R->x)) != MP_OKAY) { goto error; }
313 if ((err = mp_copy(&P->y, &R->y)) != MP_OKAY) { goto error; }
314 if ((err = mp_copy(&P->z, &R->z)) != MP_OKAY) { goto error; }
315
316 /* t1 = Z * Z */
317 if ((err = mp_sqr(&R->z, &t1)) != MP_OKAY) { goto error; }
318 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
319 /* Z = Y * Z */
320 if ((err = mp_mul(&R->z, &R->y, &R->z)) != MP_OKAY) { goto error; }
321 if ((err = mp_reduce(&R->z, modulus, mu)) != MP_OKAY) { goto error; }
322 /* Z = 2Z */
323 if ((err = mp_mul_2(&R->z, &R->z)) != MP_OKAY) { goto error; }
324 if (mp_cmp(&R->z, modulus) != MP_LT) {
325 if ((err = mp_sub(&R->z, modulus, &R->z)) != MP_OKAY) { goto error; }
326 }
327
328 /* T2 = X - T1 */
329 if ((err = mp_sub(&R->x, &t1, &t2)) != MP_OKAY) { goto error; }
330 if (mp_cmp_d(&t2, 0) == MP_LT) {
331 if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
332 }
333 /* T1 = X + T1 */
334 if ((err = mp_add(&t1, &R->x, &t1)) != MP_OKAY) { goto error; }
335 if (mp_cmp(&t1, modulus) != MP_LT) {
336 if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
337 }
338 /* T2 = T1 * T2 */
339 if ((err = mp_mul(&t1, &t2, &t2)) != MP_OKAY) { goto error; }
340 if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; }
341 /* T1 = 2T2 */
342 if ((err = mp_mul_2(&t2, &t1)) != MP_OKAY) { goto error; }
343 if (mp_cmp(&t1, modulus) != MP_LT) {
344 if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
345 }
346 /* T1 = T1 + T2 */
347 if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { goto error; }
348 if (mp_cmp(&t1, modulus) != MP_LT) {
349 if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
350 }
351
352 /* Y = 2Y */
353 if ((err = mp_mul_2(&R->y, &R->y)) != MP_OKAY) { goto error; }
354 if (mp_cmp(&R->y, modulus) != MP_LT) {
355 if ((err = mp_sub(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
356 }
357 /* Y = Y * Y */
358 if ((err = mp_sqr(&R->y, &R->y)) != MP_OKAY) { goto error; }
359 if ((err = mp_reduce(&R->y, modulus, mu)) != MP_OKAY) { goto error; }
360 /* T2 = Y * Y */
361 if ((err = mp_sqr(&R->y, &t2)) != MP_OKAY) { goto error; }
362 if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; }
363 /* T2 = T2/2 */
364 if (mp_isodd(&t2)) {
365 if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
366 }
367 if ((err = mp_div_2(&t2, &t2)) != MP_OKAY) { goto error; }
368 /* Y = Y * X */
369 if ((err = mp_mul(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; }
370 if ((err = mp_reduce(&R->y, modulus, mu)) != MP_OKAY) { goto error; }
371
372 /* X = T1 * T1 */
373 if ((err = mp_sqr(&t1, &R->x)) != MP_OKAY) { goto error; }
374 if ((err = mp_reduce(&R->x, modulus, mu)) != MP_OKAY) { goto error; }
375 /* X = X - Y */
376 if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; }
377 if (mp_cmp_d(&R->x, 0) == MP_LT) {
378 if ((err = mp_add(&R->x, modulus, &R->x)) != MP_OKAY) { goto error; }
379 }
380 /* X = X - Y */
381 if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; }
382 if (mp_cmp_d(&R->x, 0) == MP_LT) {
383 if ((err = mp_add(&R->x, modulus, &R->x)) != MP_OKAY) { goto error; }
384 }
385
386 /* Y = Y - X */
387 if ((err = mp_sub(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; }
388 if (mp_cmp_d(&R->y, 0) == MP_LT) {
389 if ((err = mp_add(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
390 }
391 /* Y = Y * T1 */
392 if ((err = mp_mul(&R->y, &t1, &R->y)) != MP_OKAY) { goto error; }
393 if ((err = mp_reduce(&R->y, modulus, mu)) != MP_OKAY) { goto error; }
394 /* Y = Y - T2 */
395 if ((err = mp_sub(&R->y, &t2, &R->y)) != MP_OKAY) { goto error; }
396 if (mp_cmp_d(&R->y, 0) == MP_LT) {
397 if ((err = mp_add(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
398 }
399
400 err = CRYPT_OK;
401 goto done;
402 error:
403 err = mpi_to_ltc_error(err);
404 done:
405 mp_clear_multi(&t1, &t2, NULL);
406 return err;
407 }
408
409 /* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */
410 static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_int *mu)
411 {
412 mp_int t1, t2, x, y, z;
413 int err;
414
415 if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
416 return mpi_to_ltc_error(err);
417 }
418
419 if ((err = mp_copy(&P->x, &x)) != MP_OKAY) { goto error; }
420 if ((err = mp_copy(&P->y, &y)) != MP_OKAY) { goto error; }
421 if ((err = mp_copy(&P->z, &z)) != MP_OKAY) { goto error; }
422
423 /* if Z' != 1 */
424 if (mp_cmp_d(&Q->z, 1) != MP_EQ) {
425 /* T1 = Z' * Z' */
426 if ((err = mp_sqr(&Q->z, &t1)) != MP_OKAY) { goto error; }
427 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
428 /* X = X * T1 */
429 if ((err = mp_mul(&t1, &x, &x)) != MP_OKAY) { goto error; }
430 if ((err = mp_reduce(&x, modulus, mu)) != MP_OKAY) { goto error; }
431 /* T1 = Z' * T1 */
432 if ((err = mp_mul(&Q->z, &t1, &t1)) != MP_OKAY) { goto error; }
433 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
434 /* Y = Y * T1 */
435 if ((err = mp_mul(&t1, &y, &y)) != MP_OKAY) { goto error; }
436 if ((err = mp_reduce(&y, modulus, mu)) != MP_OKAY) { goto error; }
437 }
438
439 /* T1 = Z*Z */
440 if ((err = mp_sqr(&z, &t1)) != MP_OKAY) { goto error; }
441 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
442 /* T2 = X' * T1 */
443 if ((err = mp_mul(&Q->x, &t1, &t2)) != MP_OKAY) { goto error; }
444 if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; }
445 /* T1 = Z * T1 */
446 if ((err = mp_mul(&z, &t1, &t1)) != MP_OKAY) { goto error; }
447 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
448 /* T1 = Y' * T1 */
449 if ((err = mp_mul(&Q->y, &t1, &t1)) != MP_OKAY) { goto error; }
450 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
451
452 /* Y = Y - T1 */
453 if ((err = mp_sub(&y, &t1, &y)) != MP_OKAY) { goto error; }
454 if (mp_cmp_d(&y, 0) == MP_LT) {
455 if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
456 }
457 /* T1 = 2T1 */
458 if ((err = mp_mul_2(&t1, &t1)) != MP_OKAY) { goto error; }
459 if (mp_cmp(&t1, modulus) != MP_LT) {
460 if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
461 }
462 /* T1 = Y + T1 */
463 if ((err = mp_add(&t1, &y, &t1)) != MP_OKAY) { goto error; }
464 if (mp_cmp(&t1, modulus) != MP_LT) {
465 if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
466 }
467 /* X = X - T2 */
468 if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; }
469 if (mp_cmp_d(&x, 0) == MP_LT) {
470 if ((err = mp_add(&x, modulus, &x)) != MP_OKAY) { goto error; }
471 }
472 /* T2 = 2T2 */
473 if ((err = mp_mul_2(&t2, &t2)) != MP_OKAY) { goto error; }
474 if (mp_cmp(&t2, modulus) != MP_LT) {
475 if ((err = mp_sub(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
476 }
477 /* T2 = X + T2 */
478 if ((err = mp_add(&t2, &x, &t2)) != MP_OKAY) { goto error; }
479 if (mp_cmp(&t2, modulus) != MP_LT) {
480 if ((err = mp_sub(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
481 }
482
483 /* if Z' != 1 */
484 if (mp_cmp_d(&Q->z, 1) != MP_EQ) {
485 /* Z = Z * Z' */
486 if ((err = mp_mul(&z, &Q->z, &z)) != MP_OKAY) { goto error; }
487 if ((err = mp_reduce(&z, modulus, mu)) != MP_OKAY) { goto error; }
488 }
489 /* Z = Z * X */
490 if ((err = mp_mul(&z, &x, &z)) != MP_OKAY) { goto error; }
491 if ((err = mp_reduce(&z, modulus, mu)) != MP_OKAY) { goto error; }
492
493 /* T1 = T1 * X */
494 if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; }
495 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
496 /* X = X * X */
497 if ((err = mp_sqr(&x, &x)) != MP_OKAY) { goto error; }
498 if ((err = mp_reduce(&x, modulus, mu)) != MP_OKAY) { goto error; }
499 /* T2 = T2 * x */
500 if ((err = mp_mul(&t2, &x, &t2)) != MP_OKAY) { goto error; }
501 if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; }
502 /* T1 = T1 * X */
503 if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; }
504 if ((err = mp_reduce(&t1, modulus, mu)) != MP_OKAY) { goto error; }
505
506 /* X = Y*Y */
507 if ((err = mp_sqr(&y, &x)) != MP_OKAY) { goto error; }
508 if ((err = mp_reduce(&x, modulus, mu)) != MP_OKAY) { goto error; }
509 /* X = X - T2 */
510 if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; }
511 if (mp_cmp_d(&x, 0) == MP_LT) {
512 if ((err = mp_add(&x, modulus, &x)) != MP_OKAY) { goto error; }
513 }
514
515 /* T2 = T2 - X */
516 if ((err = mp_sub(&t2, &x, &t2)) != MP_OKAY) { goto error; }
517 if (mp_cmp_d(&t2, 0) == MP_LT) {
518 if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
519 }
520 /* T2 = T2 - X */
521 if ((err = mp_sub(&t2, &x, &t2)) != MP_OKAY) { goto error; }
522 if (mp_cmp_d(&t2, 0) == MP_LT) {
523 if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
524 }
525 /* T2 = T2 * Y */
526 if ((err = mp_mul(&t2, &y, &t2)) != MP_OKAY) { goto error; }
527 if ((err = mp_reduce(&t2, modulus, mu)) != MP_OKAY) { goto error; }
528 /* Y = T2 - T1 */
529 if ((err = mp_sub(&t2, &t1, &y)) != MP_OKAY) { goto error; }
530 if (mp_cmp_d(&y, 0) == MP_LT) {
531 if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
532 }
533 /* Y = Y/2 */
534 if (mp_isodd(&y)) {
535 if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
536 }
537 if ((err = mp_div_2(&y, &y)) != MP_OKAY) { goto error; }
538
539 if ((err = mp_copy(&x, &R->x)) != MP_OKAY) { goto error; }
540 if ((err = mp_copy(&y, &R->y)) != MP_OKAY) { goto error; }
541 if ((err = mp_copy(&z, &R->z)) != MP_OKAY) { goto error; }
542
543 err = CRYPT_OK;
544 goto done;
545 error:
546 err = mpi_to_ltc_error(err);
547 done:
548 mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
549 return err;
550 }
551
552 /* size of sliding window, don't change this! */
553 #define WINSIZE 4
554
555 /* perform R = kG where k == integer and G == ecc_point */
556 static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus)
557 {
558 ecc_point *tG, *M[8];
559 int i, j, err;
560 mp_int mu;
561 mp_digit buf;
562 int first, bitbuf, bitcpy, bitcnt, mode, digidx;
563
564 /* init barrett reduction */
565 if ((err = mp_init(&mu)) != MP_OKAY) {
566 return mpi_to_ltc_error(err);
567 }
568 if ((err = mp_reduce_setup(&mu, modulus)) != MP_OKAY) {
569 mp_clear(&mu);
570 return mpi_to_ltc_error(err);
571 }
572
573 /* alloc ram for window temps */
574 for (i = 0; i < 8; i++) {
575 M[i] = new_point();
576 if (M[i] == NULL) {
577 for (j = 0; j < i; j++) {
578 del_point(M[j]);
579 }
580 mp_clear(&mu);
581 return CRYPT_MEM;
582 }
583 }
584
585 /* make a copy of G incase R==G */
586 tG = new_point();
587 if (tG == NULL) { err = CRYPT_MEM; goto done; }
588
589 /* tG = G */
590 if ((err = mp_copy(&G->x, &tG->x)) != MP_OKAY) { goto error; }
591 if ((err = mp_copy(&G->y, &tG->y)) != MP_OKAY) { goto error; }
592 if ((err = mp_copy(&G->z, &tG->z)) != MP_OKAY) { goto error; }
593
594 /* calc the M tab, which holds kG for k==8..15 */
595 /* M[0] == 8G */
596 if ((err = dbl_point(G, M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
597 if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
598 if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
599
600 /* now find (8+k)G for k=1..7 */
601 for (j = 9; j < 16; j++) {
602 if ((err = add_point(M[j-9], G, M[j-8], modulus, &mu)) != CRYPT_OK) { goto done; }
603 }
604
605 /* setup sliding window */
606 mode = 0;
607 bitcnt = 1;
608 buf = 0;
609 digidx = k->used - 1;
610 bitcpy = bitbuf = 0;
611 first = 1;
612
613 /* perform ops */
614 for (;;) {
615 /* grab next digit as required */
616 if (--bitcnt == 0) {
617 if (digidx == -1) {
618 break;
619 }
620 buf = k->dp[digidx--];
621 bitcnt = (int) DIGIT_BIT;
622 }
623
624 /* grab the next msb from the multiplicand */
625 i = (buf >> (DIGIT_BIT - 1)) & 1;
626 buf <<= 1;
627
628 /* skip leading zero bits */
629 if (mode == 0 && i == 0) {
630 continue;
631 }
632
633 /* if the bit is zero and mode == 1 then we double */
634 if (mode == 1 && i == 0) {
635 if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
636 continue;
637 }
638
639 /* else we add it to the window */
640 bitbuf |= (i << (WINSIZE - ++bitcpy));
641 mode = 2;
642
643 if (bitcpy == WINSIZE) {
644 /* if this is the first window we do a simple copy */
645 if (first == 1) {
646 /* R = kG [k = first window] */
647 if ((err = mp_copy(&M[bitbuf-8]->x, &R->x)) != MP_OKAY) { goto error; }
648 if ((err = mp_copy(&M[bitbuf-8]->y, &R->y)) != MP_OKAY) { goto error; }
649 if ((err = mp_copy(&M[bitbuf-8]->z, &R->z)) != MP_OKAY) { goto error; }
650 first = 0;
651 } else {
652 /* normal window */
653 /* ok window is filled so double as required and add */
654 /* double first */
655 for (j = 0; j < WINSIZE; j++) {
656 if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
657 }
658
659 /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
660 if ((err = add_point(R, M[bitbuf-8], R, modulus, &mu)) != CRYPT_OK) { goto done; }
661 }
662 /* empty window and reset */
663 bitcpy = bitbuf = 0;
664 mode = 1;
665 }
666 }
667
668 /* if bits remain then double/add */
669 if (mode == 2 && bitcpy > 0) {
670 /* double then add */
671 for (j = 0; j < bitcpy; j++) {
672 /* only double if we have had at least one add first */
673 if (first == 0) {
674 if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
675 }
676
677 bitbuf <<= 1;
678 if ((bitbuf & (1 << WINSIZE)) != 0) {
679 if (first == 1){
680 /* first add, so copy */
681 if ((err = mp_copy(&tG->x, &R->x)) != MP_OKAY) { goto error; }
682 if ((err = mp_copy(&tG->y, &R->y)) != MP_OKAY) { goto error; }
683 if ((err = mp_copy(&tG->z, &R->z)) != MP_OKAY) { goto error; }
684 first = 0;
685 } else {
686 /* then add */
687 if ((err = add_point(R, tG, R, modulus, &mu)) != CRYPT_OK) { goto done; }
688 }
689 }
690 }
691 }
692
693 /* map R back from projective space */
694 err = ecc_map(R, modulus, &mu);
695 goto done;
696 error:
697 err = mpi_to_ltc_error(err);
698 done:
699 del_point(tG);
700 for (i = 0; i < 8; i++) {
701 del_point(M[i]);
702 }
703 mp_clear(&mu);
704 return err;
705 }
706
707 #undef WINSIZE
708
709 /**
710 Perform on the ECC system
711 @return CRYPT_OK if successful
712 */
713 int ecc_test(void)
714 {
715 mp_int modulus, order;
716 ecc_point *G, *GG;
717 int i, err, primality;
718
719 if ((err = mp_init_multi(&modulus, &order, NULL)) != MP_OKAY) {
720 return mpi_to_ltc_error(err);
721 }
722
723 G = new_point();
724 GG = new_point();
725 if (G == NULL || GG == NULL) {
726 mp_clear_multi(&modulus, &order, NULL);
727 del_point(G);
728 del_point(GG);
729 return CRYPT_MEM;
730 }
731
732 for (i = 0; sets[i].size; i++) {
733 #if 0
734 printf("Testing %d\n", sets[i].size);
735 #endif
736 if ((err = mp_read_radix(&modulus, (char *)sets[i].prime, 64)) != MP_OKAY) { goto error; }
737 if ((err = mp_read_radix(&order, (char *)sets[i].order, 64)) != MP_OKAY) { goto error; }
738
739 /* is prime actually prime? */
740 if ((err = is_prime(&modulus, &primality)) != CRYPT_OK) { goto done; }
741 if (primality == 0) {
742 err = CRYPT_FAIL_TESTVECTOR;
743 goto done;
744 }
745
746 /* is order prime ? */
747 if ((err = is_prime(&order, &primality)) != CRYPT_OK) { goto done; }
748 if (primality == 0) {
749 err = CRYPT_FAIL_TESTVECTOR;
750 goto done;
751 }
752
753 if ((err = mp_read_radix(&G->x, (char *)sets[i].Gx, 64)) != MP_OKAY) { goto error; }
754 if ((err = mp_read_radix(&G->y, (char *)sets[i].Gy, 64)) != MP_OKAY) { goto error; }
755 mp_set(&G->z, 1);
756
757 /* then we should have G == (order + 1)G */
758 if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY) { goto error; }
759 if ((err = ecc_mulmod(&order, G, GG, &modulus)) != CRYPT_OK) { goto done; }
760 if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) {
761 err = CRYPT_FAIL_TESTVECTOR;
762 goto done;
763 }
764 }
765 err = CRYPT_OK;
766 goto done;
767 error:
768 err = mpi_to_ltc_error(err);
769 done:
770 del_point(GG);
771 del_point(G);
772 mp_clear_multi(&order, &modulus, NULL);
773 return err;
774 }
775
776 void ecc_sizes(int *low, int *high)
777 {
778 int i;
779 LTC_ARGCHK(low != NULL);
780 LTC_ARGCHK(high != NULL);
781
782 *low = INT_MAX;
783 *high = 0;
784 for (i = 0; sets[i].size != 0; i++) {
785 if (sets[i].size < *low) {
786 *low = sets[i].size;
787 }
788 if (sets[i].size > *high) {
789 *high = sets[i].size;
790 }
791 }
792 }
793
794 /**
795 Make a new ECC key
796 @param prng An active PRNG state
797 @param wprng The index of the PRNG you wish to use
798 @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
799 @param key [out] Destination of the newly created key
800 @return CRYPT_OK if successful, upon error all allocated memory will be freed
801 */
802 int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
803 {
804 int x, err;
805 ecc_point *base;
806 mp_int prime;
807 unsigned char *buf;
808
809 LTC_ARGCHK(key != NULL);
810
811 /* good prng? */
812 if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
813 return err;
814 }
815
816 /* find key size */
817 for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
818 keysize = sets[x].size;
819
820 if (keysize > ECC_MAXSIZE || sets[x].size == 0) {
821 return CRYPT_INVALID_KEYSIZE;
822 }
823 key->idx = x;
824
825 /* allocate ram */
826 base = NULL;
827 buf = XMALLOC(ECC_MAXSIZE);
828 if (buf == NULL) {
829 return CRYPT_MEM;
830 }
831
832 /* make up random string */
833 if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
834 err = CRYPT_ERROR_READPRNG;
835 goto LBL_ERR2;
836 }
837
838 /* setup the key variables */
839 if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL)) != MP_OKAY) {
840 err = mpi_to_ltc_error(err);
841 goto LBL_ERR;
842 }
843 base = new_point();
844 if (base == NULL) {
845 mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL);
846 err = CRYPT_MEM;
847 goto LBL_ERR;
848 }
849
850 /* read in the specs for this key */
851 if ((err = mp_read_radix(&prime, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
852 if ((err = mp_read_radix(&base->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
853 if ((err = mp_read_radix(&base->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
854 mp_set(&base->z, 1);
855 if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
856
857 /* make the public key */
858 if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK) { goto LBL_ERR; }
859 key->type = PK_PRIVATE;
860
861 /* shrink key */
862 if ((err = mp_shrink(&key->k)) != MP_OKAY) { goto error; }
863 if ((err = mp_shrink(&key->pubkey.x)) != MP_OKAY) { goto error; }
864 if ((err = mp_shrink(&key->pubkey.y)) != MP_OKAY) { goto error; }
865 if ((err = mp_shrink(&key->pubkey.z)) != MP_OKAY) { goto error; }
866
867 /* free up ram */
868 err = CRYPT_OK;
869 goto LBL_ERR;
870 error:
871 err = mpi_to_ltc_error(err);
872 LBL_ERR:
873 del_point(base);
874 mp_clear(&prime);
875 LBL_ERR2:
876 #ifdef LTC_CLEAN_STACK
877 zeromem(buf, ECC_MAXSIZE);
878 #endif
879
880 XFREE(buf);
881
882 return err;
883 }
884
885 /**
886 Free an ECC key from memory
887 @param key The key you wish to free
888 */
889 void ecc_free(ecc_key *key)
890 {
891 LTC_ARGCHK(key != NULL);
892 mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
893 }
894
895 static int compress_y_point(ecc_point *pt, int idx, int *result)
896 {
897 mp_int tmp, tmp2, p;
898 int err;
899
900 LTC_ARGCHK(pt != NULL);
901 LTC_ARGCHK(result != NULL);
902
903 if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
904 return mpi_to_ltc_error(err);
905 }
906
907 /* get x^3 - 3x + b */
908 if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
909 if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY) { goto error; } /* tmp = pX^3 */
910 if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
911 if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
912 if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp + p */
913 if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY) { goto error; } /* p = prime */
914 if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
915
916 /* now find square root */
917 if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
918 if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
919 if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */
920
921 /* if tmp equals the y point give a 0, otherwise 1 */
922 if (mp_cmp(&tmp, &pt->y) == 0) {
923 *result = 0;
924 } else {
925 *result = 1;
926 }
927
928 err = CRYPT_OK;
929 goto done;
930 error:
931 err = mpi_to_ltc_error(err);
932 done:
933 mp_clear_multi(&p, &tmp, &tmp2, NULL);
934 return err;
935 }
936
937 static int expand_y_point(ecc_point *pt, int idx, int result)
938 {
939 mp_int tmp, tmp2, p;
940 int err;
941
942 LTC_ARGCHK(pt != NULL);
943
944 if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
945 return CRYPT_MEM;
946 }
947
948 /* get x^3 - 3x + b */
949 if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
950 if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY) { goto error; } /* tmp = pX^3 */
951 if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
952 if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
953 if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp + p */
954 if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY) { goto error; } /* p = prime */
955 if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
956
957 /* now find square root */
958 if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
959 if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
960 if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */
961
962 /* if result==0, then y==tmp, otherwise y==p-tmp */
963 if (result == 0) {
964 if ((err = mp_copy(&tmp, &pt->y) != MP_OKAY)) { goto error; }
965 } else {
966 if ((err = mp_sub(&p, &tmp, &pt->y) != MP_OKAY)) { goto error; }
967 }
968
969 err = CRYPT_OK;
970 goto done;
971 error:
972 err = mpi_to_ltc_error(err);
973 done:
974 mp_clear_multi(&p, &tmp, &tmp2, NULL);
975 return err;
976 }
977
978 /**
979 Export an ECC key as a binary packet
980 @param out [out] Destination for the key
981 @param outlen [in/out] Max size and resulting size of the exported key
982 @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC)
983 @param key The key to export
984 @return CRYPT_OK if successful
985 */
986 int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
987 {
988 unsigned long y, z;
989 int cp, err;
990
991 LTC_ARGCHK(out != NULL);
992 LTC_ARGCHK(outlen != NULL);
993 LTC_ARGCHK(key != NULL);
994
995 /* can we store the static header? */
996 if (*outlen < (PACKET_SIZE + 3)) {
997 return CRYPT_BUFFER_OVERFLOW;
998 }
999
1000 /* type valid? */
1001 if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
1002 return CRYPT_PK_TYPE_MISMATCH;
1003 }
1004
1005 /* output type and magic byte */
1006 y = PACKET_SIZE;
1007 out[y++] = (unsigned char)type;
1008 out[y++] = (unsigned char)sets[key->idx].size;
1009
1010 /* output x coordinate */
1011 OUTPUT_BIGNUM(&(key->pubkey.x), out, y, z);
1012
1013 /* compress y and output it */
1014 if ((err = compress_y_point(&key->pubkey, key->idx, &cp)) != CRYPT_OK) {
1015 return err;
1016 }
1017 out[y++] = (unsigned char)cp;
1018
1019 if (type == PK_PRIVATE) {
1020 OUTPUT_BIGNUM(&key->k, out, y, z);
1021 }
1022
1023 /* store header */
1024 packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_KEY);
1025 *outlen = y;
1026
1027 return CRYPT_OK;
1028 }
1029
1030 /**
1031 Import an ECC key from a binary packet
1032 @param in The packet to import
1033 @param inlen The length of the packet
1034 @param key [out] The destination of the import
1035 @return CRYPT_OK if successful, upon error all allocated memory will be freed
1036 */
1037 int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
1038 {
1039 unsigned long x, y, s;
1040 int err;
1041
1042 LTC_ARGCHK(in != NULL);
1043 LTC_ARGCHK(key != NULL);
1044
1045 /* check length */
1046 if ((3+PACKET_SIZE) > inlen) {
1047 return CRYPT_INVALID_PACKET;
1048 }
1049
1050 /* check type */
1051 if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) {
1052 return err;
1053 }
1054
1055 /* init key */
1056 if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != MP_OKAY) {
1057 return CRYPT_MEM;
1058 }
1059
1060 y = PACKET_SIZE;
1061 key->type = (int)in[y++];
1062 s = (unsigned long)in[y++];
1063
1064 for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
1065 if (sets[x].size == 0) {
1066 err = CRYPT_INVALID_KEYSIZE;
1067 goto error;
1068 }
1069 key->idx = (int)x;
1070
1071 /* type check both values */
1072 if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
1073 err = CRYPT_INVALID_PACKET;
1074 goto error;
1075 }
1076
1077 /* is the key idx valid? */
1078 if (is_valid_idx(key->idx) != 1) {
1079 err = CRYPT_INVALID_PACKET;
1080 goto error;
1081 }
1082
1083 /* load x coordinate */
1084 INPUT_BIGNUM(&key->pubkey.x, in, x, y, inlen);
1085
1086 /* load y */
1087 x = (unsigned long)in[y++];
1088 if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) {
1089 goto error;
1090 }
1091
1092 if (key->type == PK_PRIVATE) {
1093 /* load private key */
1094 INPUT_BIGNUM(&key->k, in, x, y, inlen);
1095 }
1096
1097 /* eliminate private key if public */
1098 if (key->type == PK_PUBLIC) {
1099 mp_clear(&key->k);
1100 }
1101
1102 /* z is always 1 */
1103 mp_set(&key->pubkey.z, 1);
1104
1105 return CRYPT_OK;
1106 error:
1107 mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
1108 return err;
1109 }
1110
1111 /**
1112 Create an ECC shared secret between two keys
1113 @param private_key The private ECC key
1114 @param public_key The public key
1115 @param out [out] Destination of the shared secret
1116 @param outlen [in/out] The max size and resulting size of the shared secret
1117 @return CRYPT_OK if successful
1118 */
1119 int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
1120 unsigned char *out, unsigned long *outlen)
1121 {
1122 unsigned long x, y;
1123 ecc_point *result;
1124 mp_int prime;
1125 int err;
1126
1127 LTC_ARGCHK(private_key != NULL);
1128 LTC_ARGCHK(public_key != NULL);
1129 LTC_ARGCHK(out != NULL);
1130 LTC_ARGCHK(outlen != NULL);
1131
1132 /* type valid? */
1133 if (private_key->type != PK_PRIVATE) {
1134 return CRYPT_PK_NOT_PRIVATE;
1135 }
1136
1137 if (private_key->idx != public_key->idx) {
1138 return CRYPT_PK_TYPE_MISMATCH;
1139 }
1140
1141 /* make new point */
1142 result = new_point();
1143 if (result == NULL) {
1144 return CRYPT_MEM;
1145 }
1146
1147 if ((err = mp_init(&prime)) != MP_OKAY) {
1148 del_point(result);
1149 return mpi_to_ltc_error(err);
1150 }
1151
1152 if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
1153 if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { goto done1; }
1154
1155 x = (unsigned long)mp_unsigned_bin_size(&result->x);
1156 y = (unsigned long)mp_unsigned_bin_size(&result->y);
1157
1158 if (*outlen < (x+y)) {
1159 err = CRYPT_BUFFER_OVERFLOW;
1160 goto done1;
1161 }
1162 *outlen = x+y;
1163 if ((err = mp_to_unsigned_bin(&result->x, out)) != MP_OKAY) { goto error; }
1164 if ((err = mp_to_unsigned_bin(&result->y, out+x)) != MP_OKAY) { goto error; }
1165
1166 err = CRYPT_OK;
1167 goto done1;
1168 error:
1169 err = mpi_to_ltc_error(err);
1170 done1:
1171 mp_clear(&prime);
1172 del_point(result);
1173 return err;
1174 }
1175
1176 /**
1177 Get the size of an ECC key
1178 @param key The key to get the size of
1179 @return The size (octets) of the key or INT_MAX on error
1180 */
1181 int ecc_get_size(ecc_key *key)
1182 {
1183 LTC_ARGCHK(key != NULL);
1184 if (is_valid_idx(key->idx))
1185 return sets[key->idx].size;
1186 else
1187 return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
1188 }
1189
1190 #include "ecc_sys.c"
1191
1192 #endif
1193
1194