From 73f474e8fea34667e788ff4ec24de552e9d1d9e8 Mon Sep 17 00:00:00 2001 From: bg Date: Tue, 3 Apr 2012 20:16:38 +0200 Subject: [PATCH] updated bigint & rsa --- arm-makefile.inc | 6 +- bigint/bigint.c | 276 +++++++++++++----------- bigint/bigint.h | 2 +- bigint/bigint_io.c | 24 +-- host/bigint_test.rb | 300 +++++++++++++++++--------- host/rsa_oaep_check.rb | 107 ++++++++-- host/rsa_pkcs15_check.rb | 390 ++++++++++++++++++++++++++++++++++ rsa/rsa_basic.c | 15 ++ rsa/rsa_oaep.c | 1 - rsa/rsa_pkcs15.c | 12 +- test_src/main-bigint-test.c | 4 +- test_src/main-rsa_oaep-test.c | 148 +++++++++---- 12 files changed, 981 insertions(+), 304 deletions(-) create mode 100644 host/rsa_pkcs15_check.rb diff --git a/arm-makefile.inc b/arm-makefile.inc index b073161..5daff93 100644 --- a/arm-makefile.inc +++ b/arm-makefile.inc @@ -1,7 +1,7 @@ -TOOLCHAIN = arm-none-eabi-# +TOOLCHAIN = arm-elf-# MCU_TARGET = cortex-m3 MCU_OPTS = -mthumb -OPTIMIZE = -O0 -fomit-frame-pointer +OPTIMIZE = -Os -fomit-frame-pointer DEBUG = -gdwarf-2 WARNING = -pedantic -Wall -Wstrict-prototypes -Werror DEFS = -D$(call uc, $(subst -,_,$(MCU_TARGET))) @@ -16,7 +16,7 @@ TEST_DIR = test/# BIN_DIR = bin/# TESTSRC_DIR = test_src/# ERASECMD = -TESTPORT = /dev/ttyUSB0 +TESTPORT = /dev/ttyUSB1 TESTPORTBAUDR = 115200 TESTLOG_DIR = testlog/# TESTPREFIX = nessie-# diff --git a/bigint/bigint.c b/bigint/bigint.c index 307b1e4..a7a2b59 100644 --- a/bigint/bigint.c +++ b/bigint/bigint.c @@ -33,11 +33,10 @@ #include "bigint.h" #include -#define DEBUG 1 +#define DEBUG 0 #if DEBUG #include "cli.h" -#include "uart_lowlevel.h" #include "bigint_io.h" #endif @@ -54,9 +53,9 @@ #define SET_NEG(a) (a)->info |= BIGINT_NEG_MASK #define SET_POS(a) (a)->info &= ~BIGINT_NEG_MASK #define XCHG(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0) -#define XCHG_PTR(a,b) do{ a = (void*)(((uint32_t)(a)) ^ ((uint32_t)(b))); \ - b = (void*)(((uint32_t)(a)) ^ ((uint32_t)(b))); \ - a = (void*)(((uint32_t)(a)) ^ ((uint32_t)(b)));}while(0) +#define XCHG_PTR(a,b) do{ a = (void*)(((bigint_ptr_int_t)(a)) ^ ((bigint_ptr_int_t)(b))); \ + b = (void*)(((bigint_ptr_int_t)(a)) ^ ((bigint_ptr_int_t)(b))); \ + a = (void*)(((bigint_ptr_int_t)(a)) ^ ((bigint_ptr_int_t)(b)));}while(0) #define GET_SIGN(a) ((a)->info&BIGINT_NEG_MASK) @@ -72,7 +71,7 @@ void bigint_adjust(bigint_t* a){ bigint_word_t t; uint8_t i = BIGINT_WORD_SIZE-1; t = a->wordv[a->length_B-1]; - while((t&(1<<(BIGINT_WORD_SIZE-1)))==0 && i){ + while((t&(1L<<(BIGINT_WORD_SIZE-1)))==0 && i){ t<<=1; i--; } @@ -155,7 +154,9 @@ void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ dest->wordv[i] = (bigint_word_t)t; t>>=BIGINT_WORD_SIZE; } - dest->wordv[i++] = (bigint_word_t)t; + if(t){ + dest->wordv[i++] = (bigint_word_t)t; + } dest->length_B = i; bigint_adjust(dest); } @@ -164,9 +165,56 @@ void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ /* this should be implemented in assembly */ void bigint_add_scale_u(bigint_t* dest, const bigint_t* a, uint16_t scale){ - uint16_t i,j=0; + if(a->length_B == 0){ + return; + } + if(scale == 0){ + bigint_add_u(dest, dest, a); + return; + } + bigint_t x; +#if BIGINT_WORD_SIZE == 8 + memset(dest->wordv + dest->length_B, 0, MAX(dest->length_B, a->length_B + scale) - dest->length_B); + x.wordv = dest->wordv + scale; + x.length_B = dest->length_B - scale; + if((int16_t)x.length_B < 0){ + x.length_B = 0; + x.info = 0; + } else { + x.info = dest->info; + } + bigint_add_u(&x, &x, a); + dest->length_B = x.length_B + scale; + dest->info = 0; + bigint_adjust(dest); +#else + bigint_t s; + uint16_t word_shift = scale / sizeof(bigint_word_t), byte_shift = scale % sizeof(bigint_word_t); + bigint_word_t bv[a->length_B + 1]; + s.wordv = bv; + bv[0] = bv[a->length_B] = 0; + memcpy((uint8_t*)bv + byte_shift, a->wordv, a->length_B * sizeof(bigint_word_t)); + s.length_B = a->length_B + 1; + bigint_adjust(&s); + memset(dest->wordv + dest->length_B, 0, (MAX(dest->length_B, s.length_B + word_shift) - dest->length_B) * sizeof(bigint_word_t)); + x.wordv = dest->wordv + word_shift; + x.length_B = dest->length_B - word_shift; + if((int16_t)x.length_B < 0){ + x.length_B = 0; + x.info = 0; + }else{ + x.info = dest->info; + } + bigint_add_u(&x, &x, &s); + dest->length_B = x.length_B + word_shift; + dest->info = 0; + bigint_adjust(dest); +#endif + + +/* uint16_t i,j=0; uint16_t scale_w; - uint32_t *dst; + bigint_word_t *dst; bigint_wordplus_t t=0; scale_w = (scale+sizeof(bigint_word_t)-1)/sizeof(bigint_word_t); if(scale>dest->length_B*sizeof(bigint_word_t)){ @@ -194,6 +242,7 @@ void bigint_add_scale_u(bigint_t* dest, const bigint_t* a, uint16_t scale){ dest->length_B = i; } bigint_adjust(dest); + */ } /******************************************************************************/ @@ -224,34 +273,24 @@ void bigint_sub_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ if(r<0){ bigint_sub_u(dest, b, a); SET_NEG(dest); - }else{ - for(i=0; iwordv[i]; + return; + } + for(i=0; iwordv[i]; + if(iwordv[i]; - t -= borrow; - if(t<0){ - borrow = 1; - dest->wordv[i]=(bigint_word_t)t; - }else{ - borrow = 0; - dest->wordv[i]=(bigint_word_t)t; - } } - for(;iwordv[i] - borrow; - if(t<0){ - borrow = 1; - dest->wordv[i]=(bigint_word_t)t; - }else{ - borrow = 0; - dest->wordv[i]=(bigint_word_t)t; - } - + t -= borrow; + dest->wordv[i]=(bigint_word_t)t; + if(t<0){ + borrow = 1; + }else{ + borrow = 0; } - SET_POS(dest); - dest->length_B = i; - bigint_adjust(dest); } + SET_POS(dest); + dest->length_B = i; + bigint_adjust(dest); } /******************************************************************************/ @@ -269,8 +308,8 @@ int8_t bigint_cmp_u(const bigint_t* a, const bigint_t* b){ uint16_t i; i = a->length_B-1; do{ - if(a->wordv[i]!=b->wordv[i]){ - if(a->wordv[i]>b->wordv[i]){ + if(a->wordv[i] != b->wordv[i]){ + if(a->wordv[i] > b->wordv[i]){ return 1; }else{ return -1; @@ -469,78 +508,80 @@ void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ if(a->length_B!=1){ XCHG_PTR(a,b); } - bigint_wordplus_t i, t=0; + bigint_wordplus_t t=0; + uint16_t i; bigint_word_t x = a->wordv[0]; - for(i=0; ilength_B; ++i){ + for(i=0; i < b->length_B; ++i){ t += ((bigint_wordplus_t)b->wordv[i])*((bigint_wordplus_t)x); dest->wordv[i] = (bigint_word_t)t; t>>=BIGINT_WORD_SIZE; } dest->wordv[i] = (bigint_word_t)t; - dest->length_B=i+1; + dest->length_B = i+1; + dest->info = 0; bigint_adjust(dest); return; } - if(a->length_B<=4/sizeof(bigint_word_t) && b->length_B<=4/sizeof(bigint_word_t)){ + if(a->length_B * sizeof(bigint_word_t) <= 4 && b->length_B * sizeof(bigint_word_t) <= 4){ uint32_t p=0, q=0; uint64_t r; memcpy(&p, a->wordv, a->length_B*sizeof(bigint_word_t)); memcpy(&q, b->wordv, b->length_B*sizeof(bigint_word_t)); - r = (uint64_t)p*(uint64_t)q; - memcpy(dest->wordv, &r, (a->length_B+b->length_B)*sizeof(bigint_word_t)); - dest->length_B = a->length_B+b->length_B; + r = (uint64_t)p * (uint64_t)q; + memcpy(dest->wordv, &r, (dest->length_B = a->length_B + b->length_B)*sizeof(bigint_word_t)); bigint_adjust(dest); return; } bigint_set_zero(dest); /* split a in xh & xl; split b in yh & yl */ - uint16_t n; - n=(MAX(a->length_B, b->length_B)+1)/2; + const uint16_t n = (MAX(a->length_B, b->length_B)+1)/2; bigint_t xl, xh, yl, yh; xl.wordv = a->wordv; yl.wordv = b->wordv; if(a->length_B<=n){ - xh.info=0; - xh.length_B = 0; + bigint_set_zero(&xh); xl.length_B = a->length_B; - xl.info = 0; + xl.info = a->info; }else{ xl.length_B=n; xl.info = 0; bigint_adjust(&xl); - xh.wordv = a->wordv+n; + xh.wordv = &(a->wordv[n]); xh.length_B = a->length_B-n; - xh.info = 0; + xh.info = a->info; } if(b->length_B<=n){ - yh.info=0; - yh.length_B = 0; + bigint_set_zero(&yh); yl.length_B = b->length_B; yl.info = b->info; }else{ yl.length_B=n; yl.info = 0; bigint_adjust(&yl); - yh.wordv = b->wordv+n; + yh.wordv = &(b->wordv[n]); yh.length_B = b->length_B-n; - yh.info = 0; + yh.info = b->info; } /* now we have split up a and b */ + /* remember we want to do: + * x*y = (xh*yh)*b**2n + ((xh+xl)*(yh+yl) - xh*yh - xl*yl)*b**n + yh*yl + * 5 9 2 4 3 7 5 6 1 8 1 + */ bigint_word_t tmp_b[2*n+2], m_b[2*(n+1)]; bigint_t tmp, tmp2, m; tmp.wordv = tmp_b; - tmp2.wordv = tmp_b+n+1; + tmp2.wordv = &(tmp_b[n+1]); m.wordv = m_b; - bigint_mul_u(dest, &xl, &yl); /* dest <= xl*yl */ - bigint_add_u(&tmp2, &xh, &xl); /* tmp2 <= xh+xl */ - bigint_add_u(&tmp, &yh, &yl); /* tmp <= yh+yl */ - bigint_mul_u(&m, &tmp2, &tmp); /* m <= tmp2*tmp */ - bigint_mul_u(&tmp, &xh, &yh); /* h <= xh*yh */ - bigint_sub_u(&m, &m, dest); /* m <= m-dest */ - bigint_sub_u(&m, &m, &tmp); /* m <= m-h */ - bigint_add_scale_u(dest, &m, n*sizeof(bigint_word_t)); - bigint_add_scale_u(dest, &tmp, 2*n*sizeof(bigint_word_t)); + bigint_mul_u(dest, &xl, &yl); /* 1: dest <= xl*yl */ + bigint_add_u(&tmp2, &xh, &xl); /* 2: tmp2 <= xh+xl */ + bigint_add_u(&tmp, &yh, &yl); /* 3: tmp <= yh+yl */ + bigint_mul_u(&m, &tmp2, &tmp); /* 4: m <= tmp2*tmp */ + bigint_mul_u(&tmp, &xh, &yh); /* 5: h <= xh*yh */ + bigint_sub_u(&m, &m, dest); /* 6: m <= m-dest */ + bigint_sub_u(&m, &m, &tmp); /* 7: m <= m-h */ + bigint_add_scale_u(dest, &m, n*sizeof(bigint_word_t)); /* 8: dest <= dest+m**n*/ + bigint_add_scale_u(dest, &tmp, 2*n*sizeof(bigint_word_t)); /* 9: dest <= dest+tmp**(2*n) */ } /******************************************************************************/ @@ -600,9 +641,15 @@ void bigint_square(bigint_t* dest, const bigint_t* a){ bigint_word_t buffer[2*n+1]; xl.wordv = a->wordv; xl.length_B = n; + xl.info = 0; xh.wordv = &(a->wordv[n]); xh.length_B = a->length_B-n; + xh.info = 0; + bigint_adjust(&xl); + bigint_adjust(&xh); tmp.wordv = buffer; +/* (xh * b**n + xl)**2 = xh**2 * b**2n + 2 * xh * xl * b**n + xl**2 */ + // cli_putstr("\r\nDBG (a): xl: "); bigint_print_hex(&xl); // cli_putstr("\r\nDBG (b): xh: "); bigint_print_hex(&xh); bigint_square(dest, &xl); @@ -622,51 +669,28 @@ void bigint_square(bigint_t* dest, const bigint_t* a){ /******************************************************************************/ void bigint_sub_u_bitscale(bigint_t* a, const bigint_t* b, uint16_t bitscale){ - bigint_t tmp; - bigint_word_t tmp_b[b->length_B+4]; - uint16_t i,j,word_shift=bitscale/(8*sizeof(bigint_word_t)); - uint8_t borrow=0; - bigint_wordplus_signed_t t; + bigint_t tmp, x; + bigint_word_t tmp_b[b->length_B + 1]; + const uint16_t word_shift = bitscale / BIGINT_WORD_SIZE; - if(a->length_B < b->length_B+word_shift){ + if(a->length_B < b->length_B + word_shift){ +#if DEBUG cli_putstr("\r\nDBG: *bang*\r\n"); +#endif bigint_set_zero(a); return; } tmp.wordv = tmp_b; bigint_copy(&tmp, b); - bigint_shiftleft(&tmp, bitscale&(BIGINT_WORD_SIZE-1)); -// cli_putstr("\r\nDBG(sub_ub.0) tmp_shift = "); bigint_print_hex(&tmp); - for(j=0,i=word_shift; iwordv[i]; - t -= tmp.wordv[j]; - t -= borrow; - a->wordv[i] = (bigint_word_t)t; - if(t<0){ - borrow = 1; - }else{ - borrow = 0; - } - } - while(borrow){ - if(i+1 > a->length_B){ - // char str[16]; - cli_putstr("\r\nDBG: *boom* a->length_B = "); - cli_hexdump_rev(&a->length_B, 2); - cli_putstr(" b->length_B = "); - cli_hexdump_rev(&b->length_B, 2); - cli_putstr(" bitscale = "); - cli_hexdump_rev(&bitscale, 2); - bigint_set_zero(a); - return; - } - a->wordv[i] -= borrow; - if(a->wordv[i] != (1LL<info; + x.wordv = &(a->wordv[word_shift]); + x.length_B = a->length_B - word_shift; + + bigint_sub_u(&x, &x, &tmp); bigint_adjust(a); + return; } /******************************************************************************/ @@ -674,8 +698,9 @@ void bigint_sub_u_bitscale(bigint_t* a, const bigint_t* b, uint16_t bitscale){ void bigint_reduce(bigint_t* a, const bigint_t* r){ // bigint_adjust((bigint_t*)r); uint8_t rfbs = GET_FBS(r); - -// cli_putstr("\r\nDBG: (a) = "); bigint_print_hex(a); +#if DEBUG + cli_putstr("\r\nDBG: (a) = "); bigint_print_hex(a); +#endif if(r->length_B==0 || a->length_B==0){ return; } @@ -709,10 +734,10 @@ void bigint_reduce(bigint_t* a, const bigint_t* r){ bigint_sub_u_bitscale(a, r, shift); // cli_putstr("\r\nDBG: (1) = "); bigint_print_hex(a); } - while((GET_FBS(a) > rfbs+1) && (a->length_B == r->length_B)){ + while((GET_FBS(a) > rfbs) && (a->length_B == r->length_B)){ shift = GET_FBS(a)-rfbs-1; // cli_putstr("\r\nDBG: (q) shift = "); cli_hexdump_rev(&shift, 2); - bigint_sub_u_bitscale(a, r, GET_FBS(a)-rfbs-1); + bigint_sub_u_bitscale(a, r, shift); // cli_putstr("\r\nDBG: (2) = "); bigint_print_hex(a); } while(bigint_cmp_u(a,r)>=0){ @@ -734,7 +759,7 @@ void bigint_expmod_u(bigint_t* dest, const bigint_t* a, const bigint_t* exp, con } bigint_t res, base; - bigint_word_t t, base_b[MAX(a->length_B,r->length_B*2)], res_b[r->length_B*2]; + bigint_word_t t, base_b[MAX(a->length_B,r->length_B)], res_b[r->length_B*2]; uint16_t i; uint8_t j; // uint16_t *xaddr = &i; @@ -749,33 +774,34 @@ void bigint_expmod_u(bigint_t* dest, const bigint_t* a, const bigint_t* exp, con res.wordv[0]=1; res.length_B=1; res.info = 0; -// cli_putstr("\r\nadjust "); bigint_adjust(&res); -// cli_putstr("\r\nexpmod "); - for(i=0; i+1length_B; ++i){ - t=exp->wordv[i]; - for(j=0; jlength_B == 0){ + bigint_copy(dest, &res); + return; + } + uint8_t flag = 0; + t=exp->wordv[exp->length_B - 1]; + for(i=exp->length_B; i > 0; --i){ + t = exp->wordv[i - 1]; + for(j=BIGINT_WORD_SIZE; j > 0; --j){ + if(!flag){ + if(t & (1<<(BIGINT_WORD_SIZE-1))){ + flag = 1; + } + } + if(flag){ + bigint_square(&res, &res); bigint_reduce(&res, r); + if(t & (1<<(BIGINT_WORD_SIZE-1))){ + bigint_mul_u(&res, &res, &base); + bigint_reduce(&res, r); + } } - bigint_square(&base, &base); - bigint_reduce(&base, r); - t>>=1; + t<<=1; } } - t=exp->wordv[i]; // cli_putc('+'); - while(t){ - if(t&1){ - bigint_mul_u(&res, &res, &base); - bigint_reduce(&res, r); - } - bigint_square(&base, &base); - bigint_reduce(&base, r); - t>>=1; - } SET_POS(&res); bigint_copy(dest, &res); } diff --git a/bigint/bigint.h b/bigint/bigint.h index f385811..71b86f5 100644 --- a/bigint/bigint.h +++ b/bigint/bigint.h @@ -43,7 +43,7 @@ typedef struct{ bigint_word_t *wordv; /* word vector, pointing to the LSB */ }bigint_t; - +typedef uint32_t bigint_ptr_int_t; /******************************************************************************/ diff --git a/bigint/bigint_io.c b/bigint/bigint_io.c index bf3fca7..d22f763 100644 --- a/bigint/bigint_io.c +++ b/bigint/bigint_io.c @@ -43,7 +43,7 @@ void bigint_print_hex(const bigint_t* a){ uint8_t print_zero=0; uint8_t *p,x,y; p = (uint8_t*)&(a->wordv[a->length_B-1])+sizeof(bigint_word_t)-1; - for(idx=a->length_B*sizeof(bigint_word_t); idx>0; --idx){ + for(idx = a->length_B * sizeof(bigint_word_t); idx > 0; --idx){ x = *p >> 4; y = *p & 0xf; if(x!=0 || print_zero!=0){ @@ -97,24 +97,24 @@ static uint16_t read_byte(void){ uint8_t bigint_read_hex_echo(bigint_t* a){ uint16_t allocated=0; uint8_t shift4=0; - uint16_t t; + uint16_t t, idx = 0; a->length_B = 0; a->wordv = NULL; a->info = 0; for(;;){ - if(allocated-a->length_B < 1){ + if(allocated - idx < 1){ bigint_word_t *p; - p = realloc(a->wordv, allocated+=BLOCKSIZE); + p = realloc(a->wordv, allocated += BLOCKSIZE); if(p==NULL){ cli_putstr("\r\nERROR: Out of memory!"); free(a->wordv); return 0xff; } - memset((uint8_t*)p+allocated-BLOCKSIZE, 0, BLOCKSIZE); + memset((uint8_t*)p + allocated - BLOCKSIZE, 0, BLOCKSIZE); a->wordv=p; } t = read_byte(); - if(a->length_B==0){ + if(idx==0){ if(t&0x0400){ /* got minus */ a->info |= BIGINT_NEG_MASK; @@ -128,11 +128,11 @@ uint8_t bigint_read_hex_echo(bigint_t* a){ } } if(t<=0x00ff){ - ((uint8_t*)(a->wordv))[a->length_B++] = (uint8_t)t; + ((uint8_t*)(a->wordv))[idx++] = (uint8_t)t; }else{ if(t&0x0200){ shift4 = 1; - ((uint8_t*)(a->wordv))[a->length_B++] = (uint8_t)((t&0x0f)<<4); + ((uint8_t*)(a->wordv))[idx++] = (uint8_t)((t&0x0f)<<4); } break; } @@ -140,20 +140,18 @@ uint8_t bigint_read_hex_echo(bigint_t* a){ /* we have to reverse the byte array */ uint8_t tmp; uint8_t *p, *q; + a->length_B = (idx + sizeof(bigint_word_t)-1)/sizeof(bigint_word_t); p = (uint8_t*)(a->wordv); - q = (uint8_t*)a->wordv+a->length_B-1; + q = (uint8_t*)a->wordv + idx - 1; while(q>p){ tmp = *p; *p = *q; *q = tmp; p++; q--; } - a->length_B = (a->length_B+sizeof(bigint_word_t)-1)/sizeof(bigint_word_t); + bigint_adjust(a); if(shift4){ - bigint_adjust(a); bigint_shiftright(a, 4); - }else{ - bigint_adjust(a); } return 0; } diff --git a/host/bigint_test.rb b/host/bigint_test.rb index 7a756a1..d942b37 100644 --- a/host/bigint_test.rb +++ b/host/bigint_test.rb @@ -23,7 +23,7 @@ $debug = false require 'rubygems' require 'serialport' require 'getopt/std' -require 'ftools' +require 'fileutils' require 'date' $buffer_size = 0 $conffile_check = Hash.new @@ -37,7 +37,7 @@ def readconfigfile(fname, conf) return conf if $conffile_check[fname]==1 $conffile_check[fname]=1 section = "default" - if not File.exists?(fname) + if ! File.exists?(fname) return conf end file = File.open(fname, "r") @@ -49,7 +49,7 @@ def readconfigfile(fname, conf) conf[m[1]] = Hash.new next end - next if not /=/.match(line) + next if ! /=/.match(line) m=/[\s]*([^\s]*)[\s]*=[\s]*([^\s]*)/.match(line) if m[1]=="include" Dir.glob(m[2]){ |fn| conf = readconfigfile(fn, conf) } @@ -127,6 +127,9 @@ end ################################################################################ def init_system(test_prog) + begin + line = $sp.gets() + end while line!=nil $sp.print("echo off \r") print("DBG i: " + "echo off \r"+"\n") if $debug sleep 0.1 @@ -135,6 +138,29 @@ def init_system(test_prog) sleep 1 end +################################################################################ +# wait_for_prompt # +################################################################################ + +def wait_for_prompt(prompt) + prompt = /[\s]*#{prompt}[\s]*/ if(prompt.class == String) + start_time = Time.now.to_i + acc = '' + begin + line = $sp.gets() + puts("DBG got (#{__LINE__}): "+line) if $debug && line + line = "" if line==nil + if /^(Error:|Crypto-VS).*/.match(line) + puts line + return false + end + if (Time.now.to_i- start_time) > $max_timeout + return false + end + acc += line + end while ! m=prompt.match(acc) + return m +end ################################################################################ # screen_progress # @@ -161,7 +187,7 @@ def add_test(a,b) puts line return false end - end while not /[\s]*enter a:[\s]*/.match(line) + end while ! /[\s]*enter a:[\s]*/.match(line) $sp.print(a.to_s(16)+" ") begin line = $sp.gets() @@ -171,7 +197,7 @@ def add_test(a,b) puts line return false end - end while not /[\s]*enter b:[\s]*/.match(line) + end while ! /[\s]*enter b:[\s]*/.match(line) $sp.print(b.to_s(16)+" ") begin line = $sp.gets() @@ -181,7 +207,7 @@ def add_test(a,b) puts line return false end - end while not m=/[\s]*([-]?[0-9a-fA-F]*)[\s]+\+[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) + end while ! m=/[\s]*([-]?[0-9a-fA-F]*)[\s]+\+[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) a_ = m[1].to_i(16) b_ = m[2].to_i(16) c_ = m[3].to_i(16) @@ -210,7 +236,7 @@ def mul_test(a,b) puts line return false end - end while not /[\s]*enter a:[\s]*/.match(line) + end while ! /[\s]*enter a:[\s]*/.match(line) $sp.print(a.to_s(16)+" ") begin line = $sp.gets() @@ -220,7 +246,7 @@ def mul_test(a,b) puts line return false end - end while not /[\s]*enter b:[\s]*/.match(line) + end while ! /[\s]*enter b:[\s]*/.match(line) $sp.print(b.to_s(16)+" ") begin line = $sp.gets() @@ -230,7 +256,7 @@ def mul_test(a,b) puts line return false end - end while not m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]+\*[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) + end while ! m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]+\*[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) a_ = m[1].to_i(16) b_ = m[2].to_i(16) c_ = m[3].to_i(16) @@ -249,58 +275,43 @@ end ################################################################################ # add_scale_test # ################################################################################ +def add_scale_test_dummy(a, b, scale) + should = a + (b<<(8*scale)) + printf("[dummy] %s + %s <<8*%04x = %s\n",a.to_s(16), b.to_s(16), scale, should.to_s(16)) +end def add_scale_test(a, b, scale) - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got: "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not /[\s]*enter a:[\s]*/.match(line) + m = wait_for_prompt("enter a:") + return false if !m + puts("DBG put (#{__LINE__}): "+a.to_s(16)+" ") if $debug $sp.print(a.to_s(16)+" ") - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got: "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not /[\s]*enter b:[\s]*/.match(line) + m = wait_for_prompt("enter b:") + return false if !m + puts("DBG put (#{__LINE__}): "+b.to_s(16)+" ") if $debug $sp.print(b.to_s(16)+" ") - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got: "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not /[\s]*enter scale:[\s]*/.match(line) - $sp.print(scale.to_s(16)+"\n") - begin - line = $sp.gets() - line = "" if line==nil - puts("DBG got: "+line) if $debug - if /^Error:.*/.match(line) - puts line - return false - end - end while not m=/[\s]*([-]?[0-9a-fA-F]*)[\s]+\+[\s]+([+-]?[0-9a-fA-F]*)[\s]*<<8\*[\s]*([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) + m = wait_for_prompt("enter scale:") + return false if !m + puts("DBG put (#{__LINE__}): "+scale.to_s(10)+" ") if $debug + $sp.print(scale.to_s(10)+"\r") + should = a + (b<<(8*scale)) + m = wait_for_prompt(/[\s]*([-]?[0-9a-fA-F]+)[\s]+\+[\s]+([+-]?[0-9a-fA-F]+)[\s]*<<8\*[\s]*([+-]?[0-9a-fA-F]+)[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/) + if !m + $logfile.printf("[fail (CRASH)]:") + $logfile.printf(" ; should %s + %s << 8*%s = %s\n", a.to_s(16), b.to_s(16), scale.to_s(16), should.to_s(16)) + return false + end + line = m[0] a_ = m[1].to_i(16) b_ = m[2].to_i(16) s_ = m[3].to_i(16) c_ = m[4].to_i(16) line.chomp! - if(a_== a && b_ == b && c_ == (a+b)) + if(a_== a && b_ == b && s_ == scale && c_ == should ) $logfile.printf("[pass]: %s\n", line) return true else - $logfile.printf("[fail (%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (c_==a+b)?"":"c",line) - $logfile.printf(" ; should %s + %s = %s\n", a.to_s(16), b.to_s(16), (a+b).to_s(16)) + $logfile.printf("[fail (%s%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (scale==s_)?"":"s",(c_==should)?"":"c",line) + $logfile.printf(" ; should %s + %s << 8*%s = %s\n", a.to_s(16), b.to_s(16), scale.to_s(16), should.to_s(16)) return false end return false @@ -319,7 +330,7 @@ def square_test(a) puts line return false end - end while not /[\s]*enter a:[\s]*/.match(line) + end while ! /[\s]*enter a:[\s]*/.match(line) $sp.print(a.to_s(16)+" ") begin line = $sp.gets() @@ -329,7 +340,7 @@ def square_test(a) puts line return false end - end while not m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]*\*\*2[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) + end while ! m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]*\*\*2[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line) a_ = m[1].to_i(16) c_ = m[2].to_i(16) line.chomp! @@ -357,7 +368,7 @@ def reduce_test(a,b) puts line return false end - end while not /[\s]*enter a:[\s]*/.match(line) + end while ! /[\s]*enter a:[\s]*/.match(line) $sp.print(a.to_s(16)+" ") begin line = $sp.gets() @@ -367,18 +378,19 @@ def reduce_test(a,b) puts line return false end - end while not /[\s]*enter b:[\s]*/.match(line) + end while ! /[\s]*enter b:[\s]*/.match(line) $sp.print(b.to_s(16)+" ") line='' begin - line = $sp.gets() - line = '' if line==nil + line_tmp = $sp.gets() + line_tmp = '' if line_tmp==nil + line += line_tmp puts("DBG got: "+line) if $debug if /^Error:.*/.match(line) puts line return false end - end while not m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]+%[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/.match(line) + end while ! m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]+%[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/.match(line) a_ = m[1].to_i(16) b_ = m[2].to_i(16) c_ = m[3].to_i(16) @@ -407,7 +419,7 @@ def expmod_test(a,b,c) puts line return false end - end while not /[\s]*enter a:[\s]*/.match(line) + end while ! /[\s]*enter a:[\s]*/.match(line) $sp.print(a.to_s(16)+" ") begin line = $sp.gets() @@ -417,7 +429,7 @@ def expmod_test(a,b,c) puts line return false end - end while not /[\s]*enter b:[\s]*/.match(line) + end while ! /[\s]*enter b:[\s]*/.match(line) $sp.print(b.to_s(16)+" ") begin line = $sp.gets() @@ -427,18 +439,19 @@ def expmod_test(a,b,c) puts line return false end - end while not /[\s]*enter c:[\s]*/.match(line) + end while ! /[\s]*enter c:[\s]*/.match(line) $sp.print(c.to_s(16)+" ") line='' begin - line = $sp.gets() - line = '' if line==nil + line_tmp = $sp.gets() + line_tmp = '' if line_tmp==nil + line += line_tmp puts("DBG got: "+line) if $debug if /^Error:.*/.match(line) puts line return false end - end while not m=/[\s]*([+-]?[0-9a-fA-F]*)\*\*([+-]?[0-9a-fA-F]*)[\s]+%[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/.match(line) + end while ! m=/[\s]*([+-]?[0-9a-fA-F]*)\*\*([+-]?[0-9a-fA-F]*)[\s]+%[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/.match(line) a_ = m[1].to_i(16) b_ = m[2].to_i(16) c_ = m[3].to_i(16) @@ -468,7 +481,7 @@ def gcdext_test(a,b) puts line return false end - end while not /[\s]*enter a:[\s]*/.match(line) + end while ! /[\s]*enter a:[\s]*/.match(line) $sp.print(a.to_s(16)+" ") begin line = $sp.gets() @@ -478,18 +491,20 @@ def gcdext_test(a,b) puts line return false end - end while not /[\s]*enter b:[\s]*/.match(line) + end while ! /[\s]*enter b:[\s]*/.match(line) $sp.print(b.to_s(16)+" ") line='' begin - line = $sp.gets() - line = '' if line==nil + line_tmp = $sp.gets() + line_tmp = '' if line_tmp==nil + line = '' if line.end_with?('\n') + line += line_tmp puts("DBG got: "+line) if $debug if /^Error:.*/.match(line) puts line return false end - end while not m=/gcdext\([\s]*([+-]?[0-9a-fA-F]*)[\s]*,[\s]*([+-]?[0-9a-fA-F]*)[\s]*\)[\s]*=>[\s]*a[\s]*=[\s]*([+-]?[0-9a-fA-F]+);[\s]*b[\s]*=[\s]*([+-]?[0-9a-fA-F]+);[\s]*gcd[\s]*=[\s]*([+-]?[0-9a-fA-F]+)/.match(line) + end while ! m=/gcdext\([\s]*([+-]?[0-9a-fA-F]*)[\s]*,[\s]*([+-]?[0-9a-fA-F]*)[\s]*\)[\s]*=> a = ([+-]?[0-9a-fA-F]+); b = ([+-]?[0-9a-fA-F]+); gcd = ([+-]?[0-9a-fA-F]+)/.match(line) a_ = m[1].to_i(16) b_ = m[2].to_i(16) c_ = m[3].to_i(16) @@ -548,6 +563,80 @@ def run_test_add(skip=0) end while length_a_B<4096/8 end +################################################################################ +# run_test_add_scale # +################################################################################ + +def run_test_add_scale(skip=0) + length_a_B = skip+1 + length_b_B = skip+1 + begin + $size = length_a_B + (0..4).each do |i| + scales = [0, 300] + 16.times { scales << rand(301) } + scales.sort! + scales.each do |scale| + a = rand(256**length_a_B) + b = rand(256**length_a_B) + v = add_scale_test(a, b, scale) + screen_progress(v) + v = add_scale_test(b, a, scale) + screen_progress(v) + end + end + (0..4).each do |i| + scales = [0, 300] + 16.times { scales << rand(301) } + scales.sort! + scales.each do |scale| + b_size = rand(length_b_B+1)+1 + a = rand(256**length_a_B) + b = rand(256**b_size) + v = add_scale_test(a, b, scale) + screen_progress(v) + v = add_scale_test(b, a, scale) + screen_progress(v) + end + end + length_a_B += 10 + length_b_B += 10 + end while length_a_B<4096/8 +end + +def run_test_add_scale_dummy(skip=0) + length_a_B = skip+1 + length_b_B = skip+1 + begin + $size = length_a_B + (0..4).each do |i| + scales = [0, 300] + 16.times { scales << rand(301) } + scales.sort! + scales.each do |scale| + a = rand(256**length_a_B) + b = rand(256**length_a_B) + v = add_scale_test_dummy(a, b, scale) + v = add_scale_test_dummy(b, a, scale) + end + end + (0..4).each do |i| + scales = [0, 300] + 16.times { scales << rand(301) } + scales.sort! + scales.each do |scale| + b_size = rand(length_b_B+1) + a = rand(256**length_a_B) + b = rand(256**b_size) + v = add_scale_test_dummy(a, b, scale) + v = add_scale_test_dummy(b, a, scale) + end + end + length_a_B += 10 + length_b_B += 10 + end while length_a_B<4096/8 +end + ################################################################################ # run_test_mul # ################################################################################ @@ -667,7 +756,7 @@ def run_test_gcdext(skip=0) begin $size = length_a_B (0..16).each do |i| - a = rand(256**length_a_B)+1 + a = rand(256**length_a_B) b = rand(256**length_a_B)+1 v = gcdext_test(a, b) $logfile.flush() @@ -675,7 +764,7 @@ def run_test_gcdext(skip=0) end (0..16).each do |i| b_size = rand(length_b_B+1) - a = rand(256**length_a_B)+1 + a = rand(256**length_a_B) b = rand(256**b_size)+1 v = gcdext_test(a, b) $logfile.flush() @@ -686,6 +775,36 @@ def run_test_gcdext(skip=0) end while length_a_B<4096/8 end +def init_serialport(conf) + puts("serial port interface version: " + SerialPort::VERSION); + $linewidth = 64 + $linepos = 0 + $testno = 0 + params = { "baud" => conf["PORT"]["baud"].to_i, + "data_bits" => conf["PORT"]["databits"].to_i, + "stop_bits" => conf["PORT"]["stopbits"].to_i, + "parity" => SerialPort::NONE } + params["paraty"] = SerialPort::ODD if conf["PORT"]["paraty"].downcase == "odd" + params["paraty"] = SerialPort::EVEN if conf["PORT"]["paraty"].downcase == "even" + params["paraty"] = SerialPort::MARK if conf["PORT"]["paraty"].downcase == "mark" + params["paraty"] = SerialPort::SPACE if conf["PORT"]["paraty"].downcase == "space" + + puts("\nPort: "+conf["PORT"]["port"]+"@" + + params["baud"].to_s + + " " + + params["data_bits"].to_s + + conf["PORT"]["paraty"][0,1].upcase + + params["stop_bits"].to_s + + "\n") + + $sp = SerialPort.new(conf["PORT"]["port"], params) + + $sp.read_timeout=1000; # 5 minutes + $sp.flow_control = SerialPort::SOFT + + reset_system() +end + ################################################################################ # MAIN # ################################################################################ @@ -699,34 +818,9 @@ conf = readconfigfile("testport.conf", conf) conf = readconfigfile(opts["f"], conf) if opts["f"] #puts conf.inspect +init_serialport(conf) -puts("serial port interface version: " + SerialPort::VERSION); -$linewidth = 64 -$linepos = 0 -$testno = 0 -params = { "baud" => conf["PORT"]["baud"].to_i, - "data_bits" => conf["PORT"]["databits"].to_i, - "stop_bits" => conf["PORT"]["stopbits"].to_i, - "parity" => SerialPort::NONE } -params["paraty"] = SerialPort::ODD if conf["PORT"]["paraty"].downcase == "odd" -params["paraty"] = SerialPort::EVEN if conf["PORT"]["paraty"].downcase == "even" -params["paraty"] = SerialPort::MARK if conf["PORT"]["paraty"].downcase == "mark" -params["paraty"] = SerialPort::SPACE if conf["PORT"]["paraty"].downcase == "space" - -puts("\nPort: "+conf["PORT"]["port"]+"@" + - params["baud"].to_s + - " " + - params["data_bits"].to_s + - conf["PORT"]["paraty"][0,1].upcase + - params["stop_bits"].to_s + - "\n") - -$sp = SerialPort.new(conf["PORT"]["port"], params) - -$sp.read_timeout=1000; # 5 minutes -$sp.flow_control = SerialPort::SOFT - -reset_system() + $max_timeout = 5 * 60 if opts['d'] $debug = true @@ -740,12 +834,16 @@ if File.exists?(logfilename) i+=1 end while(File.exists?(logfilename)) while(i>2) do - File.move(sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i-2,'.txt'), - sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i-1,'.txt'), true) + n1 = sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i-2,'.txt') + n2 = sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i-1,'.txt') + File.rename(n1, n2) + printf("%s -> %s\n", n1, n2) i-=1 end - File.move(sprintf('%s%s', conf['PORT']['testlogbase'],'bigint.txt'), - sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',1,'.txt'), true) + n1 = sprintf('%s%s', conf['PORT']['testlogbase'],'bigint.txt') + n2 = sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',1,'.txt') + File.rename(n1, n2) + printf("%s -> %s\n", n1, n2) logfilename = conf['PORT']['testlogbase']+'bigint.txt' end $logfile = File.open(logfilename, 'w') @@ -758,12 +856,14 @@ $logfile.printf("seed = 0x%X\n", 0xdeadbeef) tests = Hash.new tests['a'] = proc {|x| run_test_add(x) } tests['m'] = proc {|x| run_test_mul(x) } +tests['x'] = proc {|x| run_test_add_scale(x) } tests['s'] = proc {|x| run_test_square(x) } tests['r'] = proc {|x| run_test_reduce(x) } tests['e'] = proc {|x| run_test_expmod(x) } tests['g'] = proc {|x| run_test_gcdext(x) } init_str = Hash.new init_str['a'] = 'add-test' +init_str['x'] = 'add-scale-test' init_str['m'] = 'mul-test' init_str['s'] = 'square-test' init_str['r'] = 'reduce-test' diff --git a/host/rsa_oaep_check.rb b/host/rsa_oaep_check.rb index 8277c14..8d8967e 100644 --- a/host/rsa_oaep_check.rb +++ b/host/rsa_oaep_check.rb @@ -1,7 +1,7 @@ #!/usr/bin/ruby -# nessie_check.rb +# rsa_oaep_check.rb =begin - This file is part of the ARM-Crypto-Lib. + This file is part of the AVR-Crypto-Lib. Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) This program is free software: you can redistribute it and/or modify @@ -25,6 +25,8 @@ require 'getopt/std' $buffer_size = 0 # set automatically in init_system $conffile_check = Hash.new $conffile_check.default = 0 +$debug = false +$logfile = nil ################################################################################ # readconfigfile # @@ -38,7 +40,12 @@ def read_line_from_device() l = $sp.gets() repeat_counter -= 1 end while !l && repeat_counter > 0 -# printf("DBG: << %s\n", l.inspect) + t = Time.new + $logfile.printf("DBG: (%02d:%02d:%02d)<< %s\n", t.hour, t.min, t.sec, l.inspect) if $debug + if l && l.include?("AVR-Crypto-Lib") + $logfile.printf("DBG: system crashed !!!\n") + exit(false) + end return l end @@ -202,24 +209,59 @@ def read_tv(f) return h end +def wait_for_dot + begin + s = $sp.gets() + end while !s || !s.include?('.') +end + def load_bigint(d) $sp.printf("%d\r", d.length) while l = read_line_from_device() break if /data:/.match(l) end printf "ERROR: got no answer from system!" if !l + i = 0 d.each do |e| - $sp.printf(" %02x", e) + $sp.printf("%02x", e) + i += 1 + if i % 60 == 0 +# we should now wait for incomming dot + wait_for_dot() + print('.') + end end end +def hexdump(a) + i = 0 + a.each do |e| + printf("\n\t") if i % 16 == 0 + printf('%02x ', e) + i += 1 + end + puts('') if i % 16 != 1 +end + +def str_hexdump(a) + i = 0 + s = '' + a.each do |e| + s += "\n\t" if i % 16 == 0 + s += sprintf('%02x ', e) + i += 1 + end + s += "\n" if i % 16 != 1 + return s +end + def load_key(k) $sp.print("load-key\r") sleep 0.1 v = ['n', 'e', 'p', 'q', 'dP', 'dQ', 'qInv'] v.each do |e| load_bigint(k[e]) -# printf("DBG: loaded %s\n", e) + $logfile.printf("DBG: loaded %s\n", e) if $debug end while l = read_line_from_device() break if />/.match(l) @@ -231,7 +273,7 @@ def check_tv(tv) $sp.print("seed-test\r") sleep 0.1 load_bigint(tv['msg']) -# printf("DBG: loaded %s\n", 'msg') + $logfile.printf("DBG: loaded %s\n", 'msg') if $debug sleep 0.1 tv['seed'].each { |e| $sp.printf(" %02x", e) } while l = read_line_from_device() @@ -240,7 +282,7 @@ def check_tv(tv) test_enc = '' loop do l = read_line_from_device() - break if /decrypting/.match(l) + break if ! /([0-9A-Fa-f]{2}\s*)+/.match(l) test_enc += l if l end test_enc_a = Array.new @@ -252,7 +294,7 @@ def check_tv(tv) test_enc_a.collect!{ |e| e.to_i(16) } enc_ok = (test_enc_a == tv['enc']) if !enc_ok - printf("DBG: ref = %s test = %s\n", tv['enc'].inspect , test_enc_a.inspect) + $logfile.printf("DBG: ref = %s test = %s\n", str_hexdump(tv['enc']) , str_hexdump(test_enc_a)) end m = nil loop do @@ -264,13 +306,15 @@ def check_tv(tv) return false end -def run_test(f) +def run_test(f,skip_key=1,skip_vec=1) ok = 0 fail = 0 + key_idx = 0 + vec_idx = 0 skip_file_header(f) loop do a,b = goto_next_header(f) -# printf("DBG: a=%s b=%s\n", a.inspect, b.inspect) + $logfile.printf("DBG: a=%s b=%s\n", a.inspect, b.inspect) if $debug return ok,fail if !b if a == :mainblock # Example 1: A 1024-bit RSA Key Pair @@ -281,17 +325,24 @@ def run_test(f) if a == :subblock if b == 'Components of the RSA Key Pair' k = read_key(f) - load_key(k) + key_idx += 1 + vec_idx = 0 + load_key(k) if skip_key <= key_idx else tv = read_tv(f) - r = check_tv(tv) - if r - ok += 1 - putc('*') + vec_idx += 1 + if (key_idx > skip_key) || (key_idx == skip_key && vec_idx >= skip_vec) + r = check_tv(tv) + if r + ok += 1 + putc('*') + else + fail += 1 + putc('!') + end else - fail += 1 - putc('!') - end + putc('o') + end end end end @@ -302,7 +353,7 @@ end ######################################## -opts = Getopt::Std.getopts("c:f:") +opts = Getopt::Std.getopts("dc:f:il:s:") conf = Hash.new conf = readconfigfile("/etc/testport.conf", conf) @@ -336,11 +387,27 @@ $sp = SerialPort.new(conf["PORT"]["port"], params) $sp.read_timeout=1000; # 5 minutes $sp.flow_control = SerialPort::SOFT +$debug = true if opts['d'] + +if opts['s'] && m = opts['s'].match(/([\d]+\.([\d]+))/) + sk = m[1].to_i + sv = m[2].to_i +else + sk = 1 + sv = 1 +end + +if opts['l'] + $logfile = File.open(opts['l'], 'w') +end + +$logfile = STDOUT if ! $logfile +$logfile.sync = true reset_system() f = File.open(opts['f'], "r") exit if !f -ok,fail = run_test(f) +ok,fail = run_test(f,sk,sv) printf("\nOK: %d FAIL: %d :-%s\n",ok,fail, fail==0 ? ')':'(') diff --git a/host/rsa_pkcs15_check.rb b/host/rsa_pkcs15_check.rb new file mode 100644 index 0000000..cdafa8a --- /dev/null +++ b/host/rsa_pkcs15_check.rb @@ -0,0 +1,390 @@ +#!/usr/bin/ruby +# rsa_pkcs15_check.rb +=begin + This file is part of the AVR-Crypto-Lib. + Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +=end + +require 'rubygems' +require 'serialport' +require 'getopt/std' + +$buffer_size = 0 # set automatically in init_system +$conffile_check = Hash.new +$conffile_check.default = 0 +$debug = false +$logfile = nil + +################################################################################ +# readconfigfile # +################################################################################ + +def read_line_from_device() + repeat_counter = 10000 + l = nil + s = '' + begin + l = $sp.gets() + repeat_counter -= 1 + end while !l && repeat_counter > 0 + t = Time.new + $logfile.printf("DBG: (%02d:%02d:%02d)<< %s\n", t.hour, t.min, t.sec, l.inspect) if $debug + if l && l.include?("AVR-Crypto-Lib") + $logfile.printf("DBG: system crashed !!!\n") + exit(false) + end + return l +end + +def readconfigfile(fname, conf) + return conf if $conffile_check[fname]==1 + $conffile_check[fname]=1 + section = "default" + if not File.exists?(fname) + return conf + end + file = File.open(fname, "r") + until file.eof + line = file.gets() + next if /[\s]*#/.match(line) + if m=/\[[\s]*([^\s]*)[\s]*\]/.match(line) + section=m[1] + conf[m[1]] = Hash.new + next + end + next if ! /=/.match(line) + m=/[\s]*([^\s]*)[\s]*=[\s]*([^\s]*)/.match(line) + if m[1]=="include" + Dir.glob(m[2]){ |fn| conf = readconfigfile(fn, conf) } + else + conf[section][m[1]] = m[2] + end + end + file.close() + return conf +end + +################################################################################ +# reset_system # +################################################################################ + +def reset_system + $sp.print("\r") + sleep 0.1 + $sp.print("\r") + sleep 0.1 + $sp.print("echo off\r") + sleep 0.1 +end + + +def read_block(f) + d = Array.new + begin + l = f.gets + x = l.split.collect { |e| e.to_i(16) } + d += x + end while x.length == 16 + return d +end + +=begin +# Modulus: +# Exponent: +# Modulus: +# Public exponent: +# Exponent: +# Prime 1: +# Prime 2: +# Prime exponent 1: +# Prime exponent 2: +# Coefficient: +# Message: +# Seed: +# Encryption: + +=end + +def get_next_block(f) + ret = Hash.new + data = Array.new + begin + l = f.gets + end while l && ! m= l.match(/^#[\s](.*):[\s]*$/) + return nil if ! l + ret['tag'] = m[1] + ret['line'] = f.lineno + data = read_block(f) + ret['data'] = data + return ret +end + +$key_sequence = [ + 'Modulus', # 0 + 'Exponent', # 1 + 'Modulus', # 2 + 'Public exponent', # 3 + 'Exponent', # 4 + 'Prime 1', # 5 + 'Prime 2', # 6 + 'Prime exponent 1', # 7 + 'Prime exponent 2', # 8 + 'Coefficient', # 9 +] + +def key_consitency_check(k) + return true +end + +def process_file(f, skip_key=1, skip_vec=1) + a = get_next_block(f) + key_no = 0 + ok_counter = 0 + fail_counter = 0 + begin + if !a || ! a['tag'] == 'Modulus' + printf("ERROR: a = %s %d\n", a.inspect, __LINE__) + return + end + k_seq = Array.new + k_seq[0] = a + (1..($key_sequence.length-1)).each do |i| + a = get_next_block(f) + if ! a || a['tag'] != $key_sequence[i] + printf("ERROR: (expecting: %s) a = %s %d\n", $key_sequence[i], a.inspect, __LINE__) + end + k_seq[i] = a + end + key = convert_key(k_seq) + printf("ERROR: %d\n", __LINE__) if ! key + key_no += 1 + vec_no = 0 + printf("\n run %3d: ", key_no) + skip_key_flag = (key_no < skip_key) + load_key(key) if ! skip_key_flag + test_seq = Array.new + a = get_next_block(f) + printf("ERROR: %d\n", __LINE__) if ! a + begin + vec_no += 1 + b = get_next_block(f) + c = get_next_block(f) + tv = Hash.new + tv['msg'] = a['data'] + tv['seed'] = b['data'] + tv['enc'] = c['data'] + skip_vec_flag = (skip_key_flag || (key_no == skip_key && vec_no < skip_vec)) + if skip_vec_flag + printf('o') + else + v = check_tv(tv) + if(v == true) + printf('*') + $logfile.printf("[[Test %2d.%02d = OK]]\n", key_no, vec_no) + ok_counter += 1 + else + printf('%c', v ? '*' : '!') + $logfile.printf("[[Test %2d.%02d = FAIL]]\n", key_no, vec_no) + fail_counter += 1 + end + end + a = get_next_block(f) + end while a && a['tag'] == 'Message' + end while a && a['tag'] = 'Modulus' +# printf("\nResult: %d OK / %d FAIL ==> %s \nFinished\n", ok_counter, fail_counter, fail_counter==0 ? ':-)' : ':-(') + return ok_counter,fail_counter +end + +def convert_key(k_seq) + l = ['n', 'e', 'd', 'p', 'q', 'dP', 'dQ', 'qInv'] + r = Hash.new + return nil if k_seq[0]['data'] != k_seq[2]['data'] + return nil if k_seq[1]['data'] != k_seq[3]['data'] + 8.times do |i| + r[l[i]] = k_seq[2 + i]['data'] + end + return r +end + +def wait_for_dot + begin + s = $sp.gets() + end while !s || !s.include?('.') +end + +def load_bigint(d) + $sp.printf("%d\r", d.length) + while l = read_line_from_device() + break if /data:/.match(l) + end + printf "ERROR: got no answer from system!" if !l + i = 0 + d.each do |e| + $sp.printf("%02x", e) + i += 1 + if i % 60 == 0 +# we should now wait for incomming dot + wait_for_dot() + print('.') + end + end +end + +def hexdump(a) + i = 0 + a.each do |e| + printf("\n\t") if i % 16 == 0 + printf('%02x ', e) + i += 1 + end + puts('') if i % 16 != 1 +end + +def str_hexdump(a) + i = 0 + s = '' + a.each do |e| + s += "\n\t" if i % 16 == 0 + s += sprintf('%02x ', e) + i += 1 + end + s += "\n" if i % 16 != 1 + return s +end + +def load_key(k) + $sp.print("load-key\r") + sleep 0.1 + v = ['n', 'e', 'p', 'q', 'dP', 'dQ', 'qInv'] + v.each do |e| + load_bigint(k[e]) + $logfile.printf("DBG: loaded %s\n", e) if $debug + end + while l = read_line_from_device() + break if />/.match(l) + end +end + +def strip_leading_zeros(a) + loop do + return [] if a.length == 0 + return a if a[0] != 0 + a.delete_at(0) + end +end + +def check_tv(tv) + sleep 0.1 + $sp.print("seed-test\r") + sleep 0.1 + load_bigint(tv['msg']) + $logfile.printf("DBG: loaded %s\n", 'msg') if $debug + sleep 0.1 + tv['seed'].each { |e| $sp.printf(" %02x", e) } + while l = read_line_from_device() + break if /ciphertext:/.match(l) + end + test_enc = '' + loop do + l = read_line_from_device() + break if ! /([0-9A-Fa-f]{2}\s*)+/.match(l) + test_enc += l if l + end + test_enc_a = Array.new + test_enc = test_enc.split(/[\W\r\n]+/) + test_enc.each do |e| + v = e.sub(/[^0-9A-Fa-f]/, '') + test_enc_a << v if v.length == 2 + end + test_enc_a.collect!{ |e| e.to_i(16) } + strip_leading_zeros(test_enc_a) + strip_leading_zeros(tv['enc']) + enc_ok = (test_enc_a == tv['enc']) + if !enc_ok + $logfile.printf("DBG: ref = %s test = %s\n", str_hexdump(tv['enc']) , str_hexdump(test_enc_a)) + end + m = nil + loop do + l = read_line_from_device() + m = /(>>OK<<|ERROR)/.match(l) + break if m + end + return true if enc_ok && (m[1] == '>>OK<<') + return false +end + +######################################## +# MAIN +######################################## + + +opts = Getopt::Std.getopts('dc:f:il:s:') + +conf = Hash.new +conf = readconfigfile("/etc/testport.conf", conf) +conf = readconfigfile("~/.testport.conf", conf) +conf = readconfigfile("testport.conf", conf) +conf = readconfigfile(opts["c"], conf) if opts["c"] + +#puts conf.inspect + +puts("serial port interface version: " + SerialPort::VERSION); +$linewidth = 64 +params = { "baud" => conf["PORT"]["baud"].to_i, + "data_bits" => conf["PORT"]["databits"].to_i, + "stop_bits" => conf["PORT"]["stopbits"].to_i, + "parity" => SerialPort::NONE } +params["paraty"] = SerialPort::ODD if conf["PORT"]["paraty"].downcase == "odd" +params["paraty"] = SerialPort::EVEN if conf["PORT"]["paraty"].downcase == "even" +params["paraty"] = SerialPort::MARK if conf["PORT"]["paraty"].downcase == "mark" +params["paraty"] = SerialPort::SPACE if conf["PORT"]["paraty"].downcase == "space" + +puts("\nPort: "+conf["PORT"]["port"]+"@" + + params["baud"].to_s + + " " + + params["data_bits"].to_s + + conf["PORT"]["paraty"][0,1].upcase + + params["stop_bits"].to_s + + "\n") + +$sp = SerialPort.new(conf["PORT"]["port"], params) + +$sp.read_timeout=1000; # 5 minutes +$sp.flow_control = SerialPort::SOFT + +$debug = true if opts['d'] + +if opts['l'] + $logfile = File.open(opts['l'], 'w') +end + +$logfile = STDOUT if ! $logfile +reset_system() + +if opts['s'] && m = opts['s'].match(/([\d]+\.([\d]+))/) + sk = m[1].to_i + sv = m[2].to_i +else + sk = 1 + sv = 1 +end + +f = File.open(opts['f'], "r") +exit if !f +ok,fail = process_file(f,sk,sv) +printf("\nOK: %d FAIL: %d :-%s\n",ok,fail, fail==0 ? ')':'(') + + diff --git a/rsa/rsa_basic.c b/rsa/rsa_basic.c index 38c46a1..e71bc8c 100644 --- a/rsa/rsa_basic.c +++ b/rsa/rsa_basic.c @@ -24,8 +24,12 @@ #include "bigint_io.h" #include "rsa_basic.h" +#define DEBUG 0 + +#if DEBUG #include "cli.h" #include "uart_lowlevel.h" +#endif void rsa_enc(bigint_t* data, rsa_publickey_t* key){ /* @@ -52,18 +56,29 @@ uint8_t rsa_dec_crt_mono(bigint_t* data, rsa_privatekey_t* key){ m1.wordv = malloc(key->components[0]->length_B * sizeof(bigint_word_t)); m2.wordv = malloc(key->components[1]->length_B * sizeof(bigint_word_t)); if(!m1.wordv || !m2.wordv){ +#if DEBUG cli_putstr("\r\nERROR: OOM!"); +#endif free(m1.wordv); free(m2.wordv); return 1; } +#if DEBUG + cli_putstr("\r\nDBG: expmod m1 ..."); +#endif bigint_expmod_u(&m1, data, key->components[2], key->components[0]); +#if DEBUG + cli_putstr("expmod m2 ..."); +#endif bigint_expmod_u(&m2, data, key->components[3], key->components[1]); bigint_sub_s(&m1, &m1, &m2); while(BIGINT_NEG_MASK & m1.info){ bigint_add_s(&m1, &m1, key->components[0]); } +#if DEBUG + cli_putstr("\r\nDBG: reduce-mul ..."); +#endif bigint_reduce(&m1, key->components[0]); bigint_mul_u(data, &m1, key->components[4]); bigint_reduce(data, key->components[0]); diff --git a/rsa/rsa_oaep.c b/rsa/rsa_oaep.c index 4fa488b..88526e6 100644 --- a/rsa/rsa_oaep.c +++ b/rsa/rsa_oaep.c @@ -117,7 +117,6 @@ uint8_t rsa_encrypt_oaep(void* dest, uint16_t* out_length, // cli_hexdump_block(dest, bigint_length_B(key->modulus), 4, 16); x.wordv = dest; - x.length_B = key->modulus->length_B; bigint_adjust(&x); rsa_os2ip(&x, NULL, bigint_length_B(key->modulus)); diff --git a/rsa/rsa_pkcs15.c b/rsa/rsa_pkcs15.c index 359801e..858b918 100644 --- a/rsa/rsa_pkcs15.c +++ b/rsa/rsa_pkcs15.c @@ -23,8 +23,12 @@ #include "bigint.h" #include "rsa_basic.h" +#define DEBUG 0 + +#if DEBUG #include "bigint_io.h" #include "cli.h" +#endif #include "random_dummy.h" @@ -34,8 +38,10 @@ uint8_t rsa_encrypt_pkcs15(void* dest, uint16_t* out_length, const void* src, bigint_t x; pad_length = (bigint_get_first_set_bit(key->modulus) + 7) / 8 - length_B - 3; if(pad_length<8){ +#if DEBUG cli_putstr("\r\nERROR: pad_length<8; pad_length: "); cli_hexdump_rev(&pad_length, 2); +#endif return 2; /* message to long */ } if(!pad){ @@ -69,9 +75,13 @@ uint8_t rsa_decrypt_pkcs15(void* dest, uint16_t* out_length, const void* src, uint16_t m_length, pad_length=0, idx=0; x.wordv = dest; rsa_os2ip(&x, src, length_B); +#if DEBUG cli_putstr("\r\ncalling rsa_dec() ..."); +#endif rsa_dec(&x, key); +#if DEBUG cli_putstr("\r\nfinished rsa_dec() ..."); +#endif rsa_i2osp(NULL, &x, &m_length); while(((uint8_t*)x.wordv)[idx]==0 && idx36){ + return NULL; + } + if(value == 0){ + *p++ = '0'; + *p = '\0'; + return str; + } + while(value){ + d = div(value, radix); + value = d.quot; + if(d.rem < 10){ + *p++ = '0' + d.rem; + }else{ + *p++ = 'a' + d.rem - 10; + } + } + *p = '\0'; + while(strlength_B = (sizeof(private_exponent) + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t); + epriv->length_B = (sizeof(PRIV_EXPONENT) + sizeof(bigint_word_t) - 1) / sizeof(bigint_word_t); epriv->wordv = malloc(epriv->length_B * sizeof(bigint_word_t)); if(!epriv->wordv){ cli_putstr("\r\nERROR: OOM!"); return; } - memcpy(epriv->wordv, private_exponent, sizeof(private_exponent)); + memcpy(epriv->wordv, PRIV_EXPONENT, sizeof(PRIV_EXPONENT)); priv_key.components = malloc(sizeof(bigint_t*)); priv_key.components[0] = epriv; priv_key.n = 1; @@ -547,8 +581,8 @@ void load_priv_conventional(void){ void load_priv_crt_mono(void){ bigint_t **v; - const uint8_t *bv[5] = {p,q,dp,dq,qinv}; - uint16_t sv[5] = {sizeof(p), sizeof(q), sizeof(dp), sizeof(dq), sizeof(qinv)}; + const uint8_t *bv[5] = {P,Q,DP,DQ,QINV}; + uint16_t sv[5] = {sizeof(P), sizeof(Q), sizeof(DP), sizeof(DQ), sizeof(QINV)}; uint8_t i; v = malloc(5 * sizeof(bigint_t)); if(!v){ @@ -618,30 +652,36 @@ void load_fix_rsa(void){ void quick_test(void){ uint8_t *ciphertext, *plaintext, rc; + uint8_t seed[sizeof(SEED)]; uint16_t clen, plen; ciphertext = malloc(clen = pub_key.modulus->length_B * sizeof(bigint_word_t)); plaintext = malloc(pub_key.modulus->length_B * sizeof(bigint_word_t)); -// memcpy(ciphertext, message1, sizeof(message1)); + memcpy(plaintext, MSG, sizeof(MSG)); + memcpy(seed, SEED, sizeof(SEED)); cli_putstr("\r\nplaintext:"); - cli_hexdump_block(MSG, sizeof(MSG), 4, 8); - uart_flush(0); - rc = rsa_encrypt_oaep(ciphertext, &clen, MSG, sizeof(MSG), &pub_key, NULL, NULL, SEED); + cli_hexdump_block(plaintext, sizeof(MSG), 4, 8); + cli_putstr("\r\nencrypting: ..."); + rc = rsa_encrypt_oaep(ciphertext, &clen, plaintext, sizeof(MSG), &pub_key, NULL, NULL, seed); if(rc){ cli_putstr("\r\nERROR: rsa_encrypt_oaep returned: "); cli_hexdump_byte(rc); return; } + cli_putstr("\r\n\r\nciphertext:"); cli_hexdump_block(ciphertext, clen, 4, 8); - if(clen!=sizeof(ENCRYPTED) || memcmp(ENCRYPTED, ciphertext, clen)){ - cli_putstr("\r\n>>FAIL<<"); + if(clen!=sizeof(ENCRYPTED)){ + cli_putstr("\r\n>>FAIL (no size match)<<"); }else{ - cli_putstr("\r\n>>OK<<"); + if(memcmp(ciphertext, ENCRYPTED, clen)){ + cli_putstr("\r\n>>FAIL (no content match)<<"); + }else{ + cli_putstr("\r\n>>OK<<"); + } } - uart_flush(0); - + cli_putstr("\r\ndecrypting: ..."); rc = rsa_decrypt_oaep(plaintext, &plen, ciphertext, clen, &priv_key, NULL, NULL, NULL); if(rc){ cli_putstr("\r\nERROR: rsa_decrypt_oaep returned: "); @@ -689,23 +729,41 @@ void run_seed_test(void){ rsa_encrypt_oaep(ciph, &ciph_len, msg, msg_len, &pub_key, NULL, NULL, seed); cli_putstr("\r\n ciphertext:"); cli_hexdump_block(ciph, ciph_len, 4, 16); - cli_putstr("\r\n decrypting ..."); - uart_flush(0); + cli_putstr("\r\n decrypting ... "); rsa_decrypt_oaep(msg_, &msg_len_, ciph, ciph_len, &priv_key, NULL, NULL, seed_out); + cli_putstr("[done]"); if(msg_len != msg_len_){ - cli_putstr("\r\nERROR: wrong decryted message length"); - return; + char tstr[16]; + cli_putstr("\r\nERROR: wrong decrypted message length ("); + + own_utoa(msg_len_, tstr, 10); + cli_putstr(tstr); + cli_putstr(" instead of "); + own_utoa(msg_len, tstr, 10); + cli_putstr(tstr); + cli_putc(')'); + goto end; } if(memcmp(msg, msg_, msg_len)){ - cli_putstr("\r\nERROR: wrong decryted message"); - return; + cli_putstr("\r\nERROR: wrong decrypted message:"); + cli_hexdump_block(msg_, msg_len_, 4, 16); + cli_putstr("\r\nreference:"); + cli_hexdump_block(msg, msg_len, 4, 16); + goto end; } if(memcmp(seed, seed_out, 20)){ - cli_putstr("\r\nERROR: wrong decryted seed"); - return; + cli_putstr("\r\nERROR: wrong decrypted seed:"); + cli_hexdump_block(seed_out, 20, 4, 16); + cli_putstr("\r\nreference:"); + cli_hexdump_block(seed, 20, 4, 16); + goto end; } cli_putstr("\r\n >>OK<<"); +end: + free(msg); + free(msg_); + free(ciph); } void reset_prng(void){ @@ -727,6 +785,18 @@ void load_key(void){ read_key_crt(); } +void test_dump(void){ + char lstr[16]; + int len; + cli_putstr("\r\nenter dump length: "); + cli_getsn(lstr, 15); + len = own_atou(lstr); + cli_putstr("\r\ndumping 0x"); + cli_hexdump_rev(&len, 2); + cli_putstr(" byte:"); + cli_hexdump_block(pub_key.modulus->wordv, len, 4, 8); +} + /***************************************************************************** * main * *****************************************************************************/ @@ -737,15 +807,17 @@ const char load_key_str[] = "load-key"; const char load_fix_key_str[] = "load-fix-key"; const char quick_test_str[] = "quick-test"; const char seed_test_str[] = "seed-test"; +const char dump_test_str[] = "dump-test"; const char performance_str[] = "performance"; const char echo_str[] = "echo"; -cmdlist_entry_t cmdlist[] = { +const cmdlist_entry_t cmdlist[] = { { reset_prng_str, NULL, reset_prng }, { load_key_str, NULL, load_key }, { load_fix_key_str, NULL, load_fix_rsa }, { quick_test_str, NULL, quick_test }, { seed_test_str, NULL, run_seed_test }, + { dump_test_str, NULL, test_dump }, // { performance_str, NULL, testrun_performance_bigint }, { echo_str, (void*)1, (void_fpt)echo_ctrl }, { NULL, NULL, NULL } -- 2.39.5