]> git.cryptolib.org Git - avr-crypto-lib.git/blob - test_src/main-ecdsa-test.c
7aa1e308ff1414e01d973e8a6f27dd9aa3c1b7d4
[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
497 void testrun_genkey3(void){
498     ecc_chudnovsky_point_t q;
499     ecc_affine_point_t qa;
500
501     uint8_t k_w[] = {
502         0xb2, 0x51, 0x97, 0xc3, 0x7c, 0x61, 0xf8, 0x8f,
503         0x19, 0x91, 0xcc, 0x67, 0xb5, 0x1c, 0x34, 0x23,
504         0xff, 0x13, 0xad, 0x14, 0x57, 0x43, 0x14, 0x7d
505     };
506
507     bigint_t k = {
508             .length_W = sizeof(k_w),
509             .wordv = k_w,
510             .info = 6
511     };
512
513     printf_P(PSTR("\n== testing key generation ==\n"));
514
515     if(ecc_chudnovsky_point_alloc(&q, 192)){
516         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
517         return;
518     }
519     if(ecc_affine_point_alloc(&qa, 192)){
520         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
521         return;
522     }
523
524     printf_P(PSTR("  k:  "));
525     bigint_print_hex(&k);
526     ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
527     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
528
529     printf_P(PSTR("\n  Qx: "));
530     bigint_print_hex(&qa.x);
531     printf_P(PSTR("\n  Qy: "));
532     bigint_print_hex(&qa.y);
533     puts("\n");
534 }
535
536 void testrun_genkey(void){
537     ecc_chudnovsky_point_t q;
538     ecc_affine_point_t qa;
539     uint32_t time;
540     bigint_t k;
541     uint8_t r;
542
543     printf_P(PSTR("\n== testing key generation ==\n"));
544
545     printf_P(PSTR("enter secret key d: "));
546     bigint_read_hex_echo(&k);
547     putchar('\n');
548
549     if(ecc_chudnovsky_point_alloc(&q, 192)){
550         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
551         return;
552     }
553     if(ecc_affine_point_alloc(&qa, 192)){
554         ecc_chudnovsky_point_free(&q);
555         printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
556         return;
557     }
558
559     printf_P(PSTR("(naf)  k:  "));
560     bigint_print_hex(&k);
561     startTimer(1);
562     START_TIMER;
563     r = ecc_chudnovsky_naf_multiplication(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
564     STOP_TIMER;
565     time = stopTimer();
566     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
567
568     printf_P(PSTR("\n  Qx: "));
569     bigint_print_hex(&qa.x);
570     printf_P(PSTR("\n  Qy: "));
571     bigint_print_hex(&qa.y);
572     printf_P(PSTR("\n time: %"PRIu32" cycles (r code: %"PRIu8")\n"), time, r);
573
574     printf_P(PSTR("(d&a)  k:  "));
575     bigint_print_hex(&k);
576     startTimer(1);
577     START_TIMER;
578     r = ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
579     STOP_TIMER;
580     time = stopTimer();
581     ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
582
583     printf_P(PSTR("\n  Qx: "));
584     bigint_print_hex(&qa.x);
585     printf_P(PSTR("\n  Qy: "));
586     bigint_print_hex(&qa.y);
587     printf_P(PSTR("\n time: %"PRIu32" cycles (r code: %"PRIu8")\n"), time, r);
588     free(k.wordv);
589     ecc_chudnovsky_point_free(&q);
590     ecc_affine_point_free(&qa);
591 }
592
593
594 #endif
595
596 const uint8_t ecdsa_test_1_msg[] PROGMEM = {
597 /*
598     0xcf, 0x71, 0xa0, 0xe4, 0xce, 0x59, 0x43, 0x11,
599     0x77, 0x88, 0x50, 0x87, 0x53, 0x78, 0xd0, 0xee,
600     0xa3, 0xc0, 0x32, 0xa4, 0xbc, 0xc0, 0xdc, 0x1c,
601     0xf2, 0x9d, 0x01, 0xb9, 0xc5, 0x10, 0x78, 0x9c,
602     0xd5, 0x2f, 0xc3, 0x8c, 0x74, 0xe6, 0xa4, 0x27,
603     0x87, 0xd0, 0xf2, 0x7c, 0xe2, 0x93, 0x20, 0x7a,
604     0xfd, 0xd0, 0x11, 0x7a, 0xcc, 0x71, 0xb9, 0x16,
605     0x63, 0x06, 0xce, 0x56, 0xf1, 0xa7, 0xf1, 0xc6,
606     0x0a, 0x9d, 0x68, 0x7d, 0x12, 0x5e, 0xb0, 0x7e,
607     0x26, 0xe5, 0x51, 0xdc, 0x14, 0x0e, 0x8a, 0x04,
608     0xaf, 0xa2, 0xa1, 0x6f, 0x98, 0xb5, 0x1b, 0xa9,
609     0x18, 0x96, 0xbf, 0x32, 0x0f, 0xd4, 0xd6, 0xf1,
610     0xa4, 0x4b, 0x46, 0xf3, 0x3d, 0xae, 0x39, 0xcc,
611     0x24, 0xf0, 0x4a, 0x5d, 0x86, 0x0c, 0xb1, 0x4f,
612     0x6b, 0x6e, 0x8a, 0x69, 0x73, 0xb4, 0x9f, 0xd2,
613     0xa7, 0xbc, 0xeb, 0x48, 0xd7, 0x48, 0xf7, 0xeb
614 */
615     0xeb, 0xf7, 0x48, 0xd7, 0x48, 0xeb, 0xbc, 0xa7,
616     0xd2, 0x9f, 0xb4, 0x73, 0x69, 0x8a, 0x6e, 0x6b,
617     0x4f, 0xb1, 0x0c, 0x86, 0x5d, 0x4a, 0xf0, 0x24,
618     0xcc, 0x39, 0xae, 0x3d, 0xf3, 0x46, 0x4b, 0xa4,
619     0xf1, 0xd6, 0xd4, 0x0f, 0x32, 0xbf, 0x96, 0x18,
620     0xa9, 0x1b, 0xb5, 0x98, 0x6f, 0xa1, 0xa2, 0xaf,
621     0x04, 0x8a, 0x0e, 0x14, 0xdc, 0x51, 0xe5, 0x26,
622     0x7e, 0xb0, 0x5e, 0x12, 0x7d, 0x68, 0x9d, 0x0a,
623     0xc6, 0xf1, 0xa7, 0xf1, 0x56, 0xce, 0x06, 0x63,
624     0x16, 0xb9, 0x71, 0xcc, 0x7a, 0x11, 0xd0, 0xfd,
625     0x7a, 0x20, 0x93, 0xe2, 0x7c, 0xf2, 0xd0, 0x87,
626     0x27, 0xa4, 0xe6, 0x74, 0x8c, 0xc3, 0x2f, 0xd5,
627     0x9c, 0x78, 0x10, 0xc5, 0xb9, 0x01, 0x9d, 0xf2,
628     0x1c, 0xdc, 0xc0, 0xbc, 0xa4, 0x32, 0xc0, 0xa3,
629     0xee, 0xd0, 0x78, 0x53, 0x87, 0x50, 0x88, 0x77,
630     0x11, 0x43, 0x59, 0xce, 0xe4, 0xa0, 0x71, 0xcf
631 };
632
633 const uint8_t ecdsa_test_1_d[] PROGMEM = {
634     0xf3, 0xd7, 0x60, 0xd6, 0x75, 0xf2, 0xcc, 0xeb,
635     0xf0, 0xd2, 0xfd, 0xb3, 0xb9, 0x41, 0x3f, 0xb0,
636     0xf8, 0x4f, 0x37, 0xd1, 0xb3, 0x37, 0x4f, 0xe1
637 };
638
639 const uint8_t ecdsa_test_1_k[] PROGMEM = {
640     0x25, 0x5f, 0x68, 0x89, 0xa2, 0x31, 0xbc, 0x57,
641     0x4d, 0x15, 0xc4, 0x12, 0xfb, 0x56, 0x45, 0x68,
642     0x83, 0x07, 0xa1, 0x43, 0x70, 0xbc, 0x0a, 0xcb
643 };
644
645 void hash_mem_P(const hfdesc_t *hfdesc, void *dest, const void *msg, uint16_t msg_len_b){
646     uint16_t blocksize = hfal_hash_getBlocksize(hfdesc);
647     uint8_t block[blocksize / 8];
648     hfgen_ctx_t ctx;
649     hfal_hash_init(hfdesc, &ctx);
650     while(msg_len_b > blocksize){
651         memcpy_P(block, msg, blocksize / 8);
652         msg = (uint8_t*)msg + blocksize / 8;
653         msg_len_b -= blocksize;
654         hfal_hash_nextBlock(&ctx, block);
655     }
656     memcpy_P(block, msg, (msg_len_b + 7) / 8);
657     hfal_hash_lastBlock(&ctx, block, msg_len_b);
658     hfal_hash_ctx2hash(dest,  &ctx);
659     hfal_hash_free(&ctx);
660 }
661
662 const uint8_t ecdsa_test_2_msg[] PROGMEM = {
663     0x66, 0xa2, 0x51, 0x3d, 0x7b, 0x60, 0x45, 0xe5,
664     0x66, 0x79, 0xb0, 0x32, 0xca, 0xd4, 0x5f, 0xb1,
665     0x82, 0x28, 0x9c, 0xa7, 0x6a, 0x88, 0xc0, 0x6d,
666     0x78, 0xc8, 0x5f, 0x3d, 0xd3, 0x80, 0x45, 0x90,
667     0x20, 0x5b, 0x73, 0xa7, 0x84, 0x24, 0x9a, 0x0a,
668     0x0c, 0x8b, 0xf2, 0xf2, 0x21, 0x45, 0xd1, 0x05,
669     0x21, 0x9b, 0x48, 0x0d, 0x74, 0x60, 0x7c, 0x02,
670     0xb8, 0xa6, 0xb6, 0xb4, 0x59, 0x25, 0x9e, 0x4f,
671     0xdf, 0xe2, 0xbd, 0xb4, 0xab, 0x22, 0x38, 0x01,
672     0x75, 0x35, 0x29, 0x1d, 0x7a, 0xc1, 0xab, 0xda,
673     0x66, 0xc4, 0xf6, 0xdc, 0xea, 0x9e, 0x5d, 0x0b,
674     0xf0, 0x5a, 0x93, 0x06, 0xf3, 0x33, 0xb0, 0x0e,
675     0x56, 0x34, 0x2f, 0x75, 0x53, 0x40, 0x21, 0x1a,
676     0xc2, 0x94, 0xac, 0x21, 0xa7, 0xc2, 0xb2, 0x67,
677     0x12, 0xb8, 0x79, 0x95, 0x1b, 0x2e, 0x23, 0xf6,
678     0x48, 0x7e, 0x4d, 0x39, 0x89, 0x9f, 0xe3, 0x74
679 };
680
681 const uint8_t ecdsa_test_2_d[] PROGMEM = {
682     0xeb, 0x8e, 0x9f, 0x04, 0x7d, 0xb5, 0x9a, 0x80,
683     0x34, 0x6f, 0xcd, 0xf1, 0xcc, 0x33, 0xbb, 0x78,
684     0xbe, 0xc6, 0xb8, 0x76, 0xaf, 0x9f, 0x4b, 0x69
685 };
686
687 const uint8_t ecdsa_test_2_k[] PROGMEM = {
688     0x8e, 0xd5, 0x00, 0x34, 0x08, 0x09, 0x60, 0x36,
689     0x2e, 0xfe, 0x16, 0xd0, 0x53, 0x37, 0xa2, 0xf5,
690     0x47, 0xfa, 0x11, 0xbc, 0xb1, 0xc2, 0xe8, 0x41
691 };
692
693 void test_sign1(void){
694     bigint_word_t d_w[sizeof(ecdsa_test_1_d)];
695     uint8_t rnd[sizeof(ecdsa_test_1_k)];
696     uint8_t *hash;
697     bigint_t d;
698     const hfdesc_t *hash_desc;
699     ecc_combi_point_t q;
700     ecdsa_signature_t sign;
701     ecdsa_ctx_t ctx;
702     uint8_t r;
703
704     putchar('\n');
705     d.wordv = d_w;
706     memcpy_P(rnd, ecdsa_test_1_k, sizeof(ecdsa_test_1_k));
707     memcpy_P(d_w, ecdsa_test_1_d, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
708     d.length_W = sizeof(ecdsa_test_1_d) / sizeof(bigint_word_t);
709     d.info = 0;
710     bigint_adjust(&d);
711
712     hash_desc = &sha1_desc; //hash_select();
713     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
714     if(hash == NULL){
715         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
716     }
717     hash_mem_P(hash_desc, hash, ecdsa_test_1_msg, sizeof(ecdsa_test_1_msg) * 8);
718     printf_P(PSTR("msg hash: "));
719     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
720     putchar('\n');
721
722     ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
723     ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
724     ctx.priv = &d;
725     ctx.curve = &nist_curve_p192;
726
727     printf("\n  d:  ");
728     bigint_print_hex(&d);
729     printf_P(PSTR("\n  Gx: "));
730     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
731     printf_P(PSTR("\n  Gy: "));
732     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
733
734     r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
735     if(r){
736         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
737     }
738     r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
739     if(r){
740         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
741     }
742
743     printf_P(PSTR("\n  Qx: "));
744     bigint_print_hex(&q.affine.x);
745     printf_P(PSTR("\n  Qy: "));
746     bigint_print_hex(&q.affine.y);
747     putchar('\n');
748     ctx.pub = &q.affine;
749
750     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
751
752     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
753     if(r){
754         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
755     }
756     printf_P(PSTR("  r: "));
757     bigint_print_hex(&sign.r);
758     printf_P(PSTR("\n  s: "));
759     bigint_print_hex(&sign.s);
760
761     free(hash);
762     ecdsa_signature_free(&sign);
763     ecc_chudnovsky_point_free(&q.chudnovsky);
764 }
765
766 void test_sign2(void){
767     bigint_word_t d_w[sizeof(ecdsa_test_2_d)];
768     uint8_t rnd[sizeof(ecdsa_test_2_k)];
769     uint8_t *hash;
770     bigint_t d;
771     const hfdesc_t *hash_desc;
772     ecc_combi_point_t q;
773     ecdsa_signature_t sign;
774     ecdsa_ctx_t ctx;
775     uint8_t r;
776
777     putchar('\n');
778     d.wordv = d_w;
779     memcpy_P(rnd, ecdsa_test_2_k, sizeof(ecdsa_test_2_k));
780     memcpy_P(d_w, ecdsa_test_2_d, sizeof(ecdsa_test_2_d) * sizeof(bigint_word_t));
781     d.length_W = sizeof(ecdsa_test_2_d) / sizeof(bigint_word_t);
782     d.info = 0;
783     bigint_adjust(&d);
784
785     hash_desc = &sha224_desc; //hash_select();
786     hash = malloc(hfal_hash_getHashsize(hash_desc) / 8);
787     if(hash == NULL){
788         printf_P(PSTR("DBG: XXX <%S %s %d>\n"), PSTR(__FILE__), __func__, __LINE__);
789     }
790     hash_mem_P(hash_desc, hash, ecdsa_test_2_msg, sizeof(ecdsa_test_1_msg) * 8);
791     printf_P(PSTR("msg hash: "));
792     cli_hexdump(hash, hfal_hash_getHashsize(hash_desc) / 8);
793     putchar('\n');
794
795     ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
796     ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
797     ctx.priv = &d;
798     ctx.curve = &nist_curve_p192;
799
800     printf("\n  d:  ");
801     bigint_print_hex(&d);
802     printf_P(PSTR("\n  Gx: "));
803     bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
804     printf_P(PSTR("\n  Gy: "));
805     bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
806
807     r = ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
808     if(r){
809         printf_P(PSTR("ERROR: ecc_chudnovsky_multiplication() returned: %"PRIu8"\n"), r);
810     }
811     r = ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
812     if(r){
813         printf_P(PSTR("ERROR: ecc_chudnovsky_to_affine_point() returned: %"PRIu8"\n"), r);
814     }
815
816     printf_P(PSTR("\n  Qx: "));
817     bigint_print_hex(&q.affine.x);
818     printf_P(PSTR("\n  Qy: "));
819     bigint_print_hex(&q.affine.y);
820     putchar('\n');
821     ctx.pub = &q.affine;
822
823     ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_2_d) * sizeof(bigint_word_t));
824
825     r = ecdsa_sign_hash(&sign, hash, hfal_hash_getHashsize(hash_desc) / 8, &ctx, rnd);
826     if(r){
827         printf_P(PSTR("ERROR: ecdsa_sign_message() returned: %"PRIu8"\n"), r);
828     }
829     printf_P(PSTR("  r: "));
830     bigint_print_hex(&sign.r);
831     printf_P(PSTR("\n  s: "));
832     bigint_print_hex(&sign.s);
833
834     free(hash);
835     ecdsa_signature_free(&sign);
836     ecc_chudnovsky_point_free(&q.chudnovsky);
837 }
838 /*****************************************************************************
839  *  main                                                                                                                                         *
840  *****************************************************************************/
841
842 const char echo_test_str[]               PROGMEM = "echo-test";
843 const char reset_prng_str[]              PROGMEM = "reset-prng";
844 const char quick_test_str[]              PROGMEM = "quick-test";
845 const char performance_reduce_str[]      PROGMEM = "performance_reduce";
846 const char performance_invert_str[]      PROGMEM = "performance_invert";
847 const char performance_multiply_str[]    PROGMEM = "performance_multiply";
848 const char genkey1_str[]                 PROGMEM = "genkey1";
849 const char genkey2_str[]                 PROGMEM = "genkey2";
850 const char genkey3_str[]                 PROGMEM = "genkey3";
851 const char genkey_str[]                  PROGMEM = "genkey";
852 const char testsign1_str[]               PROGMEM = "testsign1";
853 const char testsign2_str[]               PROGMEM = "testsign2";
854 const char square_str[]                  PROGMEM = "square";
855 const char echo_str[]                    PROGMEM = "echo";
856
857 const const cmdlist_entry_t cmdlist[] PROGMEM = {
858 //      { reset_prng_str,              NULL, reset_prng                           },
859 //      { quick_test_str,              NULL, quick_test                           },
860     { square_str,                  NULL, testrun_square                       },
861     { genkey_str,                  NULL, testrun_genkey                       },
862     { genkey1_str,                 NULL, testrun_genkey1                      },
863     { genkey2_str,                 NULL, testrun_genkey2                      },
864     { genkey3_str,                 NULL, testrun_genkey3                      },
865     { testsign1_str,               NULL, test_sign1                           },
866     { testsign2_str,               NULL, test_sign2                           },
867         { performance_reduce_str,      NULL, testrun_performance_reduce_bigint    },
868     { performance_invert_str,      NULL, testrun_performance_invert_bigint    },
869     { performance_multiply_str,    NULL, testrun_performance_multiply_bigint  },
870         { echo_str,                (void*)1, (void_fpt)echo_ctrl                  },
871         { NULL,                        NULL, NULL                                 }
872 };
873
874 int main (void){
875     int8_t r;
876     main_setup();
877     calibrateTimer();
878     for(;;){
879         welcome_msg(algo_name);
880         r = cmd_interface(cmdlist);
881         printf("r = %"PRId8"\n", r);
882         cli_putstr_P(PSTR("\r\nHello!\r\n"));
883         }
884 }