3 This file is part of the AVR-Crypto-Lib.
4 Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
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/>.
23 * \license GPLv3 or later
27 #include <avr/pgmspace.h>
32 #include "blockcipher_descriptor.h"
33 #include "bcal-basic.h"
34 #include "bcal-cmac.h"
36 #include "string-extras.h"
48 # include <util/delay.h>
51 bcdesc_t* cmacvs_algo=NULL;
52 bcdesc_t** cmacvs_algolist=NULL;
54 void cmacvs_listalgos(void){
59 cli_putstr_P(PSTR("\r\nthe following algorithms are available:\r\n"));
60 while(option<='z' && (t=(bcdesc_t*)pgm_read_word(&(cmacvs_algolist[i])))){
62 cli_putc((t==cmacvs_algo)?'*':' ');
64 cli_putstr_P(PSTR(":\t"));
65 cli_putstr_P((void*)(pgm_read_word(&(t->name))));
66 cli_putstr_P(PSTR("\r\n"));
71 void cmacvs_setalgo(char *param){
72 param = strstrip(param);
73 if(param[1]=='\0'){ /* single letter specified */
74 uint8_t i,option = param[0]-'a';
77 cli_putstr_P(PSTR("\r\nERROR: cmacvs_algolist not set!"));
80 for(i=0; i<=option; ++i){
81 if((void*)pgm_read_word(&(cmacvs_algolist[i]))==NULL){
82 cli_putstr_P(PSTR("\r\nERROR: invalid selection!"));
86 cmacvs_algo=(bcdesc_t*)pgm_read_word(&(cmacvs_algolist[option]));
87 } else { /* name specifyed */
90 while((t=(bcdesc_t*)pgm_read_word(&(cmacvs_algolist[i]))) &&
91 strcasecmp_P(param, (void*)pgm_read_word(&(t->name))))
96 cli_putstr_P(PSTR("\r\nERROR: could not find \""));
98 cli_putstr_P(PSTR("\"!"));
105 uint16_t buffersize_B;
112 static cmacvs_ctx_t cmacvs_ctx;
114 uint8_t buffer_add(char c){
116 if(cmacvs_ctx.buffer_idx==cmacvs_ctx.buffersize_B){
117 bcal_cmac_nextBlock(&(cmacvs_ctx.ctx), cmacvs_ctx.buffer);
119 cmacvs_ctx.buffer_idx=0;
120 cmacvs_ctx.in_byte=0;
122 memset(cmacvs_ctx.buffer, 0, cmacvs_ctx.buffersize_B);
124 if(c>='0' && c<='9'){
127 c &= (uint8_t)~('a' ^ 'A');
128 if(c>='A' && c<='F'){
134 t=cmacvs_ctx.buffer[cmacvs_ctx.buffer_idx];
135 if(cmacvs_ctx.in_byte){
137 cmacvs_ctx.buffer[cmacvs_ctx.buffer_idx]=t;
138 cmacvs_ctx.buffer_idx++;
139 cmacvs_ctx.in_byte = 0;
142 cmacvs_ctx.buffer[cmacvs_ctx.buffer_idx]=t;
143 cmacvs_ctx.in_byte = 1;
148 int32_t getValue_P(PGM_P key){
153 memset(instr, 0, 21);
154 cli_getsn_cecho(instr, 20);
155 str2 = strstrip(instr);
156 if(!strncasecmp_P(str2, key, strlen_P(key))){
157 while(*str2 && *str2!='=')
162 }while(*str2 && !isdigit(*str2));
163 val=(uint32_t)strtoul(str2, NULL, 10);
167 if(!strncasecmp_P(str2, PSTR("EXIT"), 4)){
168 cli_putstr_P(PSTR("\r\n got exit ..."));
176 uint8_t getKey(void *key_buffer, uint8_t klen_B){
179 memset(key_buffer, 0x00, klen_B);
181 c = cli_getc_cecho();
182 }while((c|('a'^'A'))!='k');
184 c = cli_getc_cecho();
185 }while((c|('a'^'A'))!='e');
187 c = cli_getc_cecho();
188 }while((c|('a'^'A'))!='y');
190 c = cli_getc_cecho();
195 c = cli_getc_cecho();
196 if(c>='0' && c<='9'){
200 if(c>='a' && c<='f'){
208 ((uint8_t*)key_buffer)[i/2] |= v;
216 uint8_t getMac(void *mac_buffer, uint8_t mlen_B){
219 memset(mac_buffer, 0x00, mlen_B);
221 c = cli_getc_cecho();
222 }while((c|('a'^'A'))!='m');
224 c = cli_getc_cecho();
225 }while((c|('a'^'A'))!='a');
227 c = cli_getc_cecho();
228 }while((c|('a'^'A'))!='c');
230 c = cli_getc_cecho();
235 c = cli_getc_cecho();
236 if(c>='0' && c<='9'){
240 if(c>='a' && c<='f'){
248 ((uint8_t*)mac_buffer)[i/2] |= v;
256 void cmacvs_test1(void){ /* Gen tests */
257 int32_t klen, mlen, tlen;
258 int32_t expect_input=0;
261 cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
265 cmacvs_ctx.buffersize_B=pgm_read_word(&(cmacvs_algo->blocksize_b))/8;
266 uint8_t tag[cmacvs_ctx.buffersize_B];
267 uint8_t buffer[cmacvs_ctx.buffersize_B+5];
268 cmacvs_ctx.buffer = buffer;
269 cli_putstr_P(PSTR("\r\nbuffer_size = 0x"));
270 cli_hexdump_rev(&(cmacvs_ctx.buffersize_B), 2);
271 cli_putstr_P(PSTR(" bytes"));
273 cmacvs_ctx.blocks = 0;
274 memset(buffer, 0, cmacvs_ctx.buffersize_B);
275 klen = getValue_P(PSTR("Klen"));
279 mlen = getValue_P(PSTR("Mlen"));
283 tlen = getValue_P(PSTR("Tlen"));
287 uint8_t key_buffer[klen];
289 cli_putstr_P(PSTR("\r\nKLen == "));
290 cli_hexdump_rev(&klen, 4);
291 cli_putstr_P(PSTR("\r\nMLen == "));
292 cli_hexdump_rev(&mlen, 4);
293 cli_putstr_P(PSTR("\r\nTLen == "));
294 cli_hexdump_rev(&tlen, 4);
296 getKey(key_buffer, klen);
303 cli_putstr_P(PSTR("\r\nexpected_input == "));
304 cli_hexdump_rev(&expect_input, 4);
306 cli_putstr_P(PSTR("\r\nexpected_input == 0 !!!"));
310 cli_putstr_P(PSTR("\r\n CMAC init"));
311 cli_putstr_P(PSTR("\r\n (2) expected_input == "));
312 cli_hexdump_rev(&expect_input, 4);
314 ret = bcal_cmac_init(cmacvs_algo, key_buffer, klen*8, &(cmacvs_ctx.ctx));
316 cli_putstr_P(PSTR("\r\n bcal_cmac_init returned with: "));
317 cli_hexdump(&ret, 1);
321 cli_putstr_P(PSTR("\r\n (3) expected_input == "));
322 cli_hexdump_rev(&expect_input, 4);
323 cli_putstr_P(PSTR("\r\n"));
325 while((c=cli_getc_cecho())!='M' && c!='m'){
327 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
329 cli_putstr_P(PSTR("]!\r\n"));
330 bcal_cmac_free(&(cmacvs_ctx.ctx));
334 if((c=cli_getc_cecho())!='s' && c!='S'){
335 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
336 bcal_cmac_free(&(cmacvs_ctx.ctx));
339 if((c=cli_getc_cecho())!='g' && c!='G'){
340 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
341 bcal_cmac_free(&(cmacvs_ctx.ctx));
344 while((c=cli_getc_cecho())!='='){
346 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
347 bcal_cmac_free(&(cmacvs_ctx.ctx));
352 cli_putstr_P(PSTR("\r\nparsing started"));
354 cmacvs_ctx.buffer_idx = 0;
355 cmacvs_ctx.in_byte = 0;
356 cmacvs_ctx.blocks = 0;
357 while(expect_input>0){
360 cli_putstr_P(PSTR("\r\n\t("));
361 cli_hexdump_rev(&expect_input, 4);
362 cli_putstr_P(PSTR(") "));
365 if(buffer_add(c)==0){
368 if(!isblank((uint16_t)c)){
369 cli_putstr_P(PSTR("\r\nERROR: wrong input (5) ("));
371 cli_putstr_P(PSTR(")!\r\n"));
372 bcal_cmac_free(&(cmacvs_ctx.ctx));
378 cli_putstr_P(PSTR("\r\nBuffer-A:"));
379 cli_hexdump_block(buffer, cmacvs_ctx.buffersize_B, 5, 8);
381 cli_putstr_P(PSTR("\r\n starting finalisation"));
382 cli_putstr_P(PSTR("\r\n\tblocks == "));
383 cli_hexdump_rev(&(cmacvs_ctx.blocks),4);
384 cli_putstr_P(PSTR("\r\n\tbuffer_idx == "));
385 cli_hexdump_rev(&(cmacvs_ctx.buffer_idx),2);
386 cli_putstr_P(PSTR("\r\n\tin_byte == "));
387 cli_hexdump_rev(&(cmacvs_ctx.in_byte),1);
390 cli_putstr_P(PSTR("\r\n starting last block"));
391 cli_putstr_P(PSTR("\r\n\tlength == "));
392 cli_hexdump_rev(&mlen,4);
393 cli_putstr_P(PSTR("\r\n\tbuffersize_B == "));
394 cli_hexdump_rev(&(cmacvs_ctx.buffersize_B),2);
395 uint16_t temp=(mlen-cmacvs_ctx.blocks*cmacvs_ctx.buffersize_B)*8;
396 cli_putstr_P(PSTR("\r\n\t (temp) == "));
397 cli_hexdump_rev(&temp,2);
400 uint16_t temp=(mlen-cmacvs_ctx.blocks*cmacvs_ctx.buffersize_B)*8;
401 bcal_cmac_lastBlock( &(cmacvs_ctx.ctx), buffer, /* be aware of freaking compilers!!! */
402 // length-(cmacvs_ctx.blocks)*((cmacvs_ctx.buffersize_B)*8));
405 cli_putstr_P(PSTR("\r\n starting ctx2cmac"));
408 bcal_cmac_ctx2mac(tag, tlen*8, &(cmacvs_ctx.ctx));
410 cli_putstr_P(PSTR("\r\n starting cmac free"));
412 bcal_cmac_free(&(cmacvs_ctx.ctx));
413 cli_putstr_P(PSTR("\r\n Mac = "));
414 cli_hexdump(tag, tlen);
420 void cmacvs_test2(void){ /* Ver tests */
421 int32_t klen, mlen, tlen;
422 int32_t expect_input=0;
425 cli_putstr_P(PSTR("\r\nERROR: select algorithm first!"));
429 cmacvs_ctx.buffersize_B=pgm_read_word(&(cmacvs_algo->blocksize_b))/8;
430 uint8_t tag[cmacvs_ctx.buffersize_B];
431 uint8_t tag_ref[cmacvs_ctx.buffersize_B];
432 uint8_t buffer[cmacvs_ctx.buffersize_B+5];
433 cmacvs_ctx.buffer = buffer;
434 cli_putstr_P(PSTR("\r\nbuffer_size = 0x"));
435 cli_hexdump_rev(&(cmacvs_ctx.buffersize_B), 2);
436 cli_putstr_P(PSTR(" bytes"));
438 cmacvs_ctx.blocks = 0;
439 memset(buffer, 0, cmacvs_ctx.buffersize_B);
440 klen = getValue_P(PSTR("Klen"));
444 mlen = getValue_P(PSTR("Mlen"));
448 tlen = getValue_P(PSTR("Tlen"));
452 uint8_t key_buffer[klen];
454 cli_putstr_P(PSTR("\r\nKLen == "));
455 cli_hexdump_rev(&klen, 4);
456 cli_putstr_P(PSTR("\r\nMLen == "));
457 cli_hexdump_rev(&mlen, 4);
458 cli_putstr_P(PSTR("\r\nTLen == "));
459 cli_hexdump_rev(&tlen, 4);
461 getKey(key_buffer, klen);
468 cli_putstr_P(PSTR("\r\nexpected_input == "));
469 cli_hexdump_rev(&expect_input, 4);
471 cli_putstr_P(PSTR("\r\nexpected_input == 0 !!!"));
475 cli_putstr_P(PSTR("\r\n CMAC init"));
476 cli_putstr_P(PSTR("\r\n (2) expected_input == "));
477 cli_hexdump_rev(&expect_input, 4);
479 ret = bcal_cmac_init(cmacvs_algo, key_buffer, klen*8, &(cmacvs_ctx.ctx));
481 cli_putstr_P(PSTR("\r\n bcal_cmac_init returned with: "));
482 cli_hexdump(&ret, 1);
486 cli_putstr_P(PSTR("\r\n (3) expected_input == "));
487 cli_hexdump_rev(&expect_input, 4);
488 cli_putstr_P(PSTR("\r\n"));
490 while((c=cli_getc_cecho())!='M' && c!='m'){
492 cli_putstr_P(PSTR("\r\nERROR: wrong input (1) [0x"));
494 cli_putstr_P(PSTR("]!\r\n"));
495 bcal_cmac_free(&(cmacvs_ctx.ctx));
499 if((c=cli_getc_cecho())!='s' && c!='S'){
500 cli_putstr_P(PSTR("\r\nERROR: wrong input (2)!\r\n"));
501 bcal_cmac_free(&(cmacvs_ctx.ctx));
504 if((c=cli_getc_cecho())!='g' && c!='G'){
505 cli_putstr_P(PSTR("\r\nERROR: wrong input (3)!\r\n"));
506 bcal_cmac_free(&(cmacvs_ctx.ctx));
509 while((c=cli_getc_cecho())!='='){
511 cli_putstr_P(PSTR("\r\nERROR: wrong input (4)!\r\n"));
512 bcal_cmac_free(&(cmacvs_ctx.ctx));
517 cli_putstr_P(PSTR("\r\nparsing started"));
519 cmacvs_ctx.buffer_idx = 0;
520 cmacvs_ctx.in_byte = 0;
521 cmacvs_ctx.blocks = 0;
522 while(expect_input>0){
525 cli_putstr_P(PSTR("\r\n\t("));
526 cli_hexdump_rev(&expect_input, 4);
527 cli_putstr_P(PSTR(") "));
530 if(buffer_add(c)==0){
533 if(!isblank((uint16_t)c)){
534 cli_putstr_P(PSTR("\r\nERROR: wrong input (5) ("));
536 cli_putstr_P(PSTR(")!\r\n"));
537 bcal_cmac_free(&(cmacvs_ctx.ctx));
543 cli_putstr_P(PSTR("\r\nBuffer-A:"));
544 cli_hexdump_block(buffer, cmacvs_ctx.buffersize_B, 5, 8);
546 cli_putstr_P(PSTR("\r\n starting finalisation"));
547 cli_putstr_P(PSTR("\r\n\tblocks == "));
548 cli_hexdump_rev(&(cmacvs_ctx.blocks),4);
549 cli_putstr_P(PSTR("\r\n\tbuffer_idx == "));
550 cli_hexdump_rev(&(cmacvs_ctx.buffer_idx),2);
551 cli_putstr_P(PSTR("\r\n\tin_byte == "));
552 cli_hexdump_rev(&(cmacvs_ctx.in_byte),1);
555 cli_putstr_P(PSTR("\r\n starting last block"));
556 cli_putstr_P(PSTR("\r\n\tlength == "));
557 cli_hexdump_rev(&mlen,4);
558 cli_putstr_P(PSTR("\r\n\tbuffersize_B == "));
559 cli_hexdump_rev(&(cmacvs_ctx.buffersize_B),2);
560 uint16_t temp=(mlen-cmacvs_ctx.blocks*cmacvs_ctx.buffersize_B)*8;
561 cli_putstr_P(PSTR("\r\n\t (temp) == "));
562 cli_hexdump_rev(&temp,2);
565 uint16_t temp=(mlen-cmacvs_ctx.blocks*cmacvs_ctx.buffersize_B)*8;
566 bcal_cmac_lastBlock( &(cmacvs_ctx.ctx), buffer, /* be aware of freaking compilers!!! */
567 // length-(cmacvs_ctx.blocks)*((cmacvs_ctx.buffersize_B)*8));
570 cli_putstr_P(PSTR("\r\n starting ctx2cmac"));
573 bcal_cmac_ctx2mac(tag, tlen*8, &(cmacvs_ctx.ctx));
575 cli_putstr_P(PSTR("\r\n starting cmac free"));
577 bcal_cmac_free(&(cmacvs_ctx.ctx));
578 cli_putstr_P(PSTR("\r\n Mac = "));
579 cli_hexdump(tag, tlen);
580 getMac(tag_ref, tlen);
581 if(memcmp(tag, tag_ref, tlen)){
582 cli_putstr_P(PSTR("\r\n Result = F"));
584 cli_putstr_P(PSTR("\r\n Result = P"));