starting to make bigint more portable/32-bit efficient

This commit is contained in:
bg 2011-02-23 23:18:37 +01:00
parent f4853b26a5
commit 5e75eafde9
23 changed files with 2818 additions and 212 deletions

View File

@ -160,7 +160,7 @@ endef
$(foreach algo, $(ALGORITHMS), $(eval $(call Flash_Template, \
$(algo), \
$(BIN_DIR)$(call lc, $(algo))/$(TEST_DIR)main-$(call lc, $(algo))-test.hex \
$(BIN_DIR)$(call lc, $(algo))/$(TEST_DIR)main-$(call lc, $(algo))-test.elf \
)))
#-------------------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
TOOLCHAIN = arm-elf-
TOOLCHAIN = arm-none-eabi-#
MCU_TARGET = cortex-m3
OPTIMIZE = -O2
DEBUG = -g
OPTIMIZE = -O0
DEBUG = -gdwarf-2
WARNING = -pedantic -Wall -Wstrict-prototypes -Werror
DEFS = -D$(call uc, $(subst -,_,$(MCU_TARGET)))
FLASHCMD = $(TOOLCHAIN)gdb -x gdb-flash #

790
bigint/bigint-stub.c Normal file
View File

@ -0,0 +1,790 @@
/* bigint.c */
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* \file bigint.c
* \author Daniel Otte
* \date 2010-02-22
*
* \license GPLv3 or later
*
*/
#define STRING2(x) #x
#define STRING(x) STRING2(x)
#define STR_LINE STRING(__LINE__)
#include "bigint.h"
#include <string.h>
/*
#include "cli.h"
#include "bigint_io.h"
*/
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#define SET_FBS(a, v) do{(a)->info &=0xF8; (a)->info |= (v);}while(0)
#define GET_FBS(a) ((a)->info&BIGINT_FBS_MASK)
#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*)(((uint16_t)(a)) ^ ((uint16_t)(b))); \
b = (void*)(((uint16_t)(a)) ^ ((uint16_t)(b))); \
a = (void*)(((uint16_t)(a)) ^ ((uint16_t)(b)));}while(0)
#define GET_SIGN(a) ((a)->info&BIGINT_NEG_MASK)
/******************************************************************************/
/*
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;
}
*/
/******************************************************************************/
/* 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){
XCHG_PTR(a,b);
}
for(i=0; i<b->length_B; ++i){
t = a->wordv[i] + b->wordv[i] + t;
dest->wordv[i] = (uint8_t)t;
t>>=8;
}
for(; i<a->length_B; ++i){
t = a->wordv[i] + t;
dest->wordv[i] = (uint8_t)t;
t>>=8;
}
dest->wordv[i++] = t;
dest->length_B = i;
bigint_adjust(dest);
}
*/
/******************************************************************************/
/* 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;
uint16_t t=0;
if(scale>dest->length_B)
memset(dest->wordv+dest->length_B, 0, scale-dest->length_B);
for(i=scale; i<a->length_B+scale; ++i,++j){
t = a->wordv[j] + t;
if(dest->length_B>i){
t += dest->wordv[i];
}
dest->wordv[i] = (uint8_t)t;
t>>=8;
}
while(t){
if(dest->length_B>i){
t = dest->wordv[i] + t;
}
dest->wordv[i] = (uint8_t)t;
t>>=8;
++i;
}
if(dest->length_B < i){
dest->length_B = i;
}
bigint_adjust(dest);
}
/******************************************************************************/
/* this should be implemented in assembly */
void bigint_sub_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){
int8_t borrow=0;
int8_t r;
int16_t t;
uint16_t i, min, max;
min = MIN(a->length_B, b->length_B);
max = MAX(a->length_B, b->length_B);
r = bigint_cmp_u(a,b);
if(r==0){
dest->length_B = 0;
dest->wordv[0] = 0;
bigint_adjust(dest);
return;
}
if(b->length_B==0){
dest->length_B = a->length_B;
memcpy(dest->wordv, a->wordv, a->length_B);
dest->info = a->info;
SET_POS(dest);
return;
}
if(a->length_B==0){
dest->length_B = b->length_B;
memcpy(dest->wordv, b->wordv, b->length_B);
dest->info = b->info;
SET_NEG(dest);
return;
}
if(r<0){
bigint_sub_u(dest, b, a);
SET_NEG(dest);
}else{
for(i=0; i<min; ++i){
t = a->wordv[i] - b->wordv[i] - borrow;
if(t<0){
borrow = 1;
dest->wordv[i]=(uint8_t)t;
}else{
borrow = 0;
dest->wordv[i]=(uint8_t)t;
}
}
for(;i<max; ++i){
t = a->wordv[i] - borrow;
if(t<0){
borrow = 1;
dest->wordv[i]=(uint8_t)t;
}else{
borrow = 0;
dest->wordv[i]=(uint8_t)t;
}
}
SET_POS(dest);
dest->length_B = i;
bigint_adjust(dest);
}
}
/******************************************************************************/
int8_t bigint_cmp_u(const bigint_t* a, const bigint_t* b){
if(a->length_B > b->length_B){
return 1;
}
if(a->length_B < b->length_B){
return -1;
}
if(a->length_B==0){
return 0;
}
uint16_t i;
i = a->length_B-1;
do{
if(a->wordv[i]!=b->wordv[i]){
if(a->wordv[i]>b->wordv[i]){
return 1;
}else{
return -1;
}
}
}while(i--);
return 0;
}
/******************************************************************************/
void bigint_add_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint8_t s;
s = GET_SIGN(a)?2:0;
s |= GET_SIGN(b)?1:0;
switch(s){
case 0: /* both positive */
bigint_add_u(dest, a,b);
SET_POS(dest);
break;
case 1: /* a positive, b negative */
bigint_sub_u(dest, a, b);
break;
case 2: /* a negative, b positive */
bigint_sub_u(dest, b, a);
break;
case 3: /* both negative */
bigint_add_u(dest, a, b);
SET_NEG(dest);
break;
default: /* how can this happen?*/
break;
}
}
/******************************************************************************/
void bigint_sub_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint8_t s;
s = GET_SIGN(a)?2:0;
s |= GET_SIGN(b)?1:0;
switch(s){
case 0: /* both positive */
bigint_sub_u(dest, a,b);
break;
case 1: /* a positive, b negative */
bigint_add_u(dest, a, b);
SET_POS(dest);
break;
case 2: /* a negative, b positive */
bigint_add_u(dest, a, b);
SET_NEG(dest);
break;
case 3: /* both negative */
bigint_sub_u(dest, b, a);
break;
default: /* how can this happen?*/
break;
}
}
/******************************************************************************/
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){
case 0: /* both positive */
return bigint_cmp_u(a, b);
break;
case 1: /* a positive, b negative */
return 1;
break;
case 2: /* a negative, b positive */
return -1;
break;
case 3: /* both negative */
return bigint_cmp_u(b, a);
break;
default: /* how can this happen?*/
break;
}
return 0; /* just to satisfy the compiler */
}
/******************************************************************************/
void bigint_shiftleft(bigint_t* a, uint16_t shift){
uint16_t byteshift;
uint16_t i;
uint8_t bitshift;
uint16_t t=0;
byteshift = (shift+3)/8;
bitshift = shift&7;
memmove(a->wordv+byteshift, a->wordv, a->length_B);
memset(a->wordv, 0, byteshift);
if(bitshift!=0){
if(bitshift<=4){ /* shift to the left */
for(i=byteshift; i<a->length_B+byteshift; ++i){
t |= (a->wordv[i])<<bitshift;
a->wordv[i] = (uint8_t)t;
t >>= 8;
}
a->wordv[i] = (uint8_t)t;
byteshift++;
}else{ /* shift to the right */
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])<<(bitshift);
a->wordv[i] = (uint8_t)(t>>8);
}
}
a->length_B += byteshift;
bigint_adjust(a);
}
/******************************************************************************/
void bigint_shiftright(bigint_t* a, uint16_t shift){
uint16_t byteshift;
uint16_t i;
uint8_t bitshift;
uint16_t t=0;
byteshift = shift/8;
bitshift = shift&7;
if(byteshift >= a->length_B){ /* we would shift out more than we have */
bigint_set_zero(a);
return;
}
if(byteshift == a->length_B-1 && bitshift>GET_FBS(a)){
bigint_set_zero(a);
return;
}
if(byteshift){
memmove(a->wordv, a->wordv+byteshift, a->length_B-byteshift);
memset(a->wordv+a->length_B-byteshift, 0, byteshift);
}
if(bitshift!=0){
/* shift to the right */
for(i=a->length_B-byteshift-1; i>0; --i){
t |= (a->wordv[i])<<(8-bitshift);
a->wordv[i] = (uint8_t)(t>>8);
t <<= 8;
}
t |= (a->wordv[0])<<(8-bitshift);
a->wordv[0] = (uint8_t)(t>>8);
}
a->length_B -= byteshift;
bigint_adjust(a);
}
/******************************************************************************/
void bigint_xor(bigint_t* dest, const bigint_t* a){
uint16_t i;
for(i=0; i<a->length_B; ++i){
dest->wordv[i] ^= a->wordv[i];
}
bigint_adjust(dest);
}
/******************************************************************************/
void bigint_set_zero(bigint_t* a){
a->length_B=0;
}
/******************************************************************************/
/* using the Karatsuba-Algorithm */
/* x*y = (xh*yh)*b**2n + ((xh+xl)*(yh+yl) - xh*yh - xl*yl)*b**n + yh*yl */
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);
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);
}
uint16_t i, t=0;
uint8_t x = a->wordv[0];
for(i=0; i<b->length_B; ++i){
t += b->wordv[i]*x;
dest->wordv[i] = (uint8_t)t;
t>>=8;
}
dest->wordv[i] = (uint8_t)t;
dest->length_B=i+1;
bigint_adjust(dest);
return;
}
if(a->length_B<=4 && b->length_B<=4){
uint32_t p=0, q=0;
uint64_t r;
memcpy(&p, a->wordv, a->length_B);
memcpy(&q, b->wordv, b->length_B);
r = (uint64_t)p*(uint64_t)q;
memcpy(dest->wordv, &r, a->length_B+b->length_B);
dest->length_B = a->length_B+b->length_B;
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;
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;
xl.length_B = a->length_B;
xl.info = 0;
}else{
xl.length_B=n;
xl.info = 0;
bigint_adjust(&xl);
xh.wordv = a->wordv+n;
xh.length_B = a->length_B-n;
xh.info = 0;
}
if(b->length_B<=n){
yh.info=0;
yh.length_B = 0;
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.length_B = b->length_B-n;
yh.info = 0;
}
/* 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;
tmp.wordv = tmp_b;
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);
bigint_add_scale_u(dest, &tmp, 2*n);
}
/******************************************************************************/
void bigint_mul_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint8_t s;
s = GET_SIGN(a)?2:0;
s |= GET_SIGN(b)?1:0;
switch(s){
case 0: /* both positive */
bigint_mul_u(dest, a,b);
SET_POS(dest);
break;
case 1: /* a positive, b negative */
bigint_mul_u(dest, a,b);
SET_NEG(dest);
break;
case 2: /* a negative, b positive */
bigint_mul_u(dest, a,b);
SET_NEG(dest);
break;
case 3: /* both negative */
bigint_mul_u(dest, a,b);
SET_POS(dest);
break;
default: /* how can this happen?*/
break;
}
}
/******************************************************************************/
/* square */
/* (xh*b^n+xl)^2 = xh^2*b^2n + 2*xh*xl*b^n + xl^2 */
void bigint_square(bigint_t* dest, const bigint_t* a){
if(a->length_B<=4){
uint64_t r=0;
memcpy(&r, a->wordv, a->length_B);
r = r*r;
memcpy(dest->wordv, &r, 2*a->length_B);
SET_POS(dest);
dest->length_B=2*a->length_B;
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 */
uint8_t buffer[2*n+1];
xl.wordv = a->wordv;
xl.length_B = n;
xh.wordv = a->wordv+n;
xh.length_B = a->length_B-n;
tmp.wordv = buffer;
bigint_square(dest, &xl);
bigint_square(&tmp, &xh);
bigint_add_scale_u(dest, &tmp, 2*n);
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; i<tmp.length_B+byteshift; ++i, ++j){
t = a->wordv[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);
}
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+1<exp->length_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<<i))==0 && (y_.wordv[0]&(1<<i))==0; ++i){
}
bigint_adjust(&x_);
bigint_adjust(&y_);
if(i){
bigint_shiftleft(&g, i);
bigint_shiftright(&x_, i);
bigint_shiftright(&y_, i);
}
u.wordv = u_b;
v.wordv = v_b;
a_.wordv = a_b;
b_.wordv = b_b;
c_.wordv = c_b;
d_.wordv = d_b;
bigint_copy(&u, &x_);
bigint_copy(&v, &y_);
a_.wordv[0] = 1;
a_.length_B = 1;
a_.info = 0;
d_.wordv[0] = 1;
d_.length_B = 1;
d_.info = 0;
bigint_set_zero(&b_);
bigint_set_zero(&c_);
do{
while((u.wordv[0]&1)==0){
bigint_shiftright(&u, 1);
if((a_.wordv[0]&1) || (b_.wordv[0]&1)){
bigint_add_s(&a_, &a_, &y_);
bigint_sub_s(&b_, &b_, &x_);
}
bigint_shiftright(&a_, 1);
bigint_shiftright(&b_, 1);
}
while((v.wordv[0]&1)==0){
bigint_shiftright(&v, 1);
if((c_.wordv[0]&1) || (d_.wordv[0]&1)){
bigint_add_s(&c_, &c_, &y_);
bigint_sub_s(&d_, &d_, &x_);
}
bigint_shiftright(&c_, 1);
bigint_shiftright(&d_, 1);
}
if(bigint_cmp_u(&u, &v)>=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<q){
t = *p;
*p = *q;
*q = t;
++p; --q;
}
}
/******************************************************************************/

858
bigint/bigint.c Normal file
View File

@ -0,0 +1,858 @@
/* bigint.c */
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* \file bigint.c
* \author Daniel Otte
* \date 2010-02-22
*
* \license GPLv3 or later
*
*/
#define STRING2(x) #x
#define STRING(x) STRING2(x)
#define STR_LINE STRING(__LINE__)
#include "bigint.h"
#include <string.h>
#define DEBUG 1
#if DEBUG
#include "cli.h"
#include "uart_lowlevel.h"
#include "bigint_io.h"
#endif
#ifndef MAX
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#define SET_FBS(a, v) do{(a)->info &=~BIGINT_FBS_MASK; (a)->info |= (v);}while(0)
#define GET_FBS(a) ((a)->info&BIGINT_FBS_MASK)
#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 GET_SIGN(a) ((a)->info&BIGINT_NEG_MASK)
/******************************************************************************/
void bigint_adjust(bigint_t* a){
while(a->length_B!=0 && a->wordv[a->length_B-1]==0){
a->length_B--;
}
if(a->length_B==0){
a->info=0;
return;
}
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){
t<<=1;
i--;
}
SET_FBS(a, i);
}
/******************************************************************************/
void bigint_copy(bigint_t* dest, const bigint_t* src){
memcpy(dest->wordv, src->wordv, src->length_B*sizeof(bigint_word_t));
dest->length_B = src->length_B;
dest->info = src->info;
}
/******************************************************************************/
/* this should be implemented in assembly */
void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint16_t i;
bigint_wordplus_t t=0LL;
if(a->length_B < b->length_B){
XCHG_PTR(a,b);
}
for(i=0; i<b->length_B; ++i){
// t = (bigint_wordplus_t)(a->wordv[i]) + (bigint_wordplus_t)(b->wordv[i]) + t;
t += a->wordv[i];
t += b->wordv[i];
dest->wordv[i] = (bigint_word_t)t;
t>>=BIGINT_WORD_SIZE;
}
for(; i<a->length_B; ++i){
t += a->wordv[i];
dest->wordv[i] = (bigint_word_t)t;
t>>=BIGINT_WORD_SIZE;
}
dest->wordv[i++] = (bigint_word_t)t;
dest->length_B = i;
bigint_adjust(dest);
}
/******************************************************************************/
/* 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;
uint16_t scale_w;
uint32_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)){
memset(((uint8_t*)dest->wordv)+dest->length_B*sizeof(bigint_word_t), 0, scale-dest->length_B*sizeof(bigint_word_t));
}
// a->wordv = (const uint32_t*)(((uint8_t*)a->wordv)+(scale&3));
dst = dest->wordv + (scale&(sizeof(bigint_word_t)-1));
for(i=scale/sizeof(bigint_word_t); i<a->length_B+scale_w; ++i,++j){
t += a->wordv[j];
if(dest->length_B>i){
t += dst[i];
}
dst[i] = (bigint_word_t)t;
t>>=BIGINT_WORD_SIZE;
}
while(t){
if(dest->length_B>i){
t += dst[i];
}
dst[i] = (bigint_word_t)t;
t>>=BIGINT_WORD_SIZE;
++i;
}
if(dest->length_B < i){
dest->length_B = i;
}
bigint_adjust(dest);
}
/******************************************************************************/
/* this should be implemented in assembly */
void bigint_sub_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){
int8_t borrow=0;
int8_t r;
bigint_wordplus_signed_t t=0LL;
uint16_t i, min, max;
min = MIN(a->length_B, b->length_B);
max = MAX(a->length_B, b->length_B);
r = bigint_cmp_u(a,b);
if(r==0){
bigint_set_zero(dest);
return;
}
if(b->length_B==0){
bigint_copy(dest, a);
SET_POS(dest);
return;
}
if(a->length_B==0){
bigint_copy(dest, b);
SET_NEG(dest);
return;
}
if(r<0){
bigint_sub_u(dest, b, a);
SET_NEG(dest);
}else{
for(i=0; i<min; ++i){
t = a->wordv[i];
t -= b->wordv[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(;i<max; ++i){
t = a->wordv[i] - borrow;
if(t<0){
borrow = 1;
dest->wordv[i]=(bigint_word_t)t;
}else{
borrow = 0;
dest->wordv[i]=(bigint_word_t)t;
}
}
SET_POS(dest);
dest->length_B = i;
bigint_adjust(dest);
}
}
/******************************************************************************/
int8_t bigint_cmp_u(const bigint_t* a, const bigint_t* b){
if(a->length_B > b->length_B){
return 1;
}
if(a->length_B < b->length_B){
return -1;
}
if(a->length_B==0){
return 0;
}
uint16_t i;
i = a->length_B-1;
do{
if(a->wordv[i]!=b->wordv[i]){
if(a->wordv[i]>b->wordv[i]){
return 1;
}else{
return -1;
}
}
}while(i--);
return 0;
}
/******************************************************************************/
void bigint_add_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint8_t s;
s = GET_SIGN(a)?2:0;
s |= GET_SIGN(b)?1:0;
switch(s){
case 0: /* both positive */
bigint_add_u(dest, a,b);
SET_POS(dest);
break;
case 1: /* a positive, b negative */
bigint_sub_u(dest, a, b);
break;
case 2: /* a negative, b positive */
bigint_sub_u(dest, b, a);
break;
case 3: /* both negative */
bigint_add_u(dest, a, b);
SET_NEG(dest);
break;
default: /* how can this happen?*/
break;
}
}
/******************************************************************************/
void bigint_sub_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint8_t s;
s = GET_SIGN(a)?2:0;
s |= GET_SIGN(b)?1:0;
switch(s){
case 0: /* both positive */
bigint_sub_u(dest, a,b);
break;
case 1: /* a positive, b negative */
bigint_add_u(dest, a, b);
SET_POS(dest);
break;
case 2: /* a negative, b positive */
bigint_add_u(dest, a, b);
SET_NEG(dest);
break;
case 3: /* both negative */
bigint_sub_u(dest, b, a);
break;
default: /* how can this happen?*/
break;
}
}
/******************************************************************************/
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){
case 0: /* both positive */
return bigint_cmp_u(a, b);
break;
case 1: /* a positive, b negative */
return 1;
break;
case 2: /* a negative, b positive */
return -1;
break;
case 3: /* both negative */
return bigint_cmp_u(b, a);
break;
default: /* how can this happen?*/
break;
}
return 0; /* just to satisfy the compiler */
}
/******************************************************************************/
void bigint_shiftleft(bigint_t* a, uint16_t shift){
uint16_t byteshift, word_alloc;
int16_t i;
uint8_t bitshift;
bigint_word_t *p;
bigint_wordplus_t t=0;
if(shift==0){
return;
}
byteshift = shift/8;
bitshift = shift&7;
for(i=0;i<=byteshift/sizeof(bigint_word_t); ++i){
a->wordv[a->length_B+i] = 0;
}
if(byteshift){
memmove(((uint8_t*)a->wordv)+byteshift, a->wordv, a->length_B*sizeof(bigint_word_t));
memset(a->wordv, 0, byteshift);
}
p = (bigint_word_t*)(((uint8_t*)a->wordv)+byteshift);
word_alloc = a->length_B+(byteshift+sizeof(bigint_word_t)-1)/sizeof(bigint_word_t)+1;
a->wordv[word_alloc-1]=0;
if(bitshift!=0){
for(i=0; i<a->length_B; ++i){
t |= ((bigint_wordplus_t)p[i])<<bitshift;
p[i] = (bigint_word_t)t;
t >>= BIGINT_WORD_SIZE;
}
p[i] = (bigint_word_t)t;
}
a->length_B = word_alloc;
bigint_adjust(a);
}
/******************************************************************************/
void bigint_shiftright(bigint_t* a, uint16_t shift){
uint16_t byteshift;
uint16_t i;
uint8_t bitshift;
bigint_wordplus_t t=0;
byteshift = shift/8;
bitshift = shift&7;
if(byteshift >= a->length_B*sizeof(bigint_word_t)){ /* we would shift out more than we have */
bigint_set_zero(a);
return;
}
if(byteshift == a->length_B*sizeof(bigint_word_t)-1 && bitshift>GET_FBS(a)){
bigint_set_zero(a);
return;
}
if(byteshift){
memmove(a->wordv, (uint8_t*)a->wordv+byteshift, a->length_B-byteshift);
memset((uint8_t*)a->wordv+a->length_B-byteshift, 0, byteshift);
}
byteshift /= sizeof(bigint_word_t);
if(bitshift!=0){
/* shift to the right */
for(i=a->length_B-byteshift-1; i>0; --i){
t |= ((bigint_wordplus_t)(a->wordv[i]))<<(BIGINT_WORD_SIZE-bitshift);
a->wordv[i] = (bigint_word_t)(t>>BIGINT_WORD_SIZE);
t <<= BIGINT_WORD_SIZE;
}
t |= ((bigint_wordplus_t)(a->wordv[0]))<<(BIGINT_WORD_SIZE-bitshift);
a->wordv[0] = (bigint_word_t)(t>>BIGINT_WORD_SIZE);
}
a->length_B -= ((shift/8)+sizeof(bigint_word_t)-1)/sizeof(bigint_word_t);
bigint_adjust(a);
}
/******************************************************************************/
void bigint_xor(bigint_t* dest, const bigint_t* a){
uint16_t i;
for(i=0; i<a->length_B; ++i){
dest->wordv[i] ^= a->wordv[i];
}
bigint_adjust(dest);
}
/******************************************************************************/
void bigint_set_zero(bigint_t* a){
a->length_B=0;
}
/******************************************************************************/
/* using the Karatsuba-Algorithm */
/* x*y = (xh*yh)*b**2n + ((xh+xl)*(yh+yl) - xh*yh - xl*yl)*b**n + yh*yl */
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);
return;
}
if(dest==a || dest==b){
bigint_t d;
bigint_word_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);
}
bigint_wordplus_t i, t=0;
bigint_word_t x = a->wordv[0];
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;
bigint_adjust(dest);
return;
}
if(a->length_B<=4/sizeof(bigint_word_t) && b->length_B<=4/sizeof(bigint_word_t)){
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;
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;
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;
xl.length_B = a->length_B;
xl.info = 0;
}else{
xl.length_B=n;
xl.info = 0;
bigint_adjust(&xl);
xh.wordv = a->wordv+n;
xh.length_B = a->length_B-n;
xh.info = 0;
}
if(b->length_B<=n){
yh.info=0;
yh.length_B = 0;
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.length_B = b->length_B-n;
yh.info = 0;
}
/* now we have split up a and b */
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;
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));
}
/******************************************************************************/
void bigint_mul_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
uint8_t s;
s = GET_SIGN(a)?2:0;
s |= GET_SIGN(b)?1:0;
switch(s){
case 0: /* both positive */
bigint_mul_u(dest, a,b);
SET_POS(dest);
break;
case 1: /* a positive, b negative */
bigint_mul_u(dest, a,b);
SET_NEG(dest);
break;
case 2: /* a negative, b positive */
bigint_mul_u(dest, a,b);
SET_NEG(dest);
break;
case 3: /* both negative */
bigint_mul_u(dest, a,b);
SET_POS(dest);
break;
default: /* how can this happen?*/
break;
}
}
/******************************************************************************/
/* square */
/* (xh*b^n+xl)^2 = xh^2*b^2n + 2*xh*xl*b^n + xl^2 */
void bigint_square(bigint_t* dest, const bigint_t* a){
if(a->length_B*sizeof(bigint_word_t)<=4){
uint64_t r=0;
memcpy(&r, a->wordv, a->length_B*sizeof(bigint_word_t));
r = r*r;
memcpy(dest->wordv, &r, 2*a->length_B*sizeof(bigint_word_t));
SET_POS(dest);
dest->length_B=2*a->length_B;
bigint_adjust(dest);
return;
}
if(dest==a){
bigint_t d;
bigint_word_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 */
bigint_word_t buffer[2*n+1];
xl.wordv = a->wordv;
xl.length_B = n;
xh.wordv = &(a->wordv[n]);
xh.length_B = a->length_B-n;
tmp.wordv = buffer;
// cli_putstr("\r\nDBG (a): xl: "); bigint_print_hex(&xl);
// cli_putstr("\r\nDBG (b): xh: "); bigint_print_hex(&xh);
bigint_square(dest, &xl);
// cli_putstr("\r\nDBG (1): xl**2: "); bigint_print_hex(dest);
bigint_square(&tmp, &xh);
// cli_putstr("\r\nDBG (2): xh**2: "); bigint_print_hex(&tmp);
bigint_add_scale_u(dest, &tmp, 2*n*sizeof(bigint_word_t));
// cli_putstr("\r\nDBG (3): xl**2 + xh**2*n**2: "); bigint_print_hex(dest);
bigint_mul_u(&tmp, &xl, &xh);
// cli_putstr("\r\nDBG (4): xl*xh: "); bigint_print_hex(&tmp);
bigint_shiftleft(&tmp, 1);
// cli_putstr("\r\nDBG (5): xl*xh*2: "); bigint_print_hex(&tmp);
bigint_add_scale_u(dest, &tmp, n*sizeof(bigint_word_t));
// cli_putstr("\r\nDBG (6): x**2: "); bigint_print_hex(dest);
// cli_putstr("\r\n");
}
/******************************************************************************/
#define cli_putstr(a)
#define bigint_print_hex(a)
#define cli_hexdump_rev(a,b)
#define uart_flush(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;
if(a->length_B < b->length_B+word_shift){
cli_putstr("\r\nDBG: *bang*\r\n");
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; i<tmp.length_B+word_shift; ++i, ++j){
t = a->wordv[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){
cli_putstr("\r\nDBG: *boom*\r\n");
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);
cli_putstr("\r\nDBG: (a) = "); bigint_print_hex(a);
if(r->length_B==0 || a->length_B==0){
return;
}
if((r->length_B*sizeof(bigint_word_t)<=4) && (a->length_B*sizeof(bigint_word_t)<=4)){
uint32_t p=0, q=0;
memcpy(&p, a->wordv, a->length_B*sizeof(bigint_word_t));
memcpy(&q, r->wordv, r->length_B*sizeof(bigint_word_t));
p %= q;
memcpy(a->wordv, &p, a->length_B*sizeof(bigint_word_t));
bigint_adjust(a);
cli_putstr("\r\nDBG: (0) = "); bigint_print_hex(a);
return;
}
uint16_t shift;
while(a->length_B > r->length_B){
shift = (a->length_B-r->length_B)*8*sizeof(bigint_word_t)+GET_FBS(a)-rfbs-1;
cli_putstr("\r\nDBG: (p) shift = "); cli_hexdump_rev(&shift, 2);
uart_flush(0);
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)){
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);
cli_putstr("\r\nDBG: (2) = "); bigint_print_hex(a);
}
while(bigint_cmp_u(a,r)>=0){
bigint_sub_u(a,a,r);
cli_putstr("\r\nDBG: (3) = "); bigint_print_hex(a);
}
bigint_adjust(a);
cli_putstr("\r\nDBG: (a) = "); bigint_print_hex(a);
cli_putstr("\r\n");
}
/******************************************************************************/
/* 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;
bigint_word_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+1<exp->length_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;
}
bigint_word_t g_b[i+2], x_b[x->length_B-i], y_b[y->length_B-i];
bigint_word_t u_b[x->length_B-i], v_b[y->length_B-i];
bigint_word_t a_b[y->length_B+2], c_b[y->length_B+2];
bigint_word_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<<i))==0 && (y_.wordv[0]&(1<<i))==0; ++i){
}
bigint_adjust(&x_);
bigint_adjust(&y_);
if(i){
bigint_shiftleft(&g, i);
bigint_shiftright(&x_, i);
bigint_shiftright(&y_, i);
}
u.wordv = u_b;
v.wordv = v_b;
a_.wordv = a_b;
b_.wordv = b_b;
c_.wordv = c_b;
d_.wordv = d_b;
bigint_copy(&u, &x_);
bigint_copy(&v, &y_);
a_.wordv[0] = 1;
a_.length_B = 1;
a_.info = 0;
d_.wordv[0] = 1;
d_.length_B = 1;
d_.info = 0;
bigint_set_zero(&b_);
bigint_set_zero(&c_);
do{
while((u.wordv[0]&1)==0){
bigint_shiftright(&u, 1);
if((a_.wordv[0]&1) || (b_.wordv[0]&1)){
bigint_add_s(&a_, &a_, &y_);
bigint_sub_s(&b_, &b_, &x_);
}
bigint_shiftright(&a_, 1);
bigint_shiftright(&b_, 1);
}
while((v.wordv[0]&1)==0){
bigint_shiftright(&v, 1);
if((c_.wordv[0]&1) || (d_.wordv[0]&1)){
bigint_add_s(&c_, &c_, &y_);
bigint_sub_s(&d_, &d_, &x_);
}
bigint_shiftright(&c_, 1);
bigint_shiftright(&d_, 1);
}
if(bigint_cmp_u(&u, &v)>=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 = (uint8_t*)(a->wordv);
q = ((uint8_t*)p)+a->length_B*sizeof(bigint_word_t)-1;
while(p<q){
t = *p;
*p = *q;
*q = t;
++p; --q;
}
}
/******************************************************************************/

74
bigint/bigint.h Normal file
View File

@ -0,0 +1,74 @@
/* bigint.h */
/*
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 <http://www.gnu.org/licenses/>.
*/
/**
* \file bigint.h
* \author Daniel Otte
* \date 2010-02-22
*
* \license GPLv3 or later
*
*/
#ifndef BIGINT_H_
#define BIGINT_H_
#include <stdint.h>
typedef uint32_t bigint_word_t;
typedef uint64_t bigint_wordplus_t;
typedef int64_t bigint_wordplus_signed_t;
#define BIGINT_WORD_SIZE 32
#define BIGINT_FBS_MASK (BIGINT_WORD_SIZE-1) /* the last five bits indicate which is the first bit set */
#define BIGINT_NEG_MASK 0x80 /* this bit indicates a negative value */
typedef struct{
uint16_t length_B;
uint8_t info;
bigint_word_t *wordv; /* word vector, pointing to the LSB */
}bigint_t;
/******************************************************************************/
void bigint_adjust(bigint_t* a);
void bigint_copy(bigint_t* dest, const bigint_t* src);
void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b);
void bigint_add_scale_u(bigint_t* dest, const bigint_t* a, uint16_t scale);
void bigint_sub_u(bigint_t* dest, const bigint_t* a, const bigint_t* b);
int8_t bigint_cmp_u(const bigint_t * a, const bigint_t * b);
void bigint_add_s(bigint_t* dest, const bigint_t* a, const bigint_t* b);
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);
void bigint_shiftleft(bigint_t* a, uint16_t shift);
void bigint_shiftright(bigint_t* a, uint16_t shift);
void bigint_xor(bigint_t* dest, const bigint_t* a);
void bigint_set_zero(bigint_t* a);
void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* b);
void bigint_mul_s(bigint_t* dest, const bigint_t* a, const bigint_t* b);
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);
void bigint_reduce(bigint_t* a, const bigint_t* r);
void bigint_expmod_u(bigint_t* dest, const bigint_t* a, const bigint_t* exp, const bigint_t* r);
void bigint_gcdext(bigint_t* gcd, bigint_t* a, bigint_t* b, const bigint_t* x, const bigint_t* y);
void bigint_inverse(bigint_t* dest, const bigint_t* a, const bigint_t* m);
void bigint_changeendianess(bigint_t* a);
/******************************************************************************/
#endif /*BIGINT_H_*/

159
bigint/bigint_io.c Normal file
View File

@ -0,0 +1,159 @@
/* bigint_io.c */
/*
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
*/
#include "cli.h"
#include "hexdigit_tab.h"
#include "bigint.h"
#include <stdlib.h>
#include <string.h>
void bigint_print_hex(const bigint_t* a){
if(a->length_B==0){
cli_putc('0');
return;
}
if(a->info&BIGINT_NEG_MASK){
cli_putc('-');
}
// cli_putc((a->info&BIGINT_NEG_MASK)?'-':'+'); /* print sign */
/* if(a->wordv[a->length_B-1]<0x10){
cli_putc(hexdigit_tab_uc[a->wordv[a->length_B-1]]);
cli_hexdump_rev(a->wordv, a->length_B-1);
} else {
*/
// cli_hexdump_rev(a->wordv, a->length_B*sizeof(bigint_word_t));
// }
uint32_t idx;
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){
x = *p >> 4;
y = *p & 0xf;
if(x!=0 || print_zero!=0){
cli_putc(hexdigit_tab_lc[x]);
}
if(x){
print_zero = 1;
}
if(y!=0 || print_zero!=0){
cli_putc(hexdigit_tab_lc[y]);
}
if(y){
print_zero = 1;
}
--p;
}
}
#define BLOCKSIZE 32
static uint8_t char2nibble(char c){
if(c>='0' && c <='9'){
return c-'0';
}
c |= 'A'^'a'; /* to lower case */
if(c>='a' && c <='f'){
return c-'a'+10;
}
return 0xff;
}
static uint16_t read_byte(void){
uint8_t t1, t2;
char c;
c = cli_getc_cecho();
if(c=='-'){
return 0x0500;
}
t1 = char2nibble(c);
if(t1 == 0xff){
return 0x0100;
}
c = cli_getc_cecho();
t2 = char2nibble(c);
if(t2 == 0xff){
return 0x0200|t1;
}
return (t1<<4)|t2;
}
uint8_t bigint_read_hex_echo(bigint_t* a){
uint16_t allocated=0;
uint8_t shift4=0;
uint16_t t;
a->length_B = 0;
a->wordv = NULL;
a->info = 0;
for(;;){
if(allocated-a->length_B < 1){
bigint_word_t *p;
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);
a->wordv=p;
}
t = read_byte();
if(a->length_B==0){
if(t&0x0400){
/* got minus */
a->info |= BIGINT_NEG_MASK;
continue;
}else{
if(t==0x0100){
free(a->wordv);
a->wordv=NULL;
return 1;
}
}
}
if(t<=0x00ff){
((uint8_t*)(a->wordv))[a->length_B++] = (uint8_t)t;
}else{
if(t&0x0200){
shift4 = 1;
((uint8_t*)(a->wordv))[a->length_B++] = (uint8_t)((t&0x0f)<<4);
}
break;
}
}
/* we have to reverse the byte array */
uint8_t tmp;
uint8_t *p, *q;
p = (uint8_t*)(a->wordv);
q = (uint8_t*)a->wordv+a->length_B-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);
if(shift4){
bigint_adjust(a);
bigint_shiftright(a, 4);
}else{
bigint_adjust(a);
}
return 0;
}

28
bigint/bigint_io.h Normal file
View File

@ -0,0 +1,28 @@
/* bigint_io.h */
/*
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
*/
#ifndef BIGINT_IO_H_
#define BIGINT_IO_H_
#include "bigint.h"
void bigint_print_hex(const bigint_t* a);
uint8_t bigint_read_hex_echo(bigint_t* a);
#endif /* BIGINT_IO_H_ */

View File

@ -1,7 +1,7 @@
#!/usr/bin/ruby
# bigint_test.rb
=begin
This file is part of the ARM-Crypto-Lib.
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2008, 2009 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
@ -246,6 +246,66 @@ def mul_test(a,b)
return false
end
################################################################################
# add_scale_test #
################################################################################
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)
$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)
$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)
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))
$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))
return false
end
return false
end
################################################################################
# square_test #
################################################################################
@ -311,9 +371,8 @@ def reduce_test(a,b)
$sp.print(b.to_s(16)+" ")
line=''
begin
line_tmp = $sp.gets()
line_tmp = '' if line_tmp==nil
line += line_tmp
line = $sp.gets()
line = '' if line==nil
puts("DBG got: "+line) if $debug
if /^Error:.*/.match(line)
puts line
@ -372,9 +431,8 @@ def expmod_test(a,b,c)
$sp.print(c.to_s(16)+" ")
line=''
begin
line_tmp = $sp.gets()
line_tmp = '' if line_tmp==nil
line += line_tmp
line = $sp.gets()
line = '' if line==nil
puts("DBG got: "+line) if $debug
if /^Error:.*/.match(line)
puts line

14
mkfiles/bigint_c.mk Normal file
View File

@ -0,0 +1,14 @@
# Makefile for BigInt
ALGO_NAME := BIGINT_C
# comment out the following line for removement of BigInt from the build process
AUX += $(ALGO_NAME)
$(ALGO_NAME)_DIR := bigint/
$(ALGO_NAME)_INCDIR := memxor/ noekeon/
$(ALGO_NAME)_OBJ := bigint.o bigint_io.o
$(ALGO_NAME)_TEST_BIN := main-bigint-test.o $(CLI_STD) \
performance_test.o noekeon.o noekeon_prng.o memxor.o
$(ALGO_NAME)_PERFORMANCE_TEST := performance

View File

@ -90,13 +90,12 @@ void cli_putstr(const char* s){
cli_tx(*s++);
}
/**
* \brief reads a line or max n characters from the console
* Writes characters from the console into the supplied buffer until a '\r'
* character is received or until n character a read (whatever happens first).
* The string will always be terminated by a '\0' character, so the buffer
* should have at least a size of n+1.
* should have at least a size of n+1.
*/
uint8_t cli_getsn(char* s, uint32_t n){
char c;
@ -109,6 +108,22 @@ uint8_t cli_getsn(char* s, uint32_t n){
return (c=='\r')?0:1;
}
/**
* \brief reads a line or max n characters from the console and echos the characters back
* Writes characters from the console into the supplied buffer until a '\r'
* character is received or until n character a read (whatever happens first).
* The string will always be terminated by a '\0' character, so the buffer
* should have at least a size of n+1.
*/
uint8_t cli_getsn_cecho(char* s, uint32_t n){
uint8_t echo_backup,r ;
echo_backup = cli_echo;
cli_echo = 1;
r = cli_getsn(s, n);
cli_echo = echo_backup;
return r;
}
void cli_hexdump_byte(uint8_t byte){
cli_tx(hexdigit_tab[byte>>4]);
cli_tx(hexdigit_tab[byte & 0xf]);
@ -309,7 +324,7 @@ uint8_t cli_completion(char* buffer, uint16_t maxcmdlength, const cmdlist_entry_
ref[0]='\0';
/* check if we are behind the first word */
while(buffer[i]){
if(!isgraph(buffer[i++]))
if(!isgraph((uint8_t)(buffer[i++])))
return 0;
}
for(;;){

View File

@ -56,6 +56,7 @@ extern uint8_t cli_echo;
void cli_putc(char c);
uint16_t cli_getc(void);
uint16_t cli_getc_cecho(void);
uint8_t cli_getsn_cecho(char* s, uint32_t n);
uint8_t cli_getsn(char* s, uint32_t n);
void cli_putstr(const char* s);
void cli_hexdump(const void* data, uint32_t length);

View File

@ -70,8 +70,8 @@ void dump(char* s){
char tstr[9];
if(s){
s=strstrip(s);
if(isalpha(*s)){
while(isalpha(*s))
if(isalpha((uint8_t)(*s))){
while(isalpha((uint8_t)(*s)))
++s;
}
char* eptr;

View File

@ -1,6 +1,6 @@
/* hw_regs.h */
/*
This file is part of the ARM-Crypto-Lib.
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
@ -25,7 +25,9 @@
#define SET_REG(r,v) (*((volatile uint32_t*)(r))) = (v)
#define GET_REG(r) (*((volatile uint32_t*)(r)))
#define HW_REG(r) (*((volatile uint32_t*)(r)))
#define _BV(x) (1<<(x))
#define HW16_REG(r) (*((volatile uint16_t*)(r)))
#define HW8_REG(r) (*((volatile uint8_t*)(r)))
#define _BV(x) (1UL<<(x))
#define SYSCTL_BASE 0x400FE000
#define DID0_OFFSET 0x000
@ -87,6 +89,48 @@
#define RCC2_BYPASS2 11
#define RCC2_OSCSR2 4
#define RCGC0_WDT0 3
#define RCGC0_HIB 6
#define RCGC0_MAXADC0SPD 8
#define RCGC0_MAXADC1SPD 10
#define RCGC0_ADC0 16
#define RCGC0_ADC1 17
#define RCGC0_CAN0 24
#define RCGC0_CAN1 25
#define RCGC0_WDT1 28
#define RCGC1_UART0 0
#define RCGC1_UART1 1
#define RCGC1_UART2 2
#define RCGC1_SSI0 4
#define RCGC1_SSI1 5
#define RCGC1_I2C0 12
#define RCGC1_I2C1 14
#define RCGC1_TIMER0 16
#define RCGC1_TIMER1 17
#define RCGC1_TIMER2 18
#define RCGC1_TIMER3 19
#define RCGC1_COMP0 24
#define RCGC1_COMP1 25
#define RCGC1_COMP2 26
#define RCGC1_I2S0 28
#define RCGC1_EPI0 30
#define RCGC2_GPIOA 0
#define RCGC2_GPIOB 1
#define RCGC2_GPIOC 2
#define RCGC2_GPIOD 3
#define RCGC2_GPIOE 4
#define RCGC2_GPIOF 5
#define RCGC2_GPIOG 6
#define RCGC2_GPIOH 7
#define RCGC2_GPIOJ 8
#define RCGC2_UDMA 13
#define RCGC2_USB0 16
#define RCGC2_EMAC0 28
#define RCGC2_EPHY0 30
#define RIS_MOSCPUPRIS 8
#define RIS_USBPLLLRIS 7
#define RIS_PLLLRIS 6

563
test_src/main-bigint-test.c Normal file
View File

@ -0,0 +1,563 @@
/* main-bigint-test.c */
/*
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2008, 2009, 2010 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 <http://www.gnu.org/licenses/>.
*/
/*
* bigint test-suit
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "cli.h"
#include "dump.h"
#include "uart_lowlevel.h"
#include "sysclock.h"
#include "hw_gptm.h"
#include "noekeon.h"
#include "noekeon_prng.h"
#include "bigint.h"
#include "bigint_io.h"
#include "performance_test.h"
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
char* algo_name = "BigInt";
void uart0_putc(char byte){
uart_putc(UART_0, byte);
}
char uart0_getc(void){
return uart_getc(UART_0);
}
/*****************************************************************************
* additional validation-functions *
*****************************************************************************/
void test_echo_bigint(void){
bigint_t a;
cli_putstr("\r\necho test\r\n");
for(;;){
cli_putstr("\r\nenter hex number:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end echo test");
return;
}
cli_putstr("\r\necho: ");
bigint_print_hex(&a);
cli_putstr("\r\n");
free(a.wordv);
}
}
void test_add_bigint(void){
bigint_t a, b, c;
cli_putstr("\r\nadd test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end add test");
return;
}
cli_putstr("\r\nenter b:");
if(bigint_read_hex_echo(&b)){
free(a.wordv);
cli_putstr("\r\n end add test");
return;
}
cli_putstr("\r\n ");
bigint_print_hex(&a);
cli_putstr(" + ");
bigint_print_hex(&b);
cli_putstr(" = ");
bigint_word_t *c_b;
c_b = malloc(((a.length_B>b.length_B)?a.length_B:b.length_B)*sizeof(bigint_word_t)+8);
if(c_b==NULL){
cli_putstr("\n\rERROR: Out of memory!");
free(a.wordv);
free(b.wordv);
continue;
}
c.wordv = c_b;
bigint_add_s(&c, &a, &b);
bigint_print_hex(&c);
cli_putstr("\r\n");
free(a.wordv);
free(b.wordv);
free(c_b);
}
}
void test_add_scale_bigint(void){
bigint_t a, b, c;
uint16_t scale;
cli_putstr("\r\nadd-scale test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end add test");
return;
}
cli_putstr("\r\nenter b:");
if(bigint_read_hex_echo(&b)){
cli_putstr("\r\n end add test");
return;
}
cli_putstr("\r\nenter scale:");
{
char str[8];
cli_getsn_cecho(str, 7);
scale = atoi(str);
}
/*
if(bigint_read_hex_echo(&scale)){
free(scale.wordv);
cli_putstr("\r\n end add test");
return;
}
*/
cli_putstr("\r\n ");
bigint_print_hex(&a);
cli_putstr(" + ");
bigint_print_hex(&b);
cli_putstr("<<8*");
cli_hexdump_rev(&scale, 2);
cli_putstr(" = ");
bigint_word_t *c_b;
c_b = malloc(((a.length_B>(b.length_B+scale))?a.length_B:(b.length_B+scale))*sizeof(bigint_word_t)+8);
if(c_b==NULL){
cli_putstr("\n\rERROR: Out of memory!");
free(a.wordv);
free(b.wordv);
continue;
}
bigint_copy(&c, &a);
c.wordv = c_b;
bigint_add_scale_u(&c, &b, scale);
bigint_print_hex(&c);
cli_putstr("\r\n");
free(a.wordv);
free(b.wordv);
free(c_b);
}
}
void test_mul_bigint(void){
bigint_t a, b, c;
cli_putstr("\r\nmul test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end mul test");
return;
}
cli_putstr("\r\nenter b:");
if(bigint_read_hex_echo(&b)){
free(a.wordv);
cli_putstr("\r\n end mul test");
return;
}
cli_putstr("\r\n ");
bigint_print_hex(&a);
cli_putstr(" * ");
bigint_print_hex(&b);
cli_putstr(" = ");
bigint_word_t *c_b;
c_b = malloc((((a.length_B>b.length_B)?a.length_B:b.length_B)+1)*2*sizeof(bigint_word_t));
if(c_b==NULL){
cli_putstr("\n\rERROR: Out of memory!");
free(a.wordv);
free(b.wordv);
continue;
}
c.wordv = c_b;
bigint_mul_s(&c, &a, &b);
bigint_print_hex(&c);
cli_putstr("\r\n");
free(a.wordv);
free(b.wordv);
free(c_b);
}
}
void test_square_bigint(void){
bigint_t a, c;
cli_putstr("\r\nsquare test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end square test");
return;
}
cli_putstr("\r\n ");
bigint_print_hex(&a);
cli_putstr("**2 = ");
bigint_word_t *c_b;
c_b = malloc(a.length_B*2*sizeof(bigint_word_t));
if(c_b==NULL){
cli_putstr("\n\rERROR: Out of memory!");
free(a.wordv);
continue;
}
c.wordv = c_b;
bigint_square(&c, &a);
bigint_print_hex(&c);
cli_putstr("\r\n");
free(a.wordv);
free(c_b);
}
}
void test_reduce_bigint(void){
bigint_t a, b;
cli_putstr("\r\nreduce test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end reduce test");
return;
}
cli_putstr("\r\nenter b:");
if(bigint_read_hex_echo(&b)){
free(a.wordv);
cli_putstr("\r\n end reduce test");
return;
}
cli_putstr("\r\n ");
bigint_print_hex(&a);
cli_putstr(" % ");
bigint_print_hex(&b);
cli_putstr(" = ");
bigint_reduce(&a, &b);
bigint_print_hex(&a);
cli_putstr("\r\n");
free(a.wordv);
free(b.wordv);
}
}
/* d = a**b % c */
void test_expmod_bigint(void){
bigint_t a, b, c, d;
bigint_word_t *d_b;
cli_putstr("\r\nreduce test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end expmod test");
return;
}
cli_putstr("\r\nenter b:");
if(bigint_read_hex_echo(&b)){
free(a.wordv);
cli_putstr("\r\n end expmod test");
return;
}
cli_putstr("\r\nenter c:");
if(bigint_read_hex_echo(&c)){
free(a.wordv);
free(b.wordv);
cli_putstr("\r\n end expmod test");
return;
}
d_b = malloc(c.length_B*sizeof(bigint_word_t));
if(d_b==NULL){
cli_putstr("\n\rERROR: Out of memory!");
free(a.wordv);
free(b.wordv);
free(c.wordv);
continue;
}
d.wordv = d_b;
cli_putstr("\r\n ");
bigint_print_hex(&a);
cli_putstr("**");
bigint_print_hex(&b);
cli_putstr(" % ");
bigint_print_hex(&c);
cli_putstr(" = ");
bigint_expmod_u(&d, &a, &b, &c);
bigint_print_hex(&d);
cli_putstr("\r\n");
free(a.wordv);
free(b.wordv);
free(c.wordv);
free(d.wordv);
}
}
void test_gcdext_bigint(void){
bigint_t a, b, c, d, e;
cli_putstr("\r\ngcdext test\r\n");
for(;;){
cli_putstr("\r\nenter a:");
if(bigint_read_hex_echo(&a)){
cli_putstr("\r\n end gcdext test");
return;
}
cli_putstr("\r\nenter b:");
if(bigint_read_hex_echo(&b)){
free(a.wordv);
cli_putstr("\r\n end gcdext test");
return;
}
c.wordv = malloc(((a.length_B<b.length_B)?a.length_B:b.length_B)*sizeof(bigint_word_t));
d.wordv = malloc((1+(a.length_B>b.length_B)?a.length_B:b.length_B)*sizeof(bigint_word_t));
e.wordv = malloc((1+(a.length_B>b.length_B)?a.length_B:b.length_B)*sizeof(bigint_word_t));
cli_putstr("\r\n gcdext( ");
bigint_print_hex(&a);
cli_putstr(", ");
bigint_print_hex(&b);
cli_putstr(") => ");
bigint_gcdext(&c, &d, &e, &a, &b);
cli_putstr("a = ");
bigint_print_hex(&d);
cli_putstr("; b = ");
bigint_print_hex(&e);
cli_putstr("; gcd = ");
bigint_print_hex(&c);
cli_putstr("\r\n");
free(a.wordv);
free(b.wordv);
free(c.wordv);
free(d.wordv);
free(e.wordv);
}
}
void test_simple(void){
bigint_t a, b, c;
bigint_word_t a_b[1], b_b[1], c_b[2];
a.wordv=a_b;
b.wordv=b_b;
c.wordv=c_b;
a.length_B = 1;
b.length_B = 1;
a_b[0] = 1;
b_b[0] = 2;
bigint_add_u(&c, &a, &b);
cli_putstr("\r\n 1+2=");
bigint_print_hex(&c);
}
/*
void test_mul_simple(void){
bigint_t a, b, c;
uint8_t a_b[5] = {0x79, 0x36, 0x9e, 0x72, 0xec};
uint8_t b_b[5] = {0x4a, 0x47, 0x0d, 0xec, 0xfd};
uint8_t c_b[12];
a.wordv=a_b;
b.wordv=b_b;
c.wordv=c_b;
a.length_B = 5;
b.length_B = 5;
bigint_adjust(&a);
bigint_adjust(&b);
bigint_mul_s(&c, &a, &b);
cli_putstr("\r\n test: ");
bigint_print_hex(&c);
}
*/
// -3d1d 6db7 8251 f371 * -7a18 3791 d18b b7c5 = 1d25ce4fdf93390f8d6c709f4d711cf5
// -20538248dece6d29068d * 400b1411b874f81394c6 = -81646b193d95136a6fedb73cee6d30c39fb950e
// -BC8B 7D53 4921 853D * 0DDA 6044 00CE DDE6 = -a33eb0c5847db8837589c22db395dce
void test_mul_simple(void){
bigint_t a, b, c;
// uint8_t a_b[10] = {0x8d, 0x06, 0x29, 0x6d, 0xce, 0xde, 0x48, 0x82, 0x53, 0x20};
// uint8_t b_b[10] = {0xc6, 0x94, 0x13, 0xf8, 0x74, 0xb8, 0x11, 0x14, 0x0b, 0x40};
uint8_t a_b[8] = {0x3d, 0x85, 0x21, 0x49, 0x53, 0x7d, 0x8b, 0xbc};
uint8_t b_b[8] = {0xe6, 0xdd, 0xce, 0x00, 0x44, 0x60, 0xda, 0x0d};
uint8_t c_b[16];
a.wordv=(bigint_word_t*)a_b;
b.wordv=(bigint_word_t*)b_b;
c.wordv=(bigint_word_t*)c_b;
a.length_B = 8/sizeof(bigint_word_t);
b.length_B = 8/sizeof(bigint_word_t);
a.info=0x80;
bigint_adjust(&a);
bigint_adjust(&b);
bigint_mul_s(&c, &a, &b);
cli_putstr("\r\n test: ");
bigint_print_hex(&a);
cli_putstr(" * ");
bigint_print_hex(&b);
cli_putstr(" = ");
bigint_print_hex(&c);
}
// f4 b86a 2220 0774 437d 70e6 **2 = e9f00f29ca1c876a7a682bd1e04f6925caffd6660ea4
/*
uint8_t square_test_data[] PROGMEM = {
0xA0, 0x3C, 0x23, 0x9F, 0x7A, 0xFC, 0x60, 0xEB, 0x96, 0xC2, 0xA8, 0xAC, 0xC3, 0xC9, 0x9E, 0xEC,
0x4A, 0xF0, 0x1C, 0xB2, 0x36, 0x68, 0xD6, 0x4D, 0x3E, 0x4F, 0x8E, 0x55, 0xEA, 0x52, 0x46, 0x68,
0x6E, 0x18, 0x88, 0x37, 0x03, 0x70, 0xBD, 0x01, 0x60, 0xE2, 0xD6, 0x12, 0xA0, 0x0E, 0xD2, 0x72,
0x0D, 0x9D, 0x9F, 0x03, 0xC5, 0x81, 0xCA, 0x6E, 0x88, 0x1E, 0xF5, 0xD8, 0x14, 0x15, 0x30, 0xEB,
0x28, 0x7C, 0x80, 0x07, 0x34, 0x05, 0x5D, 0xAA, 0xDC, 0xA8, 0xAA, 0x88, 0xC5, 0xE5, 0xC9, 0xFE,
0x9C, 0xA1, 0xCE, 0xC2, 0x09, 0x0D, 0xC4, 0xC8, 0xD3, 0xE7, 0x3A, 0xF3, 0xEF, 0xDF, 0xAE, 0x07,
0xEC, 0xC7, 0x83, 0x50, 0x9F, 0x6D, 0xB9, 0x28, 0x77, 0xC0, 0xFE, 0x69, 0xB2, 0x2E, 0x55, 0x90,
0x50, 0xED, 0xE0, 0xA1, 0x4D, 0x3D, 0x38, 0xC9, 0x0E, 0xCD, 0x04, 0x3B, 0x64, 0x3F, 0x56, 0xC5,
0xC3, 0x9E, 0x89, 0x81, 0x44, 0x60, 0xBA, 0x8E, 0x88, 0xA4, 0xA3, 0x42, 0x7B, 0x06, 0x93, 0x1C,
0x6B, 0x04, 0x29, 0xF9, 0xDD, 0xFF, 0xB0, 0x48, 0x2F, 0x6D, 0xD1, 0x0F, 0x7D, 0xA6, 0x26, 0xD8,
0xEF, 0x5E, 0x04, 0x18, 0xD1, 0x61, 0x46, 0x37, 0x87, 0xE2, 0x97, 0xDF, 0x10, 0xB4, 0x9A, 0x39,
0xB1, 0xD0, 0xCA, 0x91, 0x48, 0x1E, 0x5D, 0xA1, 0x38, 0x89, 0x02, 0xC1, 0x49, 0x86, 0xB7, 0xAE,
0x69, 0x20, 0xFA, 0x0E, 0x39, 0xDA, 0xA5, 0xEF, 0x7F, 0xB2, 0x81, 0xB8, 0xC0, 0x3A, 0xF8, 0xDB,
0xBC, 0x45, 0xF6, 0xDA, 0xCD, 0xBE, 0x27, 0xBE, 0xF6, 0x20, 0x79, 0xF3, 0xC3, 0xC8, 0xFF, 0x85,
0x43, 0x9F, 0xB1, 0x9B, 0x72, 0x88, 0xDD, 0xA4, 0x0D, 0xFC, 0xC6, 0xB5, 0x74, 0x67, 0x29, 0xF5
};
*/
void test_square_simple(void){
bigint_t a, c;
uint8_t a_b[12] = {0xe6, 0x70, 0x7d, 0x43, 0x74, 0x07, 0x20, 0x22, 0x6a, 0xb8, 0xf4, 0x00};
uint8_t c_b[24];
a.wordv=(bigint_word_t*)a_b;
c.wordv=(bigint_word_t*)c_b;
a.length_B = 12/sizeof(bigint_word_t);
a.info=0x00;
bigint_adjust(&a);
bigint_square(&c, &a);
cli_putstr("\r\n test: ");
bigint_print_hex(&a);
cli_putstr("**2 = ");
bigint_print_hex(&c);
}
// [fail (c)]: A862 % 2752 = 0D1A ; should a862 % 2752 = b1a
void test_reduce_simple(void){
bigint_t a, b, c;
uint8_t a_b[4] = {0x62, 0xA8, 0x00, 0x00};
uint8_t b_b[4] = {0x52, 0x27, 0x00, 0x00};
uint8_t c_b[4];
a.wordv=(bigint_word_t*)a_b;
a.length_B = 1;
a.info=0x00;
bigint_adjust(&a);
b.wordv=(bigint_word_t*)b_b;
b.length_B = 1;
b.info=0x00;
bigint_adjust(&b);
c.wordv = (bigint_word_t*)c_b;
bigint_copy(&c, &a);
bigint_reduce(&c, &b);
cli_putstr("\r\n test: ");
bigint_print_hex(&a);
cli_putstr(" % ");
bigint_print_hex(&b);
cli_putstr(" = ");
bigint_print_hex(&c);
}
/* gcdext( B5DDAD, 6CBBC2) */
/* gcdext( CD319349, 9EFD76CC) */
/* gcdext( 1609000771, 6FAC577D72) */
/* */
void test_gcdext_simple(void){
bigint_t a, b, c, d, e;
uint8_t a_b[8] = {0x71, 0x07, 0x00, 0x09, 0x16, 0x00, 0x00, 0x00};
uint8_t b_b[8] = {0x72, 0x7D, 0x57, 0xAC, 0X6F, 0x00, 0x00, 0x00};
uint8_t c_b[16], d_b[16], e_b[16];
a.wordv=(bigint_word_t*)a_b;
a.length_B = 2;
a.info=0x00;
bigint_adjust(&a);
b.wordv=(bigint_word_t*)b_b;
b.length_B = 2;
b.info=0x00;
bigint_adjust(&b);
c.wordv = (bigint_word_t*)c_b;
d.wordv = (bigint_word_t*)d_b;
e.wordv = (bigint_word_t*)e_b;
bigint_gcdext(&c, &d, &e, &a, &b);
cli_putstr("\r\n test: gcd( ");
bigint_print_hex(&a);
cli_putstr(", ");
bigint_print_hex(&b);
cli_putstr(") => a = ");
bigint_print_hex(&d);
cli_putstr("; b = ");
bigint_print_hex(&e);
cli_putstr("; gcd = ");
bigint_print_hex(&c);
}
void testrun_performance_bigint(void){
}
/*****************************************************************************
* main *
*****************************************************************************/
const char echo_test_str[] = "echo-test";
const char add_test_str[] = "add-test";
const char add_scale_test_str[] = "add-scale-test";
const char mul_test_str[] = "mul-test";
const char square_test_str[] = "square-test";
const char reduce_test_str[] = "reduce-test";
const char expmod_test_str[] = "expmod-test";
const char gcdext_test_str[] = "gcdext-test";
const char quick_test_str[] = "quick-test";
const char performance_str[] = "performance";
const char echo_str[] = "echo";
const cmdlist_entry_t cmdlist[] = {
{ add_test_str, NULL, test_add_bigint },
{ add_scale_test_str, NULL, test_add_scale_bigint },
{ mul_test_str, NULL, test_mul_bigint },
{ square_test_str, NULL, test_square_bigint },
{ reduce_test_str, NULL, test_reduce_bigint },
{ expmod_test_str, NULL, test_expmod_bigint },
{ gcdext_test_str, NULL, test_gcdext_bigint },
{ quick_test_str, NULL, test_gcdext_simple },
{ echo_test_str, NULL, test_echo_bigint },
{ performance_str, NULL, testrun_performance_bigint },
{ echo_str, (void*)1, (void_fpt)echo_ctrl },
{ NULL, NULL, NULL }
};
int main (void){
sysclk_set_freq(SYS_FREQ);
sysclk_mosc_verify_enable();
uart_init(UART_0, 115200, 8, UART_PARATY_NONE, UART_STOPBITS_ONE);
gptm_set_timer_32periodic(TIMER0);
cli_rx = uart0_getc;
cli_tx = uart0_putc;
for(;;){
cli_putstr("\r\n\r\nARM-Crypto-Lib VS (");
cli_putstr(algo_name);
cli_putstr("; ");
cli_putstr(__DATE__);
cli_putc(' ');
cli_putstr(__TIME__);
cli_putstr(")\r\nloaded and running\r\n");
cmd_interface(cmdlist);
}
}

View File

@ -106,7 +106,6 @@ void testrun_self_present(void){
memset(buffer, 0xFF, 8);
memset(key, 0xFF, 10);
testrun_selfenc(key, buffer);
}
void testrun_performance_present(void){

View File

@ -82,6 +82,7 @@ isr_fpt isr_vector[] __attribute__ ((section(".isr_vectors"))) = {
default_isr, /* GPIO Port D */
default_isr, /* GPIO Port E */
uart0_isr, /* UART0 */
// default_isr, /* UART0 */
default_isr, /* UART1 */
default_isr, /* SSI0 */
default_isr, /* I2C0 */

View File

@ -42,7 +42,7 @@ uint32_t stridentcnt(const char* a, const char* b){
uint16_t firstword_length(const char* s){
uint16_t ret=0;
while(isgraph(*s++))
while(isgraph((uint8_t)(*s++)))
ret++;
return ret;
}

View File

@ -27,13 +27,15 @@
#define PIOSC_FREQ 16000000UL
void sysclk_set_rawclock(void){
uint32_t tmp_rcc;
volatile uint32_t tmp_rcc;
tmp_rcc = 0; //HW_REG(SYSCTL_BASE+RCC_OFFSET);
tmp_rcc &= ~(_BV(RCC_IOSCDIS) | _BV(RCC_MOSCDIS) | _BV(RCC_USESYSDIV));
tmp_rcc |= _BV(RCC_BYPASS) | _BV(RCC_PWRDN);
tmp_rcc &= ~(3<<RCC_OSCSRC);
tmp_rcc |= (0<<RCC_OSCSRC);
HW_REG(SYSCTL_BASE+RCC_OFFSET) = tmp_rcc;
// tmp_rcc |= _BV(RCC_PWRDN);
HW_REG(SYSCTL_BASE+RCC_OFFSET) = tmp_rcc;
HW_REG(SYSCTL_BASE+RCC2_OFFSET) &= ~(_BV(31));
}
@ -58,10 +60,11 @@ void sysclk_set_freq(uint8_t freq_id){
HW_REG(SYSCTL_BASE+RCC2_OFFSET) = rcc2;
rcc2 &= ~_BV(RCC2_PWRDN2);
HW_REG(SYSCTL_BASE+RCC2_OFFSET) = rcc2;
rcc2 |= _BV(RCC2_DIV400) | freq_id<<RCC2_SYSDIV2LSB;
rcc2 |= _BV(RCC2_DIV400) | (freq_id<<RCC2_SYSDIV2LSB);
HW_REG(SYSCTL_BASE+RCC2_OFFSET) = rcc2;
while(!(HW_REG(SYSCTL_BASE+RIS_OFFSET)&_BV(RIS_PLLLRIS))){
}
// return;
rcc2 &= ~_BV(RCC2_BYPASS2);
HW_REG(SYSCTL_BASE+RCC2_OFFSET) = rcc2;
}

View File

@ -1,6 +1,6 @@
/* sysclock.h */
/*
This file is part of the ARM-Crypto-Lib.
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
@ -22,130 +22,130 @@
#include <stdint.h>
#define SYS_FREQ_80MHZ000 0x4
#define SYS_FREQ_66MHZ667 0x5
#define SYS_FREQ_57MHZ143 0x6
#define SYS_FREQ_50MHZ000 0x7
#define SYS_FREQ_44MHZ444 0x8
#define SYS_FREQ_40MHZ000 0x9
#define SYS_FREQ_36MHZ364 0xA
#define SYS_FREQ_33MHZ333 0xB
#define SYS_FREQ_30MHZ769 0xC
#define SYS_FREQ_28MHZ571 0xD
#define SYS_FREQ_26MHZ667 0xE
#define SYS_FREQ_25MHZ000 0xF
#define SYS_FREQ_23MHZ529 0x10
#define SYS_FREQ_22MHZ222 0x11
#define SYS_FREQ_21MHZ053 0x12
#define SYS_FREQ_20MHZ000 0x13
#define SYS_FREQ_19MHZ048 0x14
#define SYS_FREQ_18MHZ182 0x15
#define SYS_FREQ_17MHZ391 0x16
#define SYS_FREQ_16MHZ667 0x17
#define SYS_FREQ_16MHZ000 0x18
#define SYS_FREQ_15MHZ385 0x19
#define SYS_FREQ_14MHZ815 0x1A
#define SYS_FREQ_14MHZ286 0x1B
#define SYS_FREQ_13MHZ793 0x1C
#define SYS_FREQ_13MHZ333 0x1D
#define SYS_FREQ_12MHZ903 0x1E
#define SYS_FREQ_12MHZ500 0x1F
#define SYS_FREQ_12MHZ121 0x20
#define SYS_FREQ_11MHZ765 0x21
#define SYS_FREQ_11MHZ429 0x22
#define SYS_FREQ_11MHZ111 0x23
#define SYS_FREQ_10MHZ811 0x24
#define SYS_FREQ_10MHZ526 0x25
#define SYS_FREQ_10MHZ256 0x26
#define SYS_FREQ_10MHZ000 0x27
#define SYS_FREQ_9MHZ756 0x28
#define SYS_FREQ_9MHZ524 0x29
#define SYS_FREQ_9MHZ302 0x2A
#define SYS_FREQ_9MHZ091 0x2B
#define SYS_FREQ_8MHZ889 0x2C
#define SYS_FREQ_8MHZ696 0x2D
#define SYS_FREQ_8MHZ511 0x2E
#define SYS_FREQ_8MHZ333 0x2F
#define SYS_FREQ_8MHZ163 0x30
#define SYS_FREQ_8MHZ000 0x31
#define SYS_FREQ_7MHZ843 0x32
#define SYS_FREQ_7MHZ692 0x33
#define SYS_FREQ_7MHZ547 0x34
#define SYS_FREQ_7MHZ407 0x35
#define SYS_FREQ_7MHZ273 0x36
#define SYS_FREQ_7MHZ143 0x37
#define SYS_FREQ_7MHZ018 0x38
#define SYS_FREQ_6MHZ897 0x39
#define SYS_FREQ_6MHZ780 0x3A
#define SYS_FREQ_6MHZ667 0x3B
#define SYS_FREQ_6MHZ557 0x3C
#define SYS_FREQ_6MHZ452 0x3D
#define SYS_FREQ_6MHZ349 0x3E
#define SYS_FREQ_6MHZ250 0x3F
#define SYS_FREQ_6MHZ154 0x40
#define SYS_FREQ_6MHZ061 0x41
#define SYS_FREQ_5MHZ970 0x42
#define SYS_FREQ_5MHZ882 0x43
#define SYS_FREQ_5MHZ797 0x44
#define SYS_FREQ_5MHZ714 0x45
#define SYS_FREQ_5MHZ634 0x46
#define SYS_FREQ_5MHZ556 0x47
#define SYS_FREQ_5MHZ479 0x48
#define SYS_FREQ_5MHZ405 0x49
#define SYS_FREQ_5MHZ333 0x4A
#define SYS_FREQ_5MHZ263 0x4B
#define SYS_FREQ_5MHZ195 0x4C
#define SYS_FREQ_5MHZ128 0x4D
#define SYS_FREQ_5MHZ063 0x4E
#define SYS_FREQ_5MHZ000 0x4F
#define SYS_FREQ_4MHZ938 0x50
#define SYS_FREQ_4MHZ878 0x51
#define SYS_FREQ_4MHZ819 0x52
#define SYS_FREQ_4MHZ762 0x53
#define SYS_FREQ_4MHZ706 0x54
#define SYS_FREQ_4MHZ651 0x55
#define SYS_FREQ_4MHZ598 0x56
#define SYS_FREQ_4MHZ545 0x57
#define SYS_FREQ_4MHZ494 0x58
#define SYS_FREQ_4MHZ444 0x59
#define SYS_FREQ_4MHZ396 0x5A
#define SYS_FREQ_4MHZ348 0x5B
#define SYS_FREQ_4MHZ301 0x5C
#define SYS_FREQ_4MHZ255 0x5D
#define SYS_FREQ_4MHZ211 0x5E
#define SYS_FREQ_4MHZ167 0x5F
#define SYS_FREQ_4MHZ124 0x60
#define SYS_FREQ_4MHZ082 0x61
#define SYS_FREQ_4MHZ040 0x62
#define SYS_FREQ_4MHZ000 0x63
#define SYS_FREQ_3MHZ960 0x64
#define SYS_FREQ_3MHZ922 0x65
#define SYS_FREQ_3MHZ883 0x66
#define SYS_FREQ_3MHZ846 0x67
#define SYS_FREQ_3MHZ810 0x68
#define SYS_FREQ_3MHZ774 0x69
#define SYS_FREQ_3MHZ738 0x6A
#define SYS_FREQ_3MHZ704 0x6B
#define SYS_FREQ_3MHZ670 0x6C
#define SYS_FREQ_3MHZ636 0x6D
#define SYS_FREQ_3MHZ604 0x6E
#define SYS_FREQ_3MHZ571 0x6F
#define SYS_FREQ_3MHZ540 0x70
#define SYS_FREQ_3MHZ509 0x71
#define SYS_FREQ_3MHZ478 0x72
#define SYS_FREQ_3MHZ448 0x73
#define SYS_FREQ_3MHZ419 0x74
#define SYS_FREQ_3MHZ390 0x75
#define SYS_FREQ_3MHZ361 0x76
#define SYS_FREQ_3MHZ333 0x77
#define SYS_FREQ_3MHZ306 0x78
#define SYS_FREQ_3MHZ279 0x79
#define SYS_FREQ_3MHZ252 0x7A
#define SYS_FREQ_3MHZ226 0x7B
#define SYS_FREQ_3MHZ200 0x7C
#define SYS_FREQ_3MHZ175 0x7D
#define SYS_FREQ_3MHZ150 0x7E
#define SYS_FREQ_3MHZ125 0x7F
#define SYS_FREQ_80MHZ000 0x04UL
#define SYS_FREQ_66MHZ667 0x05UL
#define SYS_FREQ_57MHZ143 0x06UL
#define SYS_FREQ_50MHZ000 0x07UL
#define SYS_FREQ_44MHZ444 0x08UL
#define SYS_FREQ_40MHZ000 0x09UL
#define SYS_FREQ_36MHZ364 0x0AUL
#define SYS_FREQ_33MHZ333 0x0BUL
#define SYS_FREQ_30MHZ769 0x0CUL
#define SYS_FREQ_28MHZ571 0x0DUL
#define SYS_FREQ_26MHZ667 0x0EUL
#define SYS_FREQ_25MHZ000 0x0FUL
#define SYS_FREQ_23MHZ529 0x10UL
#define SYS_FREQ_22MHZ222 0x11UL
#define SYS_FREQ_21MHZ053 0x12UL
#define SYS_FREQ_20MHZ000 0x13UL
#define SYS_FREQ_19MHZ048 0x14UL
#define SYS_FREQ_18MHZ182 0x15UL
#define SYS_FREQ_17MHZ391 0x16UL
#define SYS_FREQ_16MHZ667 0x17UL
#define SYS_FREQ_16MHZ000 0x18UL
#define SYS_FREQ_15MHZ385 0x19UL
#define SYS_FREQ_14MHZ815 0x1AUL
#define SYS_FREQ_14MHZ286 0x1BUL
#define SYS_FREQ_13MHZ793 0x1CUL
#define SYS_FREQ_13MHZ333 0x1DUL
#define SYS_FREQ_12MHZ903 0x1EUL
#define SYS_FREQ_12MHZ500 0x1FUL
#define SYS_FREQ_12MHZ121 0x20UL
#define SYS_FREQ_11MHZ765 0x21UL
#define SYS_FREQ_11MHZ429 0x22UL
#define SYS_FREQ_11MHZ111 0x23UL
#define SYS_FREQ_10MHZ811 0x24UL
#define SYS_FREQ_10MHZ526 0x25UL
#define SYS_FREQ_10MHZ256 0x26UL
#define SYS_FREQ_10MHZ000 0x27UL
#define SYS_FREQ_9MHZ756 0x28UL
#define SYS_FREQ_9MHZ524 0x29UL
#define SYS_FREQ_9MHZ302 0x2AUL
#define SYS_FREQ_9MHZ091 0x2BUL
#define SYS_FREQ_8MHZ889 0x2CUL
#define SYS_FREQ_8MHZ696 0x2DUL
#define SYS_FREQ_8MHZ511 0x2EUL
#define SYS_FREQ_8MHZ333 0x2FUL
#define SYS_FREQ_8MHZ163 0x30UL
#define SYS_FREQ_8MHZ000 0x31UL
#define SYS_FREQ_7MHZ843 0x32UL
#define SYS_FREQ_7MHZ692 0x33UL
#define SYS_FREQ_7MHZ547 0x34UL
#define SYS_FREQ_7MHZ407 0x35UL
#define SYS_FREQ_7MHZ273 0x36UL
#define SYS_FREQ_7MHZ143 0x37UL
#define SYS_FREQ_7MHZ018 0x38UL
#define SYS_FREQ_6MHZ897 0x39UL
#define SYS_FREQ_6MHZ780 0x3AUL
#define SYS_FREQ_6MHZ667 0x3BUL
#define SYS_FREQ_6MHZ557 0x3CUL
#define SYS_FREQ_6MHZ452 0x3DUL
#define SYS_FREQ_6MHZ349 0x3EUL
#define SYS_FREQ_6MHZ250 0x3FUL
#define SYS_FREQ_6MHZ154 0x40UL
#define SYS_FREQ_6MHZ061 0x41UL
#define SYS_FREQ_5MHZ970 0x42UL
#define SYS_FREQ_5MHZ882 0x43UL
#define SYS_FREQ_5MHZ797 0x44UL
#define SYS_FREQ_5MHZ714 0x45UL
#define SYS_FREQ_5MHZ634 0x46UL
#define SYS_FREQ_5MHZ556 0x47UL
#define SYS_FREQ_5MHZ479 0x48UL
#define SYS_FREQ_5MHZ405 0x49UL
#define SYS_FREQ_5MHZ333 0x4AUL
#define SYS_FREQ_5MHZ263 0x4BUL
#define SYS_FREQ_5MHZ195 0x4CUL
#define SYS_FREQ_5MHZ128 0x4DUL
#define SYS_FREQ_5MHZ063 0x4EUL
#define SYS_FREQ_5MHZ000 0x4FUL
#define SYS_FREQ_4MHZ938 0x50UL
#define SYS_FREQ_4MHZ878 0x51UL
#define SYS_FREQ_4MHZ819 0x52UL
#define SYS_FREQ_4MHZ762 0x53UL
#define SYS_FREQ_4MHZ706 0x54UL
#define SYS_FREQ_4MHZ651 0x55UL
#define SYS_FREQ_4MHZ598 0x56UL
#define SYS_FREQ_4MHZ545 0x57UL
#define SYS_FREQ_4MHZ494 0x58UL
#define SYS_FREQ_4MHZ444 0x59UL
#define SYS_FREQ_4MHZ396 0x5AUL
#define SYS_FREQ_4MHZ348 0x5BUL
#define SYS_FREQ_4MHZ301 0x5CUL
#define SYS_FREQ_4MHZ255 0x5DUL
#define SYS_FREQ_4MHZ211 0x5EUL
#define SYS_FREQ_4MHZ167 0x5FUL
#define SYS_FREQ_4MHZ124 0x60UL
#define SYS_FREQ_4MHZ082 0x61UL
#define SYS_FREQ_4MHZ040 0x62UL
#define SYS_FREQ_4MHZ000 0x63UL
#define SYS_FREQ_3MHZ960 0x64UL
#define SYS_FREQ_3MHZ922 0x65UL
#define SYS_FREQ_3MHZ883 0x66UL
#define SYS_FREQ_3MHZ846 0x67UL
#define SYS_FREQ_3MHZ810 0x68UL
#define SYS_FREQ_3MHZ774 0x69UL
#define SYS_FREQ_3MHZ738 0x6AUL
#define SYS_FREQ_3MHZ704 0x6BUL
#define SYS_FREQ_3MHZ670 0x6CUL
#define SYS_FREQ_3MHZ636 0x6DUL
#define SYS_FREQ_3MHZ604 0x6EUL
#define SYS_FREQ_3MHZ571 0x6FUL
#define SYS_FREQ_3MHZ540 0x70UL
#define SYS_FREQ_3MHZ509 0x71UL
#define SYS_FREQ_3MHZ478 0x72UL
#define SYS_FREQ_3MHZ448 0x73UL
#define SYS_FREQ_3MHZ419 0x74UL
#define SYS_FREQ_3MHZ390 0x75UL
#define SYS_FREQ_3MHZ361 0x76UL
#define SYS_FREQ_3MHZ333 0x77UL
#define SYS_FREQ_3MHZ306 0x78UL
#define SYS_FREQ_3MHZ279 0x79UL
#define SYS_FREQ_3MHZ252 0x7AUL
#define SYS_FREQ_3MHZ226 0x7BUL
#define SYS_FREQ_3MHZ200 0x7CUL
#define SYS_FREQ_3MHZ175 0x7DUL
#define SYS_FREQ_3MHZ150 0x7EUL
#define SYS_FREQ_3MHZ125 0x7FUL
void sysclk_set_rawclock(void);

View File

@ -1,6 +1,6 @@
/* uart_defines.h */
/*
This file is part of the ARM-Crypto-Lib.
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
@ -47,10 +47,4 @@
#define UART_ERROR_RX_BUFFER_INIT 5
#define UART_ERROR_TX_BUFFER_INIT 6
#define UART_FLOWCTRL_NONE 0
#define UART_FLOWCTRL_SOFT 1
#define UART_XON_CHAR 0x11
#define UART_XOFF_CHAR 0x13
#endif /* UART_DEFINES_H_ */

View File

@ -23,7 +23,7 @@
#include "hw_uart_regs.h"
#include "uart_defines.h"
#include "circularbytebuffer.h"
#include "uart_lowlevel.h"
static const
uint32_t uart_base[] = { UART0_BASE, UART1_BASE, UART2_BASE };
@ -54,10 +54,6 @@ static const
uint32_t uart_rx_buffersize[] = {128, 128, 128};
static const
uint32_t uart_tx_buffersize[] = {256, 256, 256};
static
uint8_t uart_swflowctrl_en[] = {0, 0, 0};
static
uint8_t uart_swflowctrl_halt[] = {0, 0, 0};
static
circularbytebuffer_t uart_rx_buffer[3];
@ -71,6 +67,7 @@ static
void uart_rx_isr(uint8_t uartno);
void uart0_isr(void){
if(HW_REG(UART0_BASE+UARTMIS_OFFSET)&_BV(UART_TXMIS)){
// HW_REG(uart_base[0]+UARTDR_OFFSET) = 'X';
uart_tx_isr(UART_0);
@ -84,8 +81,7 @@ static
void uart_tx_isr(uint8_t uartno){
uint32_t tmp;
tmp = circularbytebuffer_cnt(&(uart_tx_buffer[uartno]));
while(tmp-- && (!(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_TXFF)))
&& !(uart_swflowctrl_en[uartno] && uart_swflowctrl_halt[uartno])){
while(tmp-- && (!(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_TXFF)))){
HW_REG(uart_base[uartno]+UARTDR_OFFSET)
= (uint32_t)circularbytebuffer_get_fifo(&(uart_tx_buffer[uartno]));
}
@ -95,21 +91,9 @@ void uart_tx_isr(uint8_t uartno){
static
void uart_rx_isr(uint8_t uartno){
uint8_t c;
while(!HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE)){
while(!(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))){
c = HW_REG(uart_base[uartno]+UARTDR_OFFSET);
if(uart_swflowctrl_en[uartno]){
circularbytebuffer_append(c, &(uart_rx_buffer[uartno]));
}else{
if(c==UART_XON_CHAR){
uart_swflowctrl_halt[uartno] = 0;
}else{
if(c==UART_XOFF_CHAR){
uart_swflowctrl_halt[uartno] = 1;
}else{
circularbytebuffer_append(c, &(uart_rx_buffer[uartno]));
}
}
}
circularbytebuffer_append(c, &(uart_rx_buffer[uartno]));
}
HW_REG(uart_base[uartno]+UARTICR_OFFSET) |= _BV(UART_RXIC);
}
@ -117,20 +101,21 @@ void uart_rx_isr(uint8_t uartno){
void calc_baud_values(uint32_t baudrate, uint16_t* intdivider, uint8_t* fracdivider, uint8_t* highspeed){
uint32_t tmp;
uint32_t uart_freq;
if(baudrate==0){
return;
}
uart_freq = sysclk_get_freq();
*highspeed = (baudrate*16>uart_freq)?1:0;
tmp = (uint64_t)uart_freq*128/((*highspeed?8:16)*baudrate);
*highspeed = ((baudrate*16L)>uart_freq)?1:0;
// tmp = (((uint64_t)UART_FREQ)*128LL)/(((*highspeed)?8L:16L)*baudrate);
tmp = uart_freq<<((*highspeed)?(7-3):(7-4));
tmp /= baudrate;
tmp++;
tmp>>=1;
*fracdivider = (uint8_t)(tmp&0x3f);
*intdivider = tmp>>6;
*intdivider = (uint16_t)(tmp>>6);
}
uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits){
return uart_init_flow(uartno, baudrate, databits, paraty, stopbits, 0);
}
uint8_t uart_init_flow(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits, uint8_t flowctrl){
uint32_t tmp;
if(databits>=5){
databits-=5;
@ -153,12 +138,17 @@ uint8_t uart_init_flow(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint
if(0==circularbytebuffer_init(uart_tx_buffersize[uartno], &(uart_tx_buffer[uartno]))){
return UART_ERROR_TX_BUFFER_INIT;
}
/* enable clock for uart */
HW_REG(SYSCTL_BASE+RCGC1_OFFSET) |= _BV(uartno);
/* enable clock for gpio*/
HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= _BV(uart_rx_gpio[uartno]) | _BV(uart_tx_gpio[uartno]);
for(tmp=0; tmp<100; ++tmp)
;
HW_REG(SYSCTL_BASE+RCGC2_OFFSET) |= 1;
for(tmp=0; tmp<100; ++tmp)
;
/* enable clock for uart */
HW_REG(SYSCTL_BASE+RCGC1_OFFSET) |= _BV(uartno);
for(tmp=0; tmp<100; ++tmp)
;
HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_ODR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* open drain */
HW_REG(gpio_base[uart_tx_gpio[uartno]] + GPIO_ODR_OFFSET) &= ~_BV(uart_tx_pin[uartno]); /* open drain */
HW_REG(gpio_base[uart_rx_gpio[uartno]] + GPIO_PUR_OFFSET) &= ~_BV(uart_rx_pin[uartno]); /* pull-up */
@ -185,20 +175,25 @@ uint8_t uart_init_flow(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint
HW_REG(gpio_base[uart_rx_gpio[uartno]]+GPIO_DIR_OFFSET) &= ~_BV(uart_rx_pin[uartno]);
/* configure tx pin as output */
HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_DIR_OFFSET) |= _BV(uart_tx_pin[uartno]);
for(tmp=0; tmp<100; ++tmp)
;
/* disable uart */
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_UARTEN);
/* set baudrate parameters */
uint8_t highspeed;
calc_baud_values(baudrate,
(uint16_t*)&HW_REG(uart_base[uartno]+UARTIBRD_OFFSET),
(uint8_t*)&HW_REG(uart_base[uartno]+UARTFBRD_OFFSET),
&highspeed);
uint8_t highspeed, fbrd;
uint16_t ibrd;
calc_baud_values(baudrate, &ibrd, &fbrd, &highspeed);
tmp=HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
HW16_REG(uart_base[uartno]+UARTIBRD_OFFSET) = ibrd;
HW8_REG(uart_base[uartno]+UARTFBRD_OFFSET) = fbrd;
HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) = tmp;
/* wait until uart is no longer busy */
while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_BUSY))
;
/* flush FIFOs */
HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) &= ~_BV(UART_FEN);
/* set line parameters (bits, paraty, stopbits*/
tmp = HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
tmp &= ~0xff;
@ -215,13 +210,6 @@ uint8_t uart_init_flow(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint
} else {
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_HSE);
}
/* set flow control */
if(flowctrl==UART_FLOWCTRL_SOFT){
uart_swflowctrl_en[uartno] = 1;
uart_swflowctrl_halt[uartno] = 0;
}else{
uart_swflowctrl_en[uartno] = 0;
}
/* uart interrupt enable */
HW_REG(uart_base[uartno]+UARTIM_OFFSET) |= _BV(UART_TXIM) | _BV(UART_RXIM);
HW_REG(ISR_ENABLE_VECTOR+uart_isr_vector[uartno]/32) |=
@ -278,3 +266,12 @@ uint32_t uart_dataavail(uint8_t uartno){
}
return(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_RXFE))?0:1;
}
void uart_flush(uint8_t uartno){
if(uartno>UART_MAX){
return;
}
while(uart_tx_buffer[uartno].fillcount>0){
;
}
}

View File

@ -1,6 +1,6 @@
/* uart_lowlevel.c */
/*
This file is part of the ARM-Crypto-Lib.
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
@ -18,23 +18,28 @@
*/
#include <stdint.h>
#include "sysclock.h"
#include "hw_regs.h"
#include "hw_uart_regs.h"
#include "uart_defines.h"
#include "sysclock.h"
void calc_baud_values(uint32_t baudrate, uint16_t* intdivider, uint8_t* fracdivider, uint8_t* highspeed){
uint32_t tmp;
uint32_t uart_freq;
if(baudrate==0){
return;
}
uart_freq = sysclk_get_freq();
*highspeed = (baudrate*16>uart_freq)?1:0;
tmp = (uint64_t)uart_freq*128/((*highspeed?8:16)*baudrate);
*highspeed = ((baudrate*16L)>uart_freq)?1:0;
// tmp = (((uint64_t)UART_FREQ)*128LL)/(((*highspeed)?8L:16L)*baudrate);
tmp = uart_freq<<((*highspeed)?(7-3):(7-4));
tmp /= baudrate;
tmp++;
tmp>>=1;
*fracdivider = (uint8_t)(tmp&0x3f);
*intdivider = tmp>>6;
*intdivider = (uint16_t)(tmp>>6);
}
//*/
static const
uint32_t uart_base[] = { UART0_BASE, UART1_BASE, UART2_BASE };
@ -109,13 +114,16 @@ uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t p
HW_REG(gpio_base[uart_tx_gpio[uartno]]+GPIO_DIR_OFFSET) |= _BV(uart_tx_pin[uartno]);
/* disable uart */
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UARTEN);
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) &= ~_BV(UART_UARTEN);
/* set baudrate parameters */
uint8_t highspeed;
calc_baud_values(baudrate,
(uint16_t*)&HW_REG(uart_base[uartno]+UARTIBRD_OFFSET),
(uint8_t*)&HW_REG(uart_base[uartno]+UARTFBRD_OFFSET),
&highspeed);
uint16_t ibrd;
uint8_t fbrd;
calc_baud_values(baudrate, &ibrd, &fbrd, &highspeed);
tmp=HW_REG(uart_base[uartno]+UARTLCRH_OFFSET);
HW16_REG(uart_base[uartno]+UARTIBRD_OFFSET) = ibrd;
HW8_REG(uart_base[uartno]+UARTFBRD_OFFSET) = fbrd;
HW_REG(uart_base[uartno]+UARTLCRH_OFFSET) = tmp;
/* wait until uart is no longer busy */
while(HW_REG(uart_base[uartno]+UARTFR_OFFSET)&_BV(UART_BUSY))
;
@ -139,7 +147,7 @@ uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t p
}
HW_REG(uart_base[uartno]+UARTFR_OFFSET) = 0;
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_RXE) | _BV(UART_TXE);
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UARTEN);
HW_REG(uart_base[uartno]+UARTCTL_OFFSET) |= _BV(UART_UARTEN);
return UART_ERROR_OK;
}

View File

@ -1,6 +1,6 @@
/* uart_lowlevel.h */
/*
This file is part of the ARM-Crypto-Lib.
This file is part of the AVR-Crypto-Lib.
Copyright (C) 2010 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
@ -27,10 +27,10 @@
#include "uart_defines.h"
uint8_t uart_init(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits);
uint8_t uart_init_flow(uint8_t uartno, uint32_t baudrate, uint8_t databits, uint8_t paraty, uint8_t stopbits, uint8_t flowctrl);
void uart_putc(uint8_t uartno, uint8_t byte);
uint16_t uart_getc(uint8_t uartno);
uint32_t uart_dataavail(uint8_t uartno);
void uart_flush(uint8_t uartno);
#endif /* UART_LOWLEVEL_H_ */