]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/main-ecdsa-test.c
fixing E-Mail-Address & Copyright
[avr-crypto-lib.git] / test_src / main-ecdsa-test.c
1 /* main-dsa-test.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20  * ECDSA test-suit
21  *
22 */
23
24 #include <ctype.h>
25
26 #include "main-test-common.h"
27
28 #include "noekeon.h"
29 #include "noekeon_prng.h"
30 #include "bigint.h"
31 #include "bigint_io.h"
32 #include "nist_p192.h"
33 #include "ecc.h"
34 #include "ecdsa_sign.h"
35
36 #include "hfal_sha1.h"
37 #include "hfal_sha224.h"
38 #include "hfal_sha256.h"
39 #include "hfal_sha384.h"
40 #include "hfal_sha512.h"
41 #include "hfal-basic.h"
42
43 #include "performance_test.h"
44 #include "hfal_sha1.h"
45 #include "base64_enc.h"
46 #include "base64_dec.h"
47
48 char *algo_name = "ECDSA";
49
50 /*****************************************************************************
51  *  additional validation-functions                                                                                      *
52  *****************************************************************************/
53
54 uint8_t prng_get_byte(void){
55     return random8();
56 }
57
58 const hfdesc_t *hash_select(void){
59     const hfdesc_t *hashes[] = { &sha1_desc, &sha224_desc, &sha256_desc, &sha384_desc, &sha512_desc };
60     uint8_t index;
61     int selection;
62     printf_P(PSTR("Please select one of the following hash functions:\n"));
63     for(index = 0; index < sizeof(hashes) / sizeof(hashes[0]); ++index){
64         printf_P(PSTR("  %c: %S\n"), index + 'a', pgm_read_word(&(hashes[index]->name)));
65     }
66     do{
67         printf_P(PSTR("[a]: "));
68         selection = getchar();
69         putchar(selection);
70         if(selection == '\n' || selection == '\r'){
71             selection = 0;
72         }else{
73             putchar('\n');
74             selection -= 'a';
75         }
76     }while(selection > sizeof(hashes) / sizeof(hashes[0]));
77     return hashes[selection];
78 }
79
80 uint8_t convert_hexchar_to_value(char a){
81     if(a >= 0 && a <= 9){
82         return a - '0';
83     }
84     if(a >= 'a' && a <= 'f'){
85         return a - 'a';
86     }
87     if(a >= 'A' && a <= 'F'){
88         return a - 'A';
89     }
90     return 0;
91 }
92
93
94 uint8_t convert_hex_to_byte(char a, char b){
95     return (convert_hexchar_to_value(a) << 4) | convert_hexchar_to_value(b);
96 }
97
98 void *hash_message(hfdesc_t *hash_function){
99     uint8_t *block, *hash_value;
100     uint16_t index = 0;
101     hfgen_ctx_t ctx;
102     if(hash_function == NULL){
103         return NULL;
104     }
105     block = malloc(hfal_hash_getBlocksize(hash_function) / 8);
106     if(block == NULL){
107         return NULL;
108     }
109     hash_value = malloc(hfal_hash_getHashsize(hash_function) / 8);
110     if(hash_value == NULL){
111         free(block);
112         return NULL;
113     }
114     hfal_hash_init(hash_function, &ctx);
115     for(;;){
116         int a,b;
117         a = getchar();
118         if(!isxdigit(a)){
119             hfal_hash_lastBlock(&ctx, block, index * 8);
120             break;
121         }
122         putchar(a);
123         b = getchar();
124         if(!isxdigit(b)){
125             printf_P(PSTR("*** invalid ***\n"));
126             hfal_hash_free(&ctx);
127             free(hash_value);
128             free(block);
129             return NULL;
130         }
131         putchar(b);
132         block[index++] = convert_hex_to_byte(a, b);
133         if(index == hfal_hash_getBlocksize(hash_function) / 8){
134             hfal_hash_nextBlock(&ctx, block);
135         }
136     }
137     hfal_hash_ctx2hash(hash_value, &ctx);
138     hfal_hash_free(&ctx);
139     free(block);
140     return hash_value;
141 }
142
143 void testrun_performance_invert_bigint(void){
144     printf_P(PSTR("\n=== performance measurement (invert) ===\n"));
145     unsigned i,j;
146     uint64_t time = 0;
147     bigint_t a, v;
148     bigint_word_t v_w[192 / BIGINT_WORD_SIZE];
149     bigint_word_t a_w[192 / BIGINT_WORD_SIZE];
150
151     a.wordv = a_w;
152     v.wordv = v_w;
153
154     for(j = 0; j < 32; ++j){
155         for(i = 0; i < 192 / BIGINT_WORD_SIZE; ++i){
156             ((uint8_t*)v_w)[i] = random();
157         }
158         v.length_W = 192 / BIGINT_WORD_SIZE;
159         v.info = 0;
160         bigint_adjust(&v);
161
162         for(i = 0; i < 16; ++i){
163             startTimer(1);
164             START_TIMER;
165             bigint_inverse(&a, &v, &nist_curve_p192_p);
166             STOP_TIMER;
167             time += stopTimer();
168         }
169     }
170
171     time >>= 8;
172     ++time;
173     time >>= 1;
174
175     printf_P(PSTR("  invert costs %"PRIu32" cycles\n"), (uint32_t)time);
176 }
177
178 void testrun_performance_multiply_bigint(void){
179     printf_P(PSTR("\n=== performance measurement (invert) ===\n"));
180     unsigned i,j;
181     uint64_t time_a = 0, time_b = 0;
182     uint32_t tmp;
183     bigint_t a, b, v;
184     bigint_word_t v_w[192 * 2 / BIGINT_WORD_SIZE];
185     bigint_word_t a_w[192 / BIGINT_WORD_SIZE];
186     bigint_word_t b_w[192 / BIGINT_WORD_SIZE];
187
188     a.wordv = a_w;
189     b.wordv = b_w;
190     v.wordv = v_w;
191
192     for(j = 0; j < 32; ++j){
193         for(i = 0; i < 192 / BIGINT_WORD_SIZE; ++i){
194             ((uint8_t*)a_w)[i] = random();
195         }
196         a.length_W = 192 / BIGINT_WORD_SIZE;
197         a.info = 0;
198         bigint_adjust(&a);
199
200         for(i = 0; i < 192 / BIGINT_WORD_SIZE; ++i){
201             ((uint8_t*)b_w)[i] = random();
202         }
203         b.length_W = 192 / BIGINT_WORD_SIZE;
204         b.info = 0;
205         bigint_adjust(&b);
206
207         for(i = 0; i < 16; ++i){
208             startTimer(1);
209             START_TIMER;
210             bigint_mul_u(&v,&a, &b);
211             STOP_TIMER;
212             tmp = stopTimer();
213             time_a += tmp;
214             time_b += tmp;
215
216             START_TIMER;
217             bigint_reduce_p192(&v);
218             STOP_TIMER;
219             tmp = stopTimer();
220             time_b += tmp;
221          }
222     }
223
224     time_a >>= 8;
225     ++time_a;
226     time_a >>= 1;
227
228     time_b >>= 8;
229     ++time_b;
230     time_b >>= 1;
231
232
233     printf_P(PSTR("  multiply          costs %7"PRIu32" cycles\n"), (uint32_t)time_a);
234     printf_P(PSTR("  multiply + reduce costs %7"PRIu32" cycles\n"), (uint32_t)time_b);
235 }
236
237 void testrun_performance_reduce_bigint(void){
238     printf_P(PSTR("\n=== performance measurement (reduce) ===\n"));
239     unsigned i, j;
240     bigint_t a,b,v;
241     bigint_word_t v_w[192 * 2 / BIGINT_WORD_SIZE];
242     bigint_word_t a_w[192 * 2 / BIGINT_WORD_SIZE];
243     bigint_word_t b_w[192 * 2 / BIGINT_WORD_SIZE];
244     uint32_t time_a, time_b;
245     int32_t time_diff;
246     int16_t faster_percent;
247     v.wordv = v_w;
248     for(j = 0; j < 32; ++j){
249         do{
250             for(i = 0; i < 192 * 2 / BIGINT_WORD_SIZE; ++i){
251                 ((uint8_t*)v_w)[i] = random();
252             }
253             v.length_W = 192 * 2 / BIGINT_WORD_SIZE;
254             v.info = 0;
255             bigint_adjust(&v);
256         }while(0);
257
258     //    printf_P(PSTR("candidate:\n"));
259     //    bigint_print_hex(&v);
260         a.wordv = a_w;
261         b.wordv = b_w;
262         calibrateTimer();
263
264     //    printf_P(PSTR("\n  going to test optimized version: ...\n"));
265         uart0_flush();
266         time_a = 0;
267         for(i = 0; i < 16; ++i){
268             bigint_copy(&a, &v);
269             startTimer(1);
270             START_TIMER;
271             bigint_reduce_p192(&a);
272             STOP_TIMER;
273             time_a += stopTimer();
274         }
275     //    printf_P(PSTR("    took: %"PRIu32" cycles\nresult:"), time);
276     //    bigint_print_hex(&a);
277
278
279     //    printf_P(PSTR("\n  going to test not-optimized version: ...\n"));
280     //    uart0_flush();
281         time_b = 0;
282         for(i = 0; i < 16; ++i){
283             bigint_copy(&b, &v);
284             startTimer(1);
285             START_TIMER;
286             bigint_reduce(&b, &nist_curve_p192_p);
287             STOP_TIMER;
288             time_b += stopTimer();
289         }
290     //    printf_P(PSTR("    took: %"PRIu32" cycles\nresult:"), time);
291     //    bigint_print_hex(&b);
292
293         time_diff = time_b - time_a;
294         faster_percent = (time_diff * 100) / time_b;
295
296         printf_P(PSTR("  delta: %7"PRId32"  (%3"PRId16"%%)  :-"), time_diff, faster_percent);
297         if(bigint_cmp_u(&a, &b)){
298             printf_P(PSTR("(\n"));
299         } else {
300             printf_P(PSTR(")\n"));
301         }
302         uart0_flush();
303     }
304 }
305
306 uint8_t ecc_affine_point_alloc(ecc_affine_point_t *p, uint16_t length_b){
307     size_t len = (length_b + BIGINT_WORD_SIZE - 1)/ BIGINT_WORD_SIZE;
308     if (! (p->x.wordv = malloc(len))){
309         return 1;
310     }
311     if (! (p->y.wordv = malloc(len))){
312         free(p->x.wordv);
313         return 2;
314     }
315     return 0;
316 }
317
318 void ecc_affine_point_free(ecc_affine_point_t *p){
319     free(p->x.wordv);
320     free(p->y.wordv);
321 }
322
323
324 void testrun_square(void){
325     bigint_word_t a_w[] = {
326         0x82, 0x6f, 0x79, 0x39, 0x47, 0x06, 0x26, 0x9f,
327         0x4b, 0xe2, 0x15, 0x61, 0x6f, 0xa1, 0xd4, 0x0c,
328         0x1f, 0x24, 0x3a, 0xd4, 0xc2, 0x6d, 0xe8, 0xb6
329     };
330
331     bigint_word_t b_w[2 * 192 / BIGINT_WORD_SIZE];
332     bigint_t a, b;
333
334     a.wordv = a_w;
335     a.length_W = sizeof(a_w);
336     a.info = 7;
337
338     b.wordv = b_w;
339     b.info = 0;
340     b.length_W = 0;
341
342     printf_P(PSTR("\n a = "));
343     bigint_print_hex(&a);
344     bigint_square(&b, &a);
345     printf_P(PSTR("\n a^2 = "));
346     bigint_print_hex(&b);
347     bigint_reduce_p192(&b);
348     printf_P(PSTR("\n a^2 %% p = "));
349     bigint_print_hex(&b);
350     putchar('\n');
351
352
353 }
354
355 #if 1
356 /*
357 0: b3cfed2634516540528622e16c396c229e50bbdf773f8423
358 1: b6e86dc2d43a241f0cd4a16f6115e24b9f26064739796f82
359 2: 563f557e41731f268f82fe81c8fed959600dd46649ebeeee
360 3: 5e45169bd87475db886b8a7833bb0845f5b011a7ce0c1766
361 4: 4abf34c505a73308a804dcefacbd8f7b10b59fa6ac6421a
362 */
363 uint8_t test_point_x_w[] = {
364     0x23, 0x84, 0x3f, 0x77, 0xdf, 0xbb, 0x50, 0x9e,
365     0x22, 0x6c, 0x39, 0x6c, 0xe1, 0x22, 0x86, 0x52,
366     0x40, 0x65, 0x51, 0x34, 0x26, 0xed, 0xcf, 0xb3
367 };
368
369 uint8_t test_point_y_w[] = {
370     0x82, 0x6f, 0x79, 0x39, 0x47, 0x06, 0x26, 0x9f,
371     0x4b, 0xe2, 0x15, 0x61, 0x6f, 0xa1, 0xd4, 0x0c,
372     0x1f, 0x24, 0x3a, 0xd4, 0xc2, 0x6d, 0xe8, 0xb6
373 };
374
375 uint8_t test_point_z1_w[] = {
376     0xee, 0xee, 0xeb, 0x49, 0x66, 0xd4, 0x0d, 0x60,
377     0x59, 0xd9, 0xfe, 0xc8, 0x81, 0xfe, 0x82, 0x8f,
378     0x26, 0x1f, 0x73, 0x41, 0x7e, 0x55, 0x3f, 0x56
379 };
380
381 uint8_t test_point_z2_w[] = {
382     0x66, 0x17, 0x0c, 0xce, 0xa7, 0x11, 0xb0, 0xf5,
383     0x45, 0x08, 0xbb, 0x33, 0x78, 0x8a, 0x6b, 0x88,
384     0xdb, 0x75, 0x74, 0xd8, 0x9b, 0x16, 0x45, 0x5e
385 };
386
387 uint8_t test_point_z3_w[] = {
388     0x1a, 0x42, 0xc6, 0x6a, 0xfa, 0x59, 0x0b, 0xb1,
389     0xf7, 0xd8, 0xcb, 0xfa, 0xce, 0x4d, 0x80, 0x8a,
390     0x30, 0x73, 0x5a, 0x50, 0x4c, 0xf3, 0xab, 0x04
391 };
392
393 ecc_combi_point_t test_point = {
394     .chudnovsky = {
395         .x = {
396             .wordv = test_point_x_w,
397             .length_W = sizeof(test_point_x_w),
398             .info = 7
399         },
400         .y = {
401             .wordv = test_point_y_w,
402             .length_W = sizeof(test_point_y_w),
403             .info = 7
404         },
405         .z1 = {
406             .wordv = test_point_z1_w,
407             .length_W = sizeof(test_point_z1_w),
408             .info = 6
409         },
410         .z2 = {
411             .wordv = test_point_z2_w,
412             .length_W = sizeof(test_point_z2_w),
413             .info = 6
414         },
415         .z3 = {
416             .wordv = test_point_z3_w,
417             .length_W = sizeof(test_point_z3_w),
418             .info = 2
419         }
420     }
421 };
422 void testrun_genkey2(void){
423     ecc_chudnovsky_point_t q;
424     ecc_affine_point_t qa;
425
426     printf_P(PSTR("\n== testing key generation (2) ==\n"));
427
428     if(ecc_chudnovsky_point_alloc(&q, 192)){
429         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
430         return;
431     }
432     if(ecc_affine_point_alloc(&qa, 192)){
433         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
434         return;
435     }
436
437     ecc_chudnovsky_point_print(&test_point.chudnovsky);
438     ecc_chudnovsky_to_affine_point(&qa, &test_point.chudnovsky, &nist_curve_p192);
439     printf_P(PSTR("\n  Qx: "));
440     bigint_print_hex(&qa.x);
441     printf_P(PSTR("\n  Qy: "));
442     bigint_print_hex(&qa.y);
443     printf_P(PSTR("\n================\n"));
444     ecc_chudnovsky_point_double_sp(&q, &test_point.chudnovsky, &nist_curve_p192);
445     ecc_chudnovsky_point_print(&q);
446
447     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
448
449     printf_P(PSTR("\n  Qx: "));
450     bigint_print_hex(&qa.x);
451     printf_P(PSTR("\n  Qy: "));
452     bigint_print_hex(&qa.y);
453     puts("\n");
454
455 }
456
457 void testrun_genkey1(void){
458     ecc_chudnovsky_point_t q;
459     ecc_affine_point_t qa;
460
461     uint8_t k_w[] = {
462     //  e5ce89a34adddf25ff3bf1ffe6803f57d0220de3118798ea
463         0xea, 0x98, 0x87, 0x11, 0xe3, 0x0d, 0x22, 0xd0,
464         0x57, 0x3f, 0x80, 0xe6, 0xff, 0xf1, 0x3b, 0xff,
465         0x25, 0xdf, 0xdd, 0x4a, 0xa3, 0x89, 0xce, 0xe5
466     };
467
468     bigint_t k = {
469             .length_W = sizeof(k_w),
470             .wordv = k_w,
471             .info = 7
472     };
473
474     printf_P(PSTR("\n== testing key generation ==\n"));
475
476     if(ecc_chudnovsky_point_alloc(&q, 192)){
477         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
478         return;
479     }
480     if(ecc_affine_point_alloc(&qa, 192)){
481         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
482         return;
483     }
484
485     printf_P(PSTR("  k:  "));
486     bigint_print_hex(&k);
487     ecc_chudnovsky_multiplication(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
488     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
489
490     printf_P(PSTR("\n  Qx: "));
491     bigint_print_hex(&qa.x);
492     printf_P(PSTR("\n  Qy: "));
493     bigint_print_hex(&qa.y);
494     puts("\n");
495
496     ecc_affine_point_free(&qa);
497     ecc_chudnovsky_point_free(&q);
498 }
499
500 void testrun_genkey3(void){
501     ecc_chudnovsky_point_t q;
502     ecc_affine_point_t qa;
503
504     uint8_t k_w[] = {
505         0xb2, 0x51, 0x97, 0xc3, 0x7c, 0x61, 0xf8, 0x8f,
506         0x19, 0x91, 0xcc, 0x67, 0xb5, 0x1c, 0x34, 0x23,
507         0xff, 0x13, 0xad, 0x14, 0x57, 0x43, 0x14, 0x7d
508     };
509
510     bigint_t k = {
511             .length_W = sizeof(k_w),
512             .wordv = k_w,
513             .info = 6
514     };
515
516     printf_P(PSTR("\n== testing key generation ==\n"));
517
518     if(ecc_chudnovsky_point_alloc(&q, 192)){
519         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
520         return;
521     }
522     if(ecc_affine_point_alloc(&qa, 192)){
523         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
524         return;
525     }
526
527     printf_P(PSTR("  k:  "));
528     bigint_print_hex(&k);
529     ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
530     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
531
532     printf_P(PSTR("\n  Qx: "));
533     bigint_print_hex(&qa.x);
534     printf_P(PSTR("\n  Qy: "));
535     bigint_print_hex(&qa.y);
536     puts("\n");
537
538     ecc_affine_point_free(&qa);
539     ecc_chudnovsky_point_free(&q);
540
541 }
542
543 void testrun_genkey(void){
544     ecc_chudnovsky_point_t q;
545     ecc_affine_point_t qa;
546     uint32_t time;
547     bigint_t k;
548     uint8_t r;
549
550     printf_P(PSTR("\n== testing key generation ==\n"));
551
552     printf_P(PSTR("enter secret key d: "));
553     bigint_read_hex_echo(&k);
554     putchar('\n');
555
556     if(ecc_chudnovsky_point_alloc(&q, 192)){
557         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
558         return;
559     }
560     if(ecc_affine_point_alloc(&qa, 192)){
561         ecc_chudnovsky_point_free(&q);
562         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
563         return;
564     }
565
566     printf_P(PSTR("(naf)  k:  "));
567     bigint_print_hex(&k);
568     startTimer(1);
569     START_TIMER;
570     r = ecc_chudnovsky_naf_multiplication(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
571     STOP_TIMER;
572     time = stopTimer();
573     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
574
575     printf_P(PSTR("\n  Qx: "));
576     bigint_print_hex(&qa.x);
577     printf_P(PSTR("\n  Qy: "));
578     bigint_print_hex(&qa.y);
579     printf_P(PSTR("\n time: %"PRIu32" cycles (r code: %"PRIu8")\n"), time, r);
580
581     printf_P(PSTR("(d&a)  k:  "));
582     bigint_print_hex(&k);
583     startTimer(1);
584     START_TIMER;
585     r = ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
586     STOP_TIMER;
587     time = stopTimer();
588     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
589
590     printf_P(PSTR("\n  Qx: "));
591     bigint_print_hex(&qa.x);
592     printf_P(PSTR("\n  Qy: "));
593     bigint_print_hex(&qa.y);
594     printf_P(PSTR("\n time: %"PRIu32" cycles (r code: %"PRIu8")\n"), time, r);
595     free(k.wordv);
596     ecc_chudnovsky_point_free(&q);
597     ecc_affine_point_free(&qa);
598 }
599 /*
600 N is
601 3128D2B4 B1C96B14 36F8DE99 FFFFFFFF FFFFFFFF FFFFFFFF 99DEF836 146BC9B1 B4D22831
602 --------------------------------------------------------------
603 C is
604 78916860 32FD8057 F636B44B 1F47CCE5 64D25099 23A7465A
605 --------------------------------------------------------------
606 D is
607 78916860 32FD8057 F636B44B 1F47CCE5 64D25099 23A7465B
608 Q_x is
609 FBA2AAC6 47884B50 4EB8CD5A 0A1287BA BCC62163 F606A9A2
610 Q_y is
611 DAE6D4CC 05EF4F27 D79EE38B 71C9C8EF 4865D988 50D84AA5
612 */
613
614 void testrun_interm(void){
615     ecc_chudnovsky_point_t q;
616     ecc_affine_point_t qa;
617     uint32_t time;
618     bigint_t k;
619     uint8_t r;
620
621     printf_P(PSTR("\n== testing key generation ==\n"));
622
623     printf_P(PSTR("enter secret key d: "));
624     bigint_read_hex_echo(&k);
625     putchar('\n');
626
627     if(ecc_chudnovsky_point_alloc(&q, 192)){
628         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
629         return;
630     }
631     if(ecc_affine_point_alloc(&qa, 192)){
632         ecc_chudnovsky_point_free(&q);
633         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
634         return;
635     }
636
637     printf_P(PSTR("(naf)  k:  "));
638     bigint_print_hex(&k);
639     startTimer(1);
640     START_TIMER;
641     r = ecc_chudnovsky_naf_multiplication(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
642     STOP_TIMER;
643     time = stopTimer();
644     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
645
646     printf_P(PSTR("\n  Qx: "));
647     bigint_print_hex(&qa.x);
648     printf_P(PSTR("\n  Qy: "));
649     bigint_print_hex(&qa.y);
650     printf_P(PSTR("\n time: %"PRIu32" cycles (r code: %"PRIu8")\n"), time, r);
651
652     printf_P(PSTR("(d&a)  k:  "));
653     bigint_print_hex(&k);
654     startTimer(1);
655     START_TIMER;
656     r = ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
657     STOP_TIMER;
658     time = stopTimer();
659     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
660
661     printf_P(PSTR("\n  Qx: "));
662     bigint_print_hex(&qa.x);
663     printf_P(PSTR("\n  Qy: "));
664     bigint_print_hex(&qa.y);
665     printf_P(PSTR("\n time: %"PRIu32" cycles (r code: %"PRIu8")\n"), time, r);
666     free(k.wordv);
667     ecc_chudnovsky_point_free(&q);
668     ecc_affine_point_free(&qa);
669 }
670
671
672
673 #endif
674
675 const uint8_t ecdsa_test_1_msg[] PROGMEM = {
676 /*
677     0xcf, 0x71, 0xa0, 0xe4, 0xce, 0x59, 0x43, 0x11,
678     0x77, 0x88, 0x50, 0x87, 0x53, 0x78, 0xd0, 0xee,
679     0xa3, 0xc0, 0x32, 0xa4, 0xbc, 0xc0, 0xdc, 0x1c,
680     0xf2, 0x9d, 0x01, 0xb9, 0xc5, 0x10, 0x78, 0x9c,
681     0xd5, 0x2f, 0xc3, 0x8c, 0x74, 0xe6, 0xa4, 0x27,
682     0x87, 0xd0, 0xf2, 0x7c, 0xe2, 0x93, 0x20, 0x7a,
683     0xfd, 0xd0, 0x11, 0x7a, 0xcc, 0x71, 0xb9, 0x16,
684     0x63, 0x06, 0xce, 0x56, 0xf1, 0xa7, 0xf1, 0xc6,
685     0x0a, 0x9d, 0x68, 0x7d, 0x12, 0x5e, 0xb0, 0x7e,
686     0x26, 0xe5, 0x51, 0xdc, 0x14, 0x0e, 0x8a, 0x04,
687     0xaf, 0xa2, 0xa1, 0x6f, 0x98, 0xb5, 0x1b, 0xa9,
688     0x18, 0x96, 0xbf, 0x32, 0x0f, 0xd4, 0xd6, 0xf1,
689     0xa4, 0x4b, 0x46, 0xf3, 0x3d, 0xae, 0x39, 0xcc,
690     0x24, 0xf0, 0x4a, 0x5d, 0x86, 0x0c, 0xb1, 0x4f,
691     0x6b, 0x6e, 0x8a, 0x69, 0x73, 0xb4, 0x9f, 0xd2,
692     0xa7, 0xbc, 0xeb, 0x48, 0xd7, 0x48, 0xf7, 0xeb
693 */
694     0xeb, 0xf7, 0x48, 0xd7, 0x48, 0xeb, 0xbc, 0xa7,
695     0xd2, 0x9f, 0xb4, 0x73, 0x69, 0x8a, 0x6e, 0x6b,
696     0x4f, 0xb1, 0x0c, 0x86, 0x5d, 0x4a, 0xf0, 0x24,
697     0xcc, 0x39, 0xae, 0x3d, 0xf3, 0x46, 0x4b, 0xa4,
698     0xf1, 0xd6, 0xd4, 0x0f, 0x32, 0xbf, 0x96, 0x18,
699     0xa9, 0x1b, 0xb5, 0x98, 0x6f, 0xa1, 0xa2, 0xaf,
700     0x04, 0x8a, 0x0e, 0x14, 0xdc, 0x51, 0xe5, 0x26,
701     0x7e, 0xb0, 0x5e, 0x12, 0x7d, 0x68, 0x9d, 0x0a,
702     0xc6, 0xf1, 0xa7, 0xf1, 0x56, 0xce, 0x06, 0x63,
703     0x16, 0xb9, 0x71, 0xcc, 0x7a, 0x11, 0xd0, 0xfd,
704     0x7a, 0x20, 0x93, 0xe2, 0x7c, 0xf2, 0xd0, 0x87,
705     0x27, 0xa4, 0xe6, 0x74, 0x8c, 0xc3, 0x2f, 0xd5,
706     0x9c, 0x78, 0x10, 0xc5, 0xb9, 0x01, 0x9d, 0xf2,
707     0x1c, 0xdc, 0xc0, 0xbc, 0xa4, 0x32, 0xc0, 0xa3,
708     0xee, 0xd0, 0x78, 0x53, 0x87, 0x50, 0x88, 0x77,
709     0x11, 0x43, 0x59, 0xce, 0xe4, 0xa0, 0x71, 0xcf
710 };
711
712 /*
713  * d = e14f37b3d1374ff8b03f41b9b3fdd2f0ebccf275d660d7f3
714  */
715
716 const uint8_t ecdsa_test_1_d[] PROGMEM = {
717     0xf3, 0xd7, 0x60, 0xd6, 0x75, 0xf2, 0xcc, 0xeb,
718     0xf0, 0xd2, 0xfd, 0xb3, 0xb9, 0x41, 0x3f, 0xb0,
719     0xf8, 0x4f, 0x37, 0xd1, 0xb3, 0x37, 0x4f, 0xe1
720 };
721
722 /*
723  * k = cb0abc7043a10783684556fb12c4154d57bc31a289685f25
724  */
725
726 const uint8_t ecdsa_test_1_k[] PROGMEM = {
727     0x25, 0x5f, 0x68, 0x89, 0xa2, 0x31, 0xbc, 0x57,
728     0x4d, 0x15, 0xc4, 0x12, 0xfb, 0x56, 0x45, 0x68,
729     0x83, 0x07, 0xa1, 0x43, 0x70, 0xbc, 0x0a, 0xcb
730 };
731
732 void hash_mem_P(const hfdesc_t *hfdesc, void *dest, const void *msg, uint16_t msg_len_b){
733     uint16_t blocksize = hfal_hash_getBlocksize(hfdesc);
734     uint8_t block[blocksize / 8];
735     hfgen_ctx_t ctx;
736     hfal_hash_init(hfdesc, &ctx);
737     while(msg_len_b > blocksize){
738         memcpy_P(block, msg, blocksize / 8);
739         msg = (uint8_t*)msg + blocksize / 8;
740         msg_len_b -= blocksize;
741         hfal_hash_nextBlock(&ctx, block);
742     }
743     memcpy_P(block, msg, (msg_len_b + 7) / 8);
744     hfal_hash_lastBlock(&ctx, block, msg_len_b);
745     hfal_hash_ctx2hash(dest,  &ctx);
746     hfal_hash_free(&ctx);
747 }
748
749 const uint8_t ecdsa_test_2_msg[] PROGMEM = {
750     0x66, 0xa2, 0x51, 0x3d, 0x7b, 0x60, 0x45, 0xe5,
751     0x66, 0x79, 0xb0, 0x32, 0xca, 0xd4, 0x5f, 0xb1,
752     0x82, 0x28, 0x9c, 0xa7, 0x6a, 0x88, 0xc0, 0x6d,
753     0x78, 0xc8, 0x5f, 0x3d, 0xd3, 0x80, 0x45, 0x90,
754     0x20, 0x5b, 0x73, 0xa7, 0x84, 0x24, 0x9a, 0x0a,
755     0x0c, 0x8b, 0xf2, 0xf2, 0x21, 0x45, 0xd1, 0x05,
756     0x21, 0x9b, 0x48, 0x0d, 0x74, 0x60, 0x7c, 0x02,
757     0xb8, 0xa6, 0xb6, 0xb4, 0x59, 0x25, 0x9e, 0x4f,
758     0xdf, 0xe2, 0xbd, 0xb4, 0xab, 0x22, 0x38, 0x01,
759     0x75, 0x35, 0x29, 0x1d, 0x7a, 0xc1, 0xab, 0xda,
760     0x66, 0xc4, 0xf6, 0xdc, 0xea, 0x9e, 0x5d, 0x0b,
761     0xf0, 0x5a, 0x93, 0x06, 0xf3, 0x33, 0xb0, 0x0e,
762     0x56, 0x34, 0x2f, 0x75, 0x53, 0x40, 0x21, 0x1a,
763     0xc2, 0x94, 0xac, 0x21, 0xa7, 0xc2, 0xb2, 0x67,
764     0x12, 0xb8, 0x79, 0x95, 0x1b, 0x2e, 0x23, 0xf6,
765     0x48, 0x7e, 0x4d, 0x39, 0x89, 0x9f, 0xe3, 0x74
766 };
767
768 const uint8_t ecdsa_test_2_d[] PROGMEM = {
769     0xeb, 0x8e, 0x9f, 0x04, 0x7d, 0xb5, 0x9a, 0x80,
770     0x34, 0x6f, 0xcd, 0xf1, 0xcc, 0x33, 0xbb, 0x78,
771     0xbe, 0xc6, 0xb8, 0x76, 0xaf, 0x9f, 0x4b, 0x69
772 };
773
774 const uint8_t ecdsa_test_2_k[] PROGMEM = {
775     0x8e, 0xd5, 0x00, 0x34, 0x08, 0x09, 0x60, 0x36,
776     0x2e, 0xfe, 0x16, 0xd0, 0x53, 0x37, 0xa2, 0xf5,
777     0x47, 0xfa, 0x11, 0xbc, 0xb1, 0xc2, 0xe8, 0x41
778 };
779
780 #if 0
781 void test_sign1(void){
782     bigint_word_t d_w[sizeof(ecdsa_test_1_d)];
783     uint8_t rnd[sizeof(ecdsa_test_1_k)];
784     uint8_t *hash;
785     bigint_t d;
786     const hfdesc_t *hash_desc;
787     ecc_combi_point_t q;
788     ecdsa_signature_t sign;
789     ecdsa_ctx_t ctx;
790     uint8_t r;
791
792     putchar('\n');
793     d.wordv = d_w;
794     memcpy_P(rnd, ecdsa_test_1_k, sizeof(ecdsa_test_1_k));
795     memcpy_P(d_w, ecdsa_test_1_d, sizeof(ecdsa_test_1_d));
796     d.length_W = (sizeof(ecdsa_test_1_d) + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t);
797     d.info = 0;
798     bigint_adjust(&d);
799
800     hash_desc = &sha1_desc; //hash_select();
801     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
802     if(hash == NULL){
803         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
804     }
805     hash_mem_P(hash_desc, hash, ecdsa_test_1_msg, sizeof(ecdsa_test_1_msg) * 8);
806     printf_P(PSTR("msg hash: "));
807     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
808     putchar('\n');
809
810     ecc_affine_point_alloc(&q.affine, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
811 //    ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
812 //    ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
813     ctx.basepoint = &nist_curve_p192_basepoint.affine;
814     ctx.priv = &d;
815     ctx.curve = &nist_curve_p192;
816
817     printf("\n  d:  ");
818     bigint_print_hex(&d);
819     printf_P(PSTR("\n  Gx: "));
820     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
821     printf_P(PSTR("\n  Gy: "));
822     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
823
824 //    r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
825     r = ecc_????
826     if(r){
827         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
828     }
829 //    r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
830     if(r){
831         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
832     }
833
834     printf_P(PSTR("\n  Qx: "));
835     bigint_print_hex(&q.affine.x);
836     printf_P(PSTR("\n  Qy: "));
837     bigint_print_hex(&q.affine.y);
838     putchar('\n');
839     ctx.pub = &q.affine;
840
841     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
842
843     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
844     if(r){
845         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
846     }
847     printf_P(PSTR("  r: "));
848     bigint_print_hex(&sign.r);
849     printf_P(PSTR("\n  s: "));
850     bigint_print_hex(&sign.s);
851
852     free(hash);
853     ecdsa_signature_free(&sign);
854     ecc_chudnovsky_point_free(&q.chudnovsky);
855 }
856
857 #else
858
859 void test_sign1(void){
860     bigint_word_t d_w[sizeof(ecdsa_test_1_d)];
861     uint8_t rnd[sizeof(ecdsa_test_1_k)];
862     uint8_t *hash;
863     bigint_t d;
864     const hfdesc_t *hash_desc;
865     ecc_combi_point_t q;
866     ecdsa_signature_t sign;
867     ecdsa_ctx_t ctx;
868     uint8_t r;
869
870     putchar('\n');
871     d.wordv = d_w;
872     memcpy_P(rnd, ecdsa_test_1_k, sizeof(ecdsa_test_1_k));
873     memcpy_P(d_w, ecdsa_test_1_d, sizeof(ecdsa_test_1_d));
874     d.length_W = (sizeof(ecdsa_test_1_d) + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t);
875     d.info = 0;
876     bigint_adjust(&d);
877
878     hash_desc = &sha1_desc; //hash_select();
879     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
880     if(hash == NULL){
881         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
882     }
883     hash_mem_P(hash_desc, hash, ecdsa_test_1_msg, sizeof(ecdsa_test_1_msg) * 8);
884     printf_P(PSTR("msg hash: "));
885     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
886     putchar('\n');
887
888     ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
889     ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
890     ctx.priv = &d;
891     ctx.curve = &nist_curve_p192;
892
893     printf("\n  d:  ");
894     bigint_print_hex(&d);
895     printf_P(PSTR("\n  Gx: "));
896     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
897     printf_P(PSTR("\n  Gy: "));
898     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
899
900     r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
901     if(r){
902         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
903     }
904     r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
905     if(r){
906         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
907     }
908
909     printf_P(PSTR("\n  Qx: "));
910     bigint_print_hex(&q.affine.x);
911     printf_P(PSTR("\n  Qy: "));
912     bigint_print_hex(&q.affine.y);
913     putchar('\n');
914     ctx.pub = &q.affine;
915
916     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
917
918     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
919     if(r){
920         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
921     }
922     printf_P(PSTR("  r: "));
923     bigint_print_hex(&sign.r);
924     printf_P(PSTR("\n  s: "));
925     bigint_print_hex(&sign.s);
926
927     free(hash);
928     ecdsa_signature_free(&sign);
929     ecc_chudnovsky_point_free(&q.chudnovsky);
930 }
931
932 #endif
933
934 void test_sign2(void){
935     bigint_word_t d_w[sizeof(ecdsa_test_2_d)];
936     uint8_t rnd[sizeof(ecdsa_test_2_k)];
937     uint8_t *hash;
938     bigint_t d;
939     const hfdesc_t *hash_desc;
940     ecc_combi_point_t q;
941     ecdsa_signature_t sign;
942     ecdsa_ctx_t ctx;
943     uint8_t r;
944
945     putchar('\n');
946     d.wordv = d_w;
947     memcpy_P(rnd, ecdsa_test_2_k, sizeof(ecdsa_test_2_k));
948     memcpy_P(d_w, ecdsa_test_2_d, sizeof(ecdsa_test_2_d) * sizeof(bigint_word_t));
949     d.length_W = sizeof(ecdsa_test_2_d) / sizeof(bigint_word_t);
950     d.info = 0;
951     bigint_adjust(&d);
952
953     hash_desc = &sha224_desc; //hash_select();
954     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
955     if(hash == NULL){
956         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
957     }
958     hash_mem_P(hash_desc, hash, ecdsa_test_2_msg, sizeof(ecdsa_test_1_msg) * 8);
959     printf_P(PSTR("msg hash: "));
960     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
961     putchar('\n');
962
963     ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
964     ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
965     ctx.priv = &d;
966     ctx.curve = &nist_curve_p192;
967
968     printf("\n  d:  ");
969     bigint_print_hex(&d);
970     printf_P(PSTR("\n  Gx: "));
971     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
972     printf_P(PSTR("\n  Gy: "));
973     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
974
975     r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
976     if(r){
977         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
978     }
979     r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
980     if(r){
981         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
982     }
983
984     printf_P(PSTR("\n  Qx: "));
985     bigint_print_hex(&q.affine.x);
986     printf_P(PSTR("\n  Qy: "));
987     bigint_print_hex(&q.affine.y);
988     putchar('\n');
989     ctx.pub = &q.affine;
990
991     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_2_d) * sizeof(bigint_word_t));
992
993     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
994     if(r){
995         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
996     }
997     printf_P(PSTR("  r: "));
998     bigint_print_hex(&sign.r);
999     printf_P(PSTR("\n  s: "));
1000     bigint_print_hex(&sign.s);
1001
1002     free(hash);
1003     ecdsa_signature_free(&sign);
1004     ecc_chudnovsky_point_free(&q.chudnovsky);
1005 }
1006 /*****************************************************************************
1007  *  main                                                                                                                                         *
1008  *****************************************************************************/
1009
1010 const char echo_test_str[]               PROGMEM = "echo-test";
1011 const char reset_prng_str[]              PROGMEM = "reset-prng";
1012 const char quick_test_str[]              PROGMEM = "quick-test";
1013 const char performance_reduce_str[]      PROGMEM = "performance_reduce";
1014 const char performance_invert_str[]      PROGMEM = "performance_invert";
1015 const char performance_multiply_str[]    PROGMEM = "performance_multiply";
1016 const char genkey1_str[]                 PROGMEM = "genkey1";
1017 const char genkey2_str[]                 PROGMEM = "genkey2";
1018 const char genkey3_str[]                 PROGMEM = "genkey3";
1019 const char genkey_str[]                  PROGMEM = "genkey";
1020 const char testsign1_str[]               PROGMEM = "testsign1";
1021 const char testsign2_str[]               PROGMEM = "testsign2";
1022 const char square_str[]                  PROGMEM = "square";
1023 const char echo_str[]                    PROGMEM = "echo";
1024
1025 const const cmdlist_entry_t cmdlist[] PROGMEM = {
1026 //      { reset_prng_str,              NULL, reset_prng                           },
1027 //      { quick_test_str,              NULL, quick_test                           },
1028     { square_str,                  NULL, testrun_square                       },
1029     { genkey_str,                  NULL, testrun_genkey                       },
1030     { genkey1_str,                 NULL, testrun_genkey1                      },
1031     { genkey2_str,                 NULL, testrun_genkey2                      },
1032     { genkey3_str,                 NULL, testrun_genkey3                      },
1033     { testsign1_str,               NULL, test_sign1                           },
1034     { testsign2_str,               NULL, test_sign2                           },
1035         { performance_reduce_str,      NULL, testrun_performance_reduce_bigint    },
1036     { performance_invert_str,      NULL, testrun_performance_invert_bigint    },
1037     { performance_multiply_str,    NULL, testrun_performance_multiply_bigint  },
1038         { echo_str,                (void*)1, (void_fpt)echo_ctrl                  },
1039         { NULL,                        NULL, NULL                                 }
1040 };
1041
1042 int main (void){
1043     int8_t r;
1044     main_setup();
1045     calibrateTimer();
1046     for(;;){
1047         welcome_msg(algo_name);
1048         r = cmd_interface(cmdlist);
1049         printf("r = %"PRId8"\n", r);
1050         cli_putstr_P(PSTR("\r\nHello!\r\n"));
1051         }
1052 }