]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/main-ecdsa-test.c
bug fixing and support for malloc instead of stack memory (some functions)
[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) 2010 Daniel Otte (daniel.otte@rub.de)
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 const uint8_t ecdsa_test_1_d[] PROGMEM = {
713     0xf3, 0xd7, 0x60, 0xd6, 0x75, 0xf2, 0xcc, 0xeb,
714     0xf0, 0xd2, 0xfd, 0xb3, 0xb9, 0x41, 0x3f, 0xb0,
715     0xf8, 0x4f, 0x37, 0xd1, 0xb3, 0x37, 0x4f, 0xe1
716 };
717
718 const uint8_t ecdsa_test_1_k[] PROGMEM = {
719     0x25, 0x5f, 0x68, 0x89, 0xa2, 0x31, 0xbc, 0x57,
720     0x4d, 0x15, 0xc4, 0x12, 0xfb, 0x56, 0x45, 0x68,
721     0x83, 0x07, 0xa1, 0x43, 0x70, 0xbc, 0x0a, 0xcb
722 };
723
724 void hash_mem_P(const hfdesc_t *hfdesc, void *dest, const void *msg, uint16_t msg_len_b){
725     uint16_t blocksize = hfal_hash_getBlocksize(hfdesc);
726     uint8_t block[blocksize / 8];
727     hfgen_ctx_t ctx;
728     hfal_hash_init(hfdesc, &ctx);
729     while(msg_len_b > blocksize){
730         memcpy_P(block, msg, blocksize / 8);
731         msg = (uint8_t*)msg + blocksize / 8;
732         msg_len_b -= blocksize;
733         hfal_hash_nextBlock(&ctx, block);
734     }
735     memcpy_P(block, msg, (msg_len_b + 7) / 8);
736     hfal_hash_lastBlock(&ctx, block, msg_len_b);
737     hfal_hash_ctx2hash(dest,  &ctx);
738     hfal_hash_free(&ctx);
739 }
740
741 const uint8_t ecdsa_test_2_msg[] PROGMEM = {
742     0x66, 0xa2, 0x51, 0x3d, 0x7b, 0x60, 0x45, 0xe5,
743     0x66, 0x79, 0xb0, 0x32, 0xca, 0xd4, 0x5f, 0xb1,
744     0x82, 0x28, 0x9c, 0xa7, 0x6a, 0x88, 0xc0, 0x6d,
745     0x78, 0xc8, 0x5f, 0x3d, 0xd3, 0x80, 0x45, 0x90,
746     0x20, 0x5b, 0x73, 0xa7, 0x84, 0x24, 0x9a, 0x0a,
747     0x0c, 0x8b, 0xf2, 0xf2, 0x21, 0x45, 0xd1, 0x05,
748     0x21, 0x9b, 0x48, 0x0d, 0x74, 0x60, 0x7c, 0x02,
749     0xb8, 0xa6, 0xb6, 0xb4, 0x59, 0x25, 0x9e, 0x4f,
750     0xdf, 0xe2, 0xbd, 0xb4, 0xab, 0x22, 0x38, 0x01,
751     0x75, 0x35, 0x29, 0x1d, 0x7a, 0xc1, 0xab, 0xda,
752     0x66, 0xc4, 0xf6, 0xdc, 0xea, 0x9e, 0x5d, 0x0b,
753     0xf0, 0x5a, 0x93, 0x06, 0xf3, 0x33, 0xb0, 0x0e,
754     0x56, 0x34, 0x2f, 0x75, 0x53, 0x40, 0x21, 0x1a,
755     0xc2, 0x94, 0xac, 0x21, 0xa7, 0xc2, 0xb2, 0x67,
756     0x12, 0xb8, 0x79, 0x95, 0x1b, 0x2e, 0x23, 0xf6,
757     0x48, 0x7e, 0x4d, 0x39, 0x89, 0x9f, 0xe3, 0x74
758 };
759
760 const uint8_t ecdsa_test_2_d[] PROGMEM = {
761     0xeb, 0x8e, 0x9f, 0x04, 0x7d, 0xb5, 0x9a, 0x80,
762     0x34, 0x6f, 0xcd, 0xf1, 0xcc, 0x33, 0xbb, 0x78,
763     0xbe, 0xc6, 0xb8, 0x76, 0xaf, 0x9f, 0x4b, 0x69
764 };
765
766 const uint8_t ecdsa_test_2_k[] PROGMEM = {
767     0x8e, 0xd5, 0x00, 0x34, 0x08, 0x09, 0x60, 0x36,
768     0x2e, 0xfe, 0x16, 0xd0, 0x53, 0x37, 0xa2, 0xf5,
769     0x47, 0xfa, 0x11, 0xbc, 0xb1, 0xc2, 0xe8, 0x41
770 };
771
772 void test_sign1(void){
773     bigint_word_t d_w[sizeof(ecdsa_test_1_d)];
774     uint8_t rnd[sizeof(ecdsa_test_1_k)];
775     uint8_t *hash;
776     bigint_t d;
777     const hfdesc_t *hash_desc;
778     ecc_combi_point_t q;
779     ecdsa_signature_t sign;
780     ecdsa_ctx_t ctx;
781     uint8_t r;
782
783     putchar('\n');
784     d.wordv = d_w;
785     memcpy_P(rnd, ecdsa_test_1_k, sizeof(ecdsa_test_1_k));
786     memcpy_P(d_w, ecdsa_test_1_d, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
787     d.length_W = sizeof(ecdsa_test_1_d) / sizeof(bigint_word_t);
788     d.info = 0;
789     bigint_adjust(&d);
790
791     hash_desc = &sha1_desc; //hash_select();
792     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
793     if(hash == NULL){
794         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
795     }
796     hash_mem_P(hash_desc, hash, ecdsa_test_1_msg, sizeof(ecdsa_test_1_msg) * 8);
797     printf_P(PSTR("msg hash: "));
798     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
799     putchar('\n');
800
801     ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
802     ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
803     ctx.priv = &d;
804     ctx.curve = &nist_curve_p192;
805
806     printf("\n  d:  ");
807     bigint_print_hex(&d);
808     printf_P(PSTR("\n  Gx: "));
809     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
810     printf_P(PSTR("\n  Gy: "));
811     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
812
813     r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
814     if(r){
815         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
816     }
817     r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
818     if(r){
819         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
820     }
821
822     printf_P(PSTR("\n  Qx: "));
823     bigint_print_hex(&q.affine.x);
824     printf_P(PSTR("\n  Qy: "));
825     bigint_print_hex(&q.affine.y);
826     putchar('\n');
827     ctx.pub = &q.affine;
828
829     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
830
831     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
832     if(r){
833         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
834     }
835     printf_P(PSTR("  r: "));
836     bigint_print_hex(&sign.r);
837     printf_P(PSTR("\n  s: "));
838     bigint_print_hex(&sign.s);
839
840     free(hash);
841     ecdsa_signature_free(&sign);
842     ecc_chudnovsky_point_free(&q.chudnovsky);
843 }
844
845 void test_sign2(void){
846     bigint_word_t d_w[sizeof(ecdsa_test_2_d)];
847     uint8_t rnd[sizeof(ecdsa_test_2_k)];
848     uint8_t *hash;
849     bigint_t d;
850     const hfdesc_t *hash_desc;
851     ecc_combi_point_t q;
852     ecdsa_signature_t sign;
853     ecdsa_ctx_t ctx;
854     uint8_t r;
855
856     putchar('\n');
857     d.wordv = d_w;
858     memcpy_P(rnd, ecdsa_test_2_k, sizeof(ecdsa_test_2_k));
859     memcpy_P(d_w, ecdsa_test_2_d, sizeof(ecdsa_test_2_d) * sizeof(bigint_word_t));
860     d.length_W = sizeof(ecdsa_test_2_d) / sizeof(bigint_word_t);
861     d.info = 0;
862     bigint_adjust(&d);
863
864     hash_desc = &sha224_desc; //hash_select();
865     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
866     if(hash == NULL){
867         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
868     }
869     hash_mem_P(hash_desc, hash, ecdsa_test_2_msg, sizeof(ecdsa_test_1_msg) * 8);
870     printf_P(PSTR("msg hash: "));
871     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
872     putchar('\n');
873
874     ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
875     ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
876     ctx.priv = &d;
877     ctx.curve = &nist_curve_p192;
878
879     printf("\n  d:  ");
880     bigint_print_hex(&d);
881     printf_P(PSTR("\n  Gx: "));
882     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
883     printf_P(PSTR("\n  Gy: "));
884     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
885
886     r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
887     if(r){
888         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
889     }
890     r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
891     if(r){
892         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
893     }
894
895     printf_P(PSTR("\n  Qx: "));
896     bigint_print_hex(&q.affine.x);
897     printf_P(PSTR("\n  Qy: "));
898     bigint_print_hex(&q.affine.y);
899     putchar('\n');
900     ctx.pub = &q.affine;
901
902     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_2_d) * sizeof(bigint_word_t));
903
904     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
905     if(r){
906         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
907     }
908     printf_P(PSTR("  r: "));
909     bigint_print_hex(&sign.r);
910     printf_P(PSTR("\n  s: "));
911     bigint_print_hex(&sign.s);
912
913     free(hash);
914     ecdsa_signature_free(&sign);
915     ecc_chudnovsky_point_free(&q.chudnovsky);
916 }
917 /*****************************************************************************
918  *  main                                                                                                                                         *
919  *****************************************************************************/
920
921 const char echo_test_str[]               PROGMEM = "echo-test";
922 const char reset_prng_str[]              PROGMEM = "reset-prng";
923 const char quick_test_str[]              PROGMEM = "quick-test";
924 const char performance_reduce_str[]      PROGMEM = "performance_reduce";
925 const char performance_invert_str[]      PROGMEM = "performance_invert";
926 const char performance_multiply_str[]    PROGMEM = "performance_multiply";
927 const char genkey1_str[]                 PROGMEM = "genkey1";
928 const char genkey2_str[]                 PROGMEM = "genkey2";
929 const char genkey3_str[]                 PROGMEM = "genkey3";
930 const char genkey_str[]                  PROGMEM = "genkey";
931 const char testsign1_str[]               PROGMEM = "testsign1";
932 const char testsign2_str[]               PROGMEM = "testsign2";
933 const char square_str[]                  PROGMEM = "square";
934 const char echo_str[]                    PROGMEM = "echo";
935
936 const const cmdlist_entry_t cmdlist[] PROGMEM = {
937 //      { reset_prng_str,              NULL, reset_prng                           },
938 //      { quick_test_str,              NULL, quick_test                           },
939     { square_str,                  NULL, testrun_square                       },
940     { genkey_str,                  NULL, testrun_genkey                       },
941     { genkey1_str,                 NULL, testrun_genkey1                      },
942     { genkey2_str,                 NULL, testrun_genkey2                      },
943     { genkey3_str,                 NULL, testrun_genkey3                      },
944     { testsign1_str,               NULL, test_sign1                           },
945     { testsign2_str,               NULL, test_sign2                           },
946         { performance_reduce_str,      NULL, testrun_performance_reduce_bigint    },
947     { performance_invert_str,      NULL, testrun_performance_invert_bigint    },
948     { performance_multiply_str,    NULL, testrun_performance_multiply_bigint  },
949         { echo_str,                (void*)1, (void_fpt)echo_ctrl                  },
950         { NULL,                        NULL, NULL                                 }
951 };
952
953 int main (void){
954     int8_t r;
955     main_setup();
956     calibrateTimer();
957     for(;;){
958         welcome_msg(algo_name);
959         r = cmd_interface(cmdlist);
960         printf("r = %"PRId8"\n", r);
961         cli_putstr_P(PSTR("\r\nHello!\r\n"));
962         }
963 }