You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
2.8 KiB
134 lines
2.8 KiB
/**
|
|
* SHA1 - Secure Hash Algorithm
|
|
* This code is a direct implementation of the algorithm presented in rfc3174.
|
|
* No optimizations has been used, although I tried to keep it small in order
|
|
* to fit on an ATTiny45 (together with VUSB).
|
|
* It is written in assumption that the target architecture is little endian.
|
|
*/
|
|
#include "sha1.h"
|
|
|
|
#define H1 0x67452301
|
|
#define H2 0xEFCDAB89
|
|
#define H3 0x98BADCFE
|
|
#define H4 0x10325476
|
|
#define H5 0xC3D2E1F0
|
|
|
|
#define K1 0x5A827999
|
|
#define K2 0x6ED9EBA1
|
|
#define K3 0x8F1BBCDC
|
|
#define K4 0xCA62C1D6
|
|
|
|
#define _LROT32(x,n) (( (uint32_t)(x) << n ) | ( (uint32_t)(x) >>(32-n) ))
|
|
#define _W(n) (n>=16 ? _sha1_chunk_e[n-16] : _sha1_chunk[n])
|
|
|
|
|
|
uint32_t _sha1_chunk[16];
|
|
static uint8_t chunk_cnt;
|
|
uint32_t _sha1_chunk_e[64]; /*putting this here saves a lot of code space*/
|
|
|
|
void sha1_addbyte(uint8_t c){
|
|
uint8_t* p=(uint8_t*)_sha1_chunk;
|
|
uint8_t i=(chunk_cnt & 0x03);
|
|
|
|
/* chunk_cnt-i)+3-i deals with the endianess */
|
|
p[(chunk_cnt-i)+3-i]=c;
|
|
chunk_cnt++;
|
|
if(chunk_cnt==64){
|
|
/*chunk extension*/
|
|
uint32_t a,b,c,d,e;
|
|
for(i=0; i<64; ++i){
|
|
_sha1_chunk_e[i]= _LROT32( _W(i+16-3) ^ _W(i+16-8) ^ _W(i+16-14) ^ _W(i+16-16), 1 );
|
|
}
|
|
a=sha1_digest[4];
|
|
b=sha1_digest[3];
|
|
c=sha1_digest[2];
|
|
d=sha1_digest[1];
|
|
e=sha1_digest[0];
|
|
|
|
/*main loop*/
|
|
for(i=0;i<80;i++){
|
|
uint32_t f,k,temp;
|
|
|
|
if(i<20){
|
|
k=K1;
|
|
f=(b & c) | ((~b) & d);
|
|
}else if(i<40){
|
|
k=K2;
|
|
f=b ^ c ^ d;
|
|
}else if(i<60){
|
|
k=K3;
|
|
f=(b & c) | (b & d) | (c & d);
|
|
}else{
|
|
k=K4;
|
|
f=b ^ c ^ d;
|
|
}
|
|
temp = e + k + f+_LROT32(a,5)+_W(i);
|
|
e = d;
|
|
d = c;
|
|
c = _LROT32(b,30);
|
|
b = a;
|
|
a = temp;
|
|
}
|
|
|
|
sha1_digest[4]+=a;
|
|
sha1_digest[3]+=b;
|
|
sha1_digest[2]+=c;
|
|
sha1_digest[1]+=d;
|
|
sha1_digest[0]+=e;
|
|
|
|
chunk_cnt=0;
|
|
}
|
|
}
|
|
|
|
void sha1_fill(int32_t len){
|
|
/*"append a 1-bit to the message"*/
|
|
/*"append 0-bits to the message to obtain a length of len%512=448"*/
|
|
/*"append length of message in bits as 64-bit integer"*/
|
|
uint8_t j;
|
|
uint8_t end=(uint8_t)((120-(len-(len/64)*64+1))%64);
|
|
sha1_addbyte(0x80);
|
|
for(j=0;j<end;j++){
|
|
sha1_addbyte(0x00);
|
|
}
|
|
{
|
|
uint64_t l=len*8;
|
|
//pay attention to the endiness here
|
|
sha1_addbyte( ((char*)(&l))[7]);
|
|
sha1_addbyte( ((char*)(&l))[6]);
|
|
sha1_addbyte( ((char*)(&l))[5]);
|
|
sha1_addbyte( ((char*)(&l))[4]);
|
|
sha1_addbyte( ((char*)(&l))[3]);
|
|
sha1_addbyte( ((char*)(&l))[2]);
|
|
sha1_addbyte( ((char*)(&l))[1]);
|
|
sha1_addbyte( ((char*)(&l))[0]);
|
|
}
|
|
}
|
|
|
|
void sha1(char* msg, int32_t len){
|
|
int32_t i;
|
|
uint8_t j;
|
|
sha1_init();
|
|
|
|
for(i=0; i<=len; i+=64){
|
|
if(i+64>=len){
|
|
for(j=0;j<len-i;j++){
|
|
sha1_addbyte(msg[i+j]);
|
|
}
|
|
sha1_fill(len);
|
|
continue;
|
|
}
|
|
for(j=0;j<64;j++){
|
|
sha1_addbyte(msg[i+j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sha1_init(void){
|
|
chunk_cnt=0;
|
|
sha1_digest[4]=H1;
|
|
sha1_digest[3]=H2;
|
|
sha1_digest[2]=H3;
|
|
sha1_digest[1]=H4;
|
|
sha1_digest[0]=H5;
|
|
}
|
|
|
|
|