X-Git-Url: https://git.cryptolib.org/?a=blobdiff_plain;f=bigint%2Fbigint.c;h=3e2f0eb295241651d679faa9f04f3df723db01d1;hb=35dc9566e40c9f68fa216c70eaa6d5b0597448fe;hp=fb2f524cfc2fedc0227a3ee5c2903e1d64b15de9;hpb=eb09a2a6f447833e3cf73a71fc0113f84d51f41b;p=avr-crypto-lib.git diff --git a/bigint/bigint.c b/bigint/bigint.c index fb2f524..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){ @@ -344,19 +323,18 @@ void bigint_shiftleft(bigint_t* a, uint16_t shift){ t >>= 8; } a->wordv[i] = (uint8_t)t; + byteshift++; }else{ /* shift to the right */ - bitshift = 8 - bitshift; - for(i=a->length_B+byteshift-1; i>byteshift; --i){ - t |= (a->wordv[i])<<(8-bitshift); + for(i=a->length_B+byteshift-1; i>byteshift-1; --i){ + t |= (a->wordv[i])<<(bitshift); a->wordv[i] = (uint8_t)(t>>8); t <<= 8; } - t |= (a->wordv[i])<<(8-bitshift); + t |= (a->wordv[i])<<(bitshift); a->wordv[i] = (uint8_t)(t>>8); } - } - a->length_B += byteshift+1; + a->length_B += byteshift; bigint_adjust(a); } @@ -370,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){ @@ -422,7 +396,14 @@ void bigint_set_zero(bigint_t* a){ void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ if(a->length_B==0 || b->length_B==0){ bigint_set_zero(dest); - depth -= 1; + 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){ @@ -488,7 +469,6 @@ void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){ /* now we have split up a and b */ uint8_t tmp_b[2*n+2], m_b[2*(n+1)]; bigint_t tmp, tmp2, m; - /* calculate h=xh*yh; l=xl*yl; sx=xh+xl; sy=yh+yl */ tmp.wordv = tmp_b; tmp2.wordv = tmp_b+n+1; m.wordv = m_b; @@ -496,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 */ @@ -547,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 */ @@ -562,9 +550,254 @@ void bigint_square(bigint_t* dest, const bigint_t* a){ bigint_mul_u(&tmp, &xl, &xh); bigint_shiftleft(&tmp, 1); bigint_add_scale_u(dest, &tmp, n); +} + +/******************************************************************************/ +void bigint_sub_u_bitscale(bigint_t* a, const bigint_t* b, uint16_t bitscale){ + bigint_t tmp; + uint8_t tmp_b[b->length_B+1]; + uint16_t i,j,byteshift=bitscale/8; + uint8_t borrow=0; + int16_t t; + + if(a->length_B < b->length_B+byteshift){ + bigint_set_zero(a); + return; + } + + tmp.wordv = tmp_b; + bigint_copy(&tmp, b); + bigint_shiftleft(&tmp, bitscale&7); + + for(j=0,i=byteshift; iwordv[i] - tmp.wordv[j] - borrow; + a->wordv[i] = (uint8_t)t; + if(t<0){ + borrow = 1; + }else{ + borrow = 0; + } + } + while(borrow){ + if(i+1 > a->length_B){ + bigint_set_zero(a); + return; + } + a->wordv[i] -= borrow; + if(a->wordv[i]!=0xff){ + borrow=0; + } + ++i; + } + bigint_adjust(a); } +/******************************************************************************/ + +void bigint_reduce(bigint_t* a, const bigint_t* r){ +// bigint_adjust(r); + uint8_t rfbs = GET_FBS(r); + + 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) && (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); + } +} + +/******************************************************************************/ + +/* 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