X-Git-Url: https://git.cryptolib.org/?a=blobdiff_plain;f=bigint%2Fbigint.c;h=3e2f0eb295241651d679faa9f04f3df723db01d1;hb=35dc9566e40c9f68fa216c70eaa6d5b0597448fe;hp=d83edb6204721f638721436a81db0ccb340eb749;hpb=4bd4efef59a3f71149393516b7bd283eeab18363;p=avr-crypto-lib.git diff --git a/bigint/bigint.c b/bigint/bigint.c index d83edb6..3e2f0eb 100644 --- a/bigint/bigint.c +++ b/bigint/bigint.c @@ -26,12 +26,16 @@ */ +#define STRING2(x) #x +#define STRING(x) STRING2(x) +#define STR_LINE STRING(__LINE__) + #include "bigint.h" #include - -#include "bigint_io.h" +/* #include "cli.h" - +#include "bigint_io.h" +*/ #ifndef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #endif @@ -73,15 +77,14 @@ void bigint_adjust(bigint_t* a){ /******************************************************************************/ void bigint_copy(bigint_t* dest, const bigint_t* src){ - memcpy(dest->wordv, src->wordv, src->length_B); dest->length_B = src->length_B; dest->info = src->info; + memcpy(dest->wordv, src->wordv, src->length_B); } /******************************************************************************/ /* this should be implemented in assembly */ -/* void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ uint16_t t=0, i; if(a->length_B < b->length_B){ @@ -101,7 +104,7 @@ void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ dest->length_B = i; bigint_adjust(dest); } -*/ + /******************************************************************************/ /* this should be implemented in assembly */ @@ -164,29 +167,8 @@ void bigint_sub_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ return; } if(r<0){ - for(i=0; iwordv[i] - b->wordv[i] - borrow; - if(t<1){ - borrow = 0; - dest->wordv[i]=(uint8_t)(-t); - }else{ - borrow = -1; - dest->wordv[i]=(uint8_t)(-t); - } - } - for(;iwordv[i] + borrow; - if(t<1){ - borrow = 0; - dest->wordv[i]=(uint8_t)t; - }else{ - borrow = -1; - dest->wordv[i]=(uint8_t)t; - } - } + bigint_sub_u(dest, b, a); SET_NEG(dest); - dest->length_B = i; - bigint_adjust(dest); }else{ for(i=0; iwordv[i] - b->wordv[i] - borrow; @@ -224,12 +206,6 @@ int8_t bigint_cmp_u(const bigint_t* a, const bigint_t* b){ if(a->length_B < b->length_B){ return -1; } - if(GET_FBS(a) > GET_FBS(b)){ - return 1; - } - if(GET_FBS(a) < GET_FBS(b)){ - return -1; - } if(a->length_B==0){ return 0; } @@ -304,6 +280,9 @@ void bigint_sub_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){ int8_t bigint_cmp_s(const bigint_t* a, const bigint_t* b){ uint8_t s; + if(a->length_B==0 && b->length_B==0){ + return 0; + } s = GET_SIGN(a)?2:0; s |= GET_SIGN(b)?1:0; switch(s){ @@ -369,15 +348,11 @@ void bigint_shiftright(bigint_t* a, uint16_t shift){ byteshift = shift/8; bitshift = shift&7; if(byteshift >= a->length_B){ /* we would shift out more than we have */ - a->length_B=0; - a->wordv[0] = 0; - SET_FBS(a, 0); + bigint_set_zero(a); return; } if(byteshift == a->length_B-1 && bitshift>GET_FBS(a)){ - a->length_B=0; - a->wordv[0] = 0; - SET_FBS(a, 0); + bigint_set_zero(a); return; } if(byteshift){ @@ -423,6 +398,14 @@ void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ bigint_set_zero(dest); return; } + if(dest==a || dest==b){ + bigint_t d; + uint8_t d_b[a->length_B+b->length_B]; + d.wordv = d_b; + bigint_mul_u(&d, a, b); + bigint_copy(dest, &d); + return; + } if(a->length_B==1 || b->length_B==1){ if(a->length_B!=1){ XCHG_PTR(a,b); @@ -493,7 +476,7 @@ void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* 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 <= tmp*tmp */ + 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 */ @@ -544,6 +527,14 @@ void bigint_square(bigint_t* dest, const bigint_t* a){ bigint_adjust(dest); return; } + if(dest==a){ + bigint_t d; + uint8_t d_b[a->length_B*2]; + d.wordv = d_b; + bigint_square(&d, a); + bigint_copy(dest, &d); + return; + } uint16_t n; n=(a->length_B+1)/2; bigint_t xh, xl, tmp; /* x-high, x-low, temp */ @@ -571,7 +562,6 @@ void bigint_sub_u_bitscale(bigint_t* a, const bigint_t* b, uint16_t bitscale){ int16_t t; if(a->length_B < b->length_B+byteshift){ - cli_putstr_P(PSTR("\r\nERROR: bigint_sub_u_bitscale result negative")); bigint_set_zero(a); return; } @@ -591,8 +581,6 @@ void bigint_sub_u_bitscale(bigint_t* a, const bigint_t* b, uint16_t bitscale){ } while(borrow){ if(i+1 > a->length_B){ - cli_putstr_P(PSTR("\r\nERROR: bigint_sub_u_bitscale result negative (2) shift=")); - cli_hexdump_rev(&bitscale, 2); bigint_set_zero(a); return; } @@ -608,21 +596,211 @@ 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(r); uint8_t rfbs = GET_FBS(r); - if(r->length_B==0){ + + if(r->length_B==0 || a->length_B==0){ return; } while(a->length_B > r->length_B){ bigint_sub_u_bitscale(a, r, (a->length_B-r->length_B)*8+GET_FBS(a)-rfbs-1); } - while(GET_FBS(a) > rfbs+1){ + while((GET_FBS(a) > rfbs+1) && (a->length_B == r->length_B)){ bigint_sub_u_bitscale(a, r, GET_FBS(a)-rfbs-1); } while(bigint_cmp_u(a,r)>=0){ bigint_sub_u(a,a,r); } - bigint_adjust(a); } + +/******************************************************************************/ + +/* calculate dest = a**exp % r */ +/* using square&multiply */ +void bigint_expmod_u(bigint_t* dest, const bigint_t* a, const bigint_t* exp, const bigint_t* r){ + if(a->length_B==0 || r->length_B==0){ + return; + } + + bigint_t res, base; + uint8_t base_b[MAX(a->length_B,r->length_B*2)], res_b[r->length_B*2]; + uint16_t i; + uint8_t j, t; + res.wordv = res_b; + base.wordv = base_b; + bigint_copy(&base, a); + bigint_reduce(&base, r); + res.wordv[0]=1; + res.length_B=1; + res.info = 0; + bigint_adjust(&res); + for(i=0; i+1length_B; ++i){ + t=exp->wordv[i]; + for(j=0; j<8; ++j){ + if(t&1){ + bigint_mul_u(&res, &res, &base); + bigint_reduce(&res, r); + } + bigint_square(&base, &base); + bigint_reduce(&base, r); + t>>=1; + } + } + t=exp->wordv[i]; + 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); +} + +/******************************************************************************/ +/* gcd <-- gcd(x,y) a*x+b*y=gcd */ +void bigint_gcdext(bigint_t* gcd, bigint_t* a, bigint_t* b, const bigint_t* x, const bigint_t* y){ + bigint_t g, x_, y_, u, v, a_, b_, c_, d_; + volatile uint16_t i=0; + if(x->length_B==0 || y->length_B==0){ + return; + } + while(x->wordv[i]==0 && y->wordv[i]==0){ + ++i; + } + uint8_t g_b[i+2], x_b[x->length_B-i], y_b[y->length_B-i]; + uint8_t u_b[x->length_B-i], v_b[y->length_B-i]; + uint8_t a_b[y->length_B+2], c_b[y->length_B+2]; + uint8_t b_b[x->length_B+2], d_b[x->length_B+2]; + + g.wordv = g_b; + x_.wordv = x_b; + y_.wordv = y_b; + memset(g_b, 0, i); + g_b[i]=1; + g.length_B = i+1; + g.info=0; + x_.info = y_.info = 0; + x_.length_B = x->length_B-i; + y_.length_B = y->length_B-i; + memcpy(x_.wordv, x->wordv+i, x_.length_B); + memcpy(y_.wordv, y->wordv+i, y_.length_B); + for(i=0; (x_.wordv[0]&(1<=0){ + bigint_sub_u(&u, &u, &v); + bigint_sub_s(&a_, &a_, &c_); + bigint_sub_s(&b_, &b_, &d_); + }else{ + bigint_sub_u(&v, &v, &u); + bigint_sub_s(&c_, &c_, &a_); + bigint_sub_s(&d_, &d_, &b_); + } + }while(u.length_B); + if(gcd){ + bigint_mul_s(gcd, &v, &g); + } + if(a){ + bigint_copy(a, &c_); + } + if(b){ + bigint_copy(b, &d_); + } +} + +/******************************************************************************/ + +void bigint_inverse(bigint_t* dest, const bigint_t* a, const bigint_t* m){ + bigint_gcdext(NULL, dest, NULL, a, m); + while(dest->info&BIGINT_NEG_MASK){ + bigint_add_s(dest, dest, m); + } +} + +/******************************************************************************/ + +void bigint_changeendianess(bigint_t* a){ + uint8_t t, *p, *q; + p = a->wordv; + q = p+a->length_B-1; + while(p