3 This file is part of the AVR-Crypto-Lib.
4 Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
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.
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.
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/>.
24 #include "main-test-common.h"
27 #include "noekeon_prng.h"
29 #include "bigint_io.h"
30 #include "nist_p192.h"
32 #include "ecdsa_sign.h"
34 #include "hfal_sha1.h"
35 #include "hfal_sha224.h"
36 #include "hfal_sha256.h"
37 #include "hfal_sha384.h"
38 #include "hfal_sha512.h"
40 #include "performance_test.h"
41 #include "hfal_sha1.h"
42 #include "base64_enc.h"
43 #include "base64_dec.h"
45 char* algo_name = "ECDSA";
47 /*****************************************************************************
48 * additional validation-functions *
49 *****************************************************************************/
51 uint8_t prng_get_byte(void){
55 void testrun_performance_invert_bigint(void){
56 printf_P(PSTR("\n=== performance measurement (invert) ===\n"));
60 bigint_word_t v_w[192 / BIGINT_WORD_SIZE];
61 bigint_word_t a_w[192 / BIGINT_WORD_SIZE];
66 for(j = 0; j < 32; ++j){
67 for(i = 0; i < 192 / BIGINT_WORD_SIZE; ++i){
68 ((uint8_t*)v_w)[i] = random();
70 v.length_W = 192 / BIGINT_WORD_SIZE;
74 for(i = 0; i < 16; ++i){
77 bigint_inverse(&a, &v, &nist_curve_p192_p);
87 printf_P(PSTR(" invert costs %"PRIu32" cycles\n"), (uint32_t)time);
90 void testrun_performance_multiply_bigint(void){
91 printf_P(PSTR("\n=== performance measurement (invert) ===\n"));
93 uint64_t time_a = 0, time_b = 0;
96 bigint_word_t v_w[192 * 2 / BIGINT_WORD_SIZE];
97 bigint_word_t a_w[192 / BIGINT_WORD_SIZE];
98 bigint_word_t b_w[192 / BIGINT_WORD_SIZE];
104 for(j = 0; j < 32; ++j){
105 for(i = 0; i < 192 / BIGINT_WORD_SIZE; ++i){
106 ((uint8_t*)a_w)[i] = random();
108 a.length_W = 192 / BIGINT_WORD_SIZE;
112 for(i = 0; i < 192 / BIGINT_WORD_SIZE; ++i){
113 ((uint8_t*)b_w)[i] = random();
115 b.length_W = 192 / BIGINT_WORD_SIZE;
119 for(i = 0; i < 16; ++i){
122 bigint_mul_u(&v,&a, &b);
129 bigint_reduce_p192(&v);
145 printf_P(PSTR(" multiply costs %7"PRIu32" cycles\n"), (uint32_t)time_a);
146 printf_P(PSTR(" multiply + reduce costs %7"PRIu32" cycles\n"), (uint32_t)time_b);
149 void testrun_performance_reduce_bigint(void){
150 printf_P(PSTR("\n=== performance measurement (reduce) ===\n"));
153 bigint_word_t v_w[192 * 2 / BIGINT_WORD_SIZE];
154 bigint_word_t a_w[192 * 2 / BIGINT_WORD_SIZE];
155 bigint_word_t b_w[192 * 2 / BIGINT_WORD_SIZE];
156 uint32_t time_a, time_b;
158 int16_t faster_percent;
160 for(j = 0; j < 32; ++j){
162 for(i = 0; i < 192 * 2 / BIGINT_WORD_SIZE; ++i){
163 ((uint8_t*)v_w)[i] = random();
165 v.length_W = 192 * 2 / BIGINT_WORD_SIZE;
170 // printf_P(PSTR("candidate:\n"));
171 // bigint_print_hex(&v);
176 // printf_P(PSTR("\n going to test optimized version: ...\n"));
179 for(i = 0; i < 16; ++i){
183 bigint_reduce_p192(&a);
185 time_a += stopTimer();
187 // printf_P(PSTR(" took: %"PRIu32" cycles\nresult:"), time);
188 // bigint_print_hex(&a);
191 // printf_P(PSTR("\n going to test not-optimized version: ...\n"));
194 for(i = 0; i < 16; ++i){
198 bigint_reduce(&b, &nist_curve_p192_p);
200 time_b += stopTimer();
202 // printf_P(PSTR(" took: %"PRIu32" cycles\nresult:"), time);
203 // bigint_print_hex(&b);
205 time_diff = time_b - time_a;
206 faster_percent = (time_diff * 100) / time_b;
208 printf_P(PSTR(" delta: %7"PRId32" (%3"PRId16"%%) :-"), time_diff, faster_percent);
209 if(bigint_cmp_u(&a, &b)){
210 printf_P(PSTR("(\n"));
212 printf_P(PSTR(")\n"));
218 uint8_t ecc_affine_point_alloc(ecc_affine_point_t *p, uint16_t length_b){
219 size_t len = (length_b + BIGINT_WORD_SIZE - 1)/ BIGINT_WORD_SIZE;
220 if (! (p->x.wordv = malloc(len))){
223 if (! (p->y.wordv = malloc(len))){
230 void ecc_affine_point_free(ecc_affine_point_t *p){
236 void testrun_square(void){
237 bigint_word_t a_w[] = {
238 0x82, 0x6f, 0x79, 0x39, 0x47, 0x06, 0x26, 0x9f,
239 0x4b, 0xe2, 0x15, 0x61, 0x6f, 0xa1, 0xd4, 0x0c,
240 0x1f, 0x24, 0x3a, 0xd4, 0xc2, 0x6d, 0xe8, 0xb6
243 bigint_word_t b_w[2 * 192 / BIGINT_WORD_SIZE];
247 a.length_W = sizeof(a_w);
254 printf_P(PSTR("\n a = "));
255 bigint_print_hex(&a);
256 bigint_square(&b, &a);
257 printf_P(PSTR("\n a^2 = "));
258 bigint_print_hex(&b);
259 bigint_reduce_p192(&b);
260 printf_P(PSTR("\n a^2 %% p = "));
261 bigint_print_hex(&b);
269 0: b3cfed2634516540528622e16c396c229e50bbdf773f8423
270 1: b6e86dc2d43a241f0cd4a16f6115e24b9f26064739796f82
271 2: 563f557e41731f268f82fe81c8fed959600dd46649ebeeee
272 3: 5e45169bd87475db886b8a7833bb0845f5b011a7ce0c1766
273 4: 4abf34c505a73308a804dcefacbd8f7b10b59fa6ac6421a
275 uint8_t test_point_x_w[] = {
276 0x23, 0x84, 0x3f, 0x77, 0xdf, 0xbb, 0x50, 0x9e,
277 0x22, 0x6c, 0x39, 0x6c, 0xe1, 0x22, 0x86, 0x52,
278 0x40, 0x65, 0x51, 0x34, 0x26, 0xed, 0xcf, 0xb3
281 uint8_t test_point_y_w[] = {
282 0x82, 0x6f, 0x79, 0x39, 0x47, 0x06, 0x26, 0x9f,
283 0x4b, 0xe2, 0x15, 0x61, 0x6f, 0xa1, 0xd4, 0x0c,
284 0x1f, 0x24, 0x3a, 0xd4, 0xc2, 0x6d, 0xe8, 0xb6
287 uint8_t test_point_z1_w[] = {
288 0xee, 0xee, 0xeb, 0x49, 0x66, 0xd4, 0x0d, 0x60,
289 0x59, 0xd9, 0xfe, 0xc8, 0x81, 0xfe, 0x82, 0x8f,
290 0x26, 0x1f, 0x73, 0x41, 0x7e, 0x55, 0x3f, 0x56
293 uint8_t test_point_z2_w[] = {
294 0x66, 0x17, 0x0c, 0xce, 0xa7, 0x11, 0xb0, 0xf5,
295 0x45, 0x08, 0xbb, 0x33, 0x78, 0x8a, 0x6b, 0x88,
296 0xdb, 0x75, 0x74, 0xd8, 0x9b, 0x16, 0x45, 0x5e
299 uint8_t test_point_z3_w[] = {
300 0x1a, 0x42, 0xc6, 0x6a, 0xfa, 0x59, 0x0b, 0xb1,
301 0xf7, 0xd8, 0xcb, 0xfa, 0xce, 0x4d, 0x80, 0x8a,
302 0x30, 0x73, 0x5a, 0x50, 0x4c, 0xf3, 0xab, 0x04
305 ecc_combi_point_t test_point = {
308 .wordv = test_point_x_w,
309 .length_W = sizeof(test_point_x_w),
313 .wordv = test_point_y_w,
314 .length_W = sizeof(test_point_y_w),
318 .wordv = test_point_z1_w,
319 .length_W = sizeof(test_point_z1_w),
323 .wordv = test_point_z2_w,
324 .length_W = sizeof(test_point_z2_w),
328 .wordv = test_point_z3_w,
329 .length_W = sizeof(test_point_z3_w),
334 void testrun_genkey2(void){
335 ecc_chudnovsky_point_t q;
336 ecc_affine_point_t qa;
338 printf_P(PSTR("\n== testing key generation (2) ==\n"));
340 if(ecc_chudnovsky_point_alloc(&q, 192)){
341 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
344 if(ecc_affine_point_alloc(&qa, 192)){
345 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
349 ecc_chudnovsky_point_print(&test_point.chudnovsky);
350 ecc_chudnovsky_to_affine_point(&qa, &test_point.chudnovsky, &nist_curve_p192);
351 printf_P(PSTR("\n Qx: "));
352 bigint_print_hex(&qa.x);
353 printf_P(PSTR("\n Qy: "));
354 bigint_print_hex(&qa.y);
355 printf_P(PSTR("\n================\n"));
356 ecc_chudnovsky_point_double_sp(&q, &test_point.chudnovsky, &nist_curve_p192);
357 ecc_chudnovsky_point_print(&q);
359 ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
361 printf_P(PSTR("\n Qx: "));
362 bigint_print_hex(&qa.x);
363 printf_P(PSTR("\n Qy: "));
364 bigint_print_hex(&qa.y);
369 void testrun_genkey1(void){
370 ecc_chudnovsky_point_t q;
371 ecc_affine_point_t qa;
374 // e5ce89a34adddf25ff3bf1ffe6803f57d0220de3118798ea
375 0xea, 0x98, 0x87, 0x11, 0xe3, 0x0d, 0x22, 0xd0,
376 0x57, 0x3f, 0x80, 0xe6, 0xff, 0xf1, 0x3b, 0xff,
377 0x25, 0xdf, 0xdd, 0x4a, 0xa3, 0x89, 0xce, 0xe5
381 .length_W = sizeof(k_w),
386 printf_P(PSTR("\n== testing key generation ==\n"));
388 if(ecc_chudnovsky_point_alloc(&q, 192)){
389 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
392 if(ecc_affine_point_alloc(&qa, 192)){
393 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
397 printf_P(PSTR(" k: "));
398 bigint_print_hex(&k);
399 ecc_chudnovsky_multiplication(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
400 ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
402 printf_P(PSTR("\n Qx: "));
403 bigint_print_hex(&qa.x);
404 printf_P(PSTR("\n Qy: "));
405 bigint_print_hex(&qa.y);
409 void testrun_genkey3(void){
410 ecc_chudnovsky_point_t q;
411 ecc_affine_point_t qa;
414 0xb2, 0x51, 0x97, 0xc3, 0x7c, 0x61, 0xf8, 0x8f,
415 0x19, 0x91, 0xcc, 0x67, 0xb5, 0x1c, 0x34, 0x23,
416 0xff, 0x13, 0xad, 0x14, 0x57, 0x43, 0x14, 0x7d
420 .length_W = sizeof(k_w),
425 printf_P(PSTR("\n== testing key generation ==\n"));
427 if(ecc_chudnovsky_point_alloc(&q, 192)){
428 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
431 if(ecc_affine_point_alloc(&qa, 192)){
432 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
436 printf_P(PSTR(" k: "));
437 bigint_print_hex(&k);
438 ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
439 ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
441 printf_P(PSTR("\n Qx: "));
442 bigint_print_hex(&qa.x);
443 printf_P(PSTR("\n Qy: "));
444 bigint_print_hex(&qa.y);
448 void testrun_genkey(void){
449 ecc_chudnovsky_point_t q;
450 ecc_affine_point_t qa;
454 printf_P(PSTR("\n== testing key generation ==\n"));
456 printf_P(PSTR("enter secret key d: "));
457 bigint_read_hex_echo(&k);
460 if(ecc_chudnovsky_point_alloc(&q, 192)){
461 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
464 if(ecc_affine_point_alloc(&qa, 192)){
465 ecc_chudnovsky_point_free(&q);
466 printf_P(PSTR("ERROR: OOM! <%s %s %d>\n"), __FILE__, __func__, __LINE__);
470 printf_P(PSTR("(naf) k: "));
471 bigint_print_hex(&k);
474 ecc_chudnovsky_naf_multiplication(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
477 ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
479 printf_P(PSTR("\n Qx: "));
480 bigint_print_hex(&qa.x);
481 printf_P(PSTR("\n Qy: "));
482 bigint_print_hex(&qa.y);
483 printf_P(PSTR("\n time: %"PRIu32" cycles\n"), time);
485 printf_P(PSTR("(d&a) k: "));
486 bigint_print_hex(&k);
489 ecc_chudnovsky_double_and_add(&q, &k, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
492 ecc_chudnovsky_to_affine_point(&qa, &q, &nist_curve_p192);
494 printf_P(PSTR("\n Qx: "));
495 bigint_print_hex(&qa.x);
496 printf_P(PSTR("\n Qy: "));
497 bigint_print_hex(&qa.y);
498 printf_P(PSTR("\n time: %"PRIu32" cycles\n"), time);
500 ecc_chudnovsky_point_free(&q);
501 ecc_affine_point_free(&qa);
507 const uint8_t ecdsa_test_1_msg[] PROGMEM = {
508 0xcf, 0x71, 0xa0, 0xe4, 0xce, 0x59, 0x43, 0x11,
509 0x77, 0x88, 0x50, 0x87, 0x53, 0x78, 0xd0, 0xee,
510 0xa3, 0xc0, 0x32, 0xa4, 0xbc, 0xc0, 0xdc, 0x1c,
511 0xf2, 0x9d, 0x01, 0xb9, 0xc5, 0x10, 0x78, 0x9c,
512 0xd5, 0x2f, 0xc3, 0x8c, 0x74, 0xe6, 0xa4, 0x27,
513 0x87, 0xd0, 0xf2, 0x7c, 0xe2, 0x93, 0x20, 0x7a,
514 0xfd, 0xd0, 0x11, 0x7a, 0xcc, 0x71, 0xb9, 0x16,
515 0x63, 0x06, 0xce, 0x56, 0xf1, 0xa7, 0xf1, 0xc6,
516 0x0a, 0x9d, 0x68, 0x7d, 0x12, 0x5e, 0xb0, 0x7e,
517 0x26, 0xe5, 0x51, 0xdc, 0x14, 0x0e, 0x8a, 0x04,
518 0xaf, 0xa2, 0xa1, 0x6f, 0x98, 0xb5, 0x1b, 0xa9,
519 0x18, 0x96, 0xbf, 0x32, 0x0f, 0xd4, 0xd6, 0xf1,
520 0xa4, 0x4b, 0x46, 0xf3, 0x3d, 0xae, 0x39, 0xcc,
521 0x24, 0xf0, 0x4a, 0x5d, 0x86, 0x0c, 0xb1, 0x4f,
522 0x6b, 0x6e, 0x8a, 0x69, 0x73, 0xb4, 0x9f, 0xd2,
523 0xa7, 0xbc, 0xeb, 0x48, 0xd7, 0x48, 0xf7, 0xeb
526 const uint8_t ecdsa_test_1_d[] PROGMEM = {
527 0xf3, 0xd7, 0x60, 0xd6, 0x75, 0xf2, 0xcc, 0xeb,
528 0xf0, 0xd2, 0xfd, 0xb3, 0xb9, 0x41, 0x3f, 0xb0,
529 0xf8, 0x4f, 0x37, 0xd1, 0xb3, 0x37, 0x4f, 0xe1
532 const uint8_t ecdsa_test_1_k[] PROGMEM = {
533 0x25, 0x5f, 0x68, 0x89, 0xa2, 0x31, 0xbc, 0x57,
534 0x4d, 0x15, 0xc4, 0x12, 0xfb, 0x56, 0x45, 0x68,
535 0x83, 0x07, 0xa1, 0x43, 0x70, 0xbc, 0x0a, 0xcb
538 void test_sign1(void){
539 bigint_word_t d_w[sizeof(ecdsa_test_1_d)];
540 uint8_t msg[sizeof(ecdsa_test_1_msg)];
541 uint8_t rnd[sizeof(ecdsa_test_1_k)];
544 ecdsa_signature_t sign;
547 memcpy_P(msg, ecdsa_test_1_msg, sizeof(ecdsa_test_1_msg));
548 memcpy_P(rnd, ecdsa_test_1_k, sizeof(ecdsa_test_1_k));
549 memcpy_P(d_w, ecdsa_test_1_d, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
550 d.length_W = sizeof(ecdsa_test_1_d) / sizeof(bigint_word_t);
554 ecc_chudnovsky_point_alloc(&q.chudnovsky, nist_curve_p192_p.length_W * sizeof(bigint_word_t));
555 ctx.basepoint = &nist_curve_p192_basepoint.chudnovsky;
557 ctx.curve = &nist_curve_p192;
560 bigint_print_hex(&d);
561 printf_P(PSTR("\n Gx: "));
562 bigint_print_hex(&nist_curve_p192_basepoint.affine.x);
563 printf_P(PSTR("\n Gy: "));
564 bigint_print_hex(&nist_curve_p192_basepoint.affine.y);
566 ecc_chudnovsky_multiplication(&q.chudnovsky, &d, &nist_curve_p192_basepoint.chudnovsky, &nist_curve_p192);
567 ecc_chudnovsky_to_affine_point(&q.affine, &q.chudnovsky, &nist_curve_p192);
568 printf_P(PSTR("\n Qx: "));
569 bigint_print_hex(&q.affine.x);
570 printf_P(PSTR("\n Qy: "));
571 bigint_print_hex(&q.affine.y);
575 ecdsa_signature_alloc(&sign, sizeof(ecdsa_test_1_d) * sizeof(bigint_word_t));
577 ecdsa_sign_message(&sign, msg, sizeof(msg) * 8, &sha1_desc, &ctx, rnd);
579 printf_P(PSTR("\n r: "));
580 bigint_print_hex(&sign.r);
581 printf_P(PSTR("\n r: "));
582 bigint_print_hex(&sign.s);
585 ecdsa_signature_free(&sign);
586 ecc_chudnovsky_point_free(&q.chudnovsky);
589 /*****************************************************************************
591 *****************************************************************************/
593 const char echo_test_str[] PROGMEM = "echo-test";
594 const char reset_prng_str[] PROGMEM = "reset-prng";
595 const char quick_test_str[] PROGMEM = "quick-test";
596 const char performance_reduce_str[] PROGMEM = "performance_reduce";
597 const char performance_invert_str[] PROGMEM = "performance_invert";
598 const char performance_multiply_str[] PROGMEM = "performance_multiply";
599 const char genkey1_str[] PROGMEM = "genkey1";
600 const char genkey2_str[] PROGMEM = "genkey2";
601 const char genkey3_str[] PROGMEM = "genkey3";
602 const char genkey_str[] PROGMEM = "genkey";
603 const char testsign1_str[] PROGMEM = "testsign1";
604 const char square_str[] PROGMEM = "square";
605 const char echo_str[] PROGMEM = "echo";
607 const const cmdlist_entry_t cmdlist[] PROGMEM = {
608 // { reset_prng_str, NULL, reset_prng },
609 // { quick_test_str, NULL, quick_test },
610 { square_str, NULL, testrun_square },
611 { genkey_str, NULL, testrun_genkey },
612 { genkey1_str, NULL, testrun_genkey1 },
613 { genkey2_str, NULL, testrun_genkey2 },
614 { genkey3_str, NULL, testrun_genkey3 },
615 { testsign1_str, NULL, test_sign1 },
616 { performance_reduce_str, NULL, testrun_performance_reduce_bigint },
617 { performance_invert_str, NULL, testrun_performance_invert_bigint },
618 { performance_multiply_str, NULL, testrun_performance_multiply_bigint },
619 { echo_str, (void*)1, (void_fpt)echo_ctrl },
628 welcome_msg(algo_name);
629 r = cmd_interface(cmdlist);
630 printf("r = %"PRId8"\n", r);
631 cli_putstr_P(PSTR("\r\nHello!\r\n"));