//Emil Fihlman #ifndef LIBEF_SHA256_H #define LIBEF_SHA256_H #include "stdtypes.h" #define SHA256_DIGEST_SIZE 32 #define SHA256_BLOCK_SIZE 64 static inline u32 sha256BytesToU32(u8 *buffer) { return((((u32)(buffer[0]))<<24)|(((u32)(buffer[1]))<<16)|(((u32)(buffer[2]))<<8)|(((u32)(buffer[3]))<<0)); } static inline u32 sha256RorCountU32(u32 value, u8 count) { count&=31; return((value<<(32-count))|(value>>count)); } static inline void sha256U64ToArray(u64 input, void *output) { u8 *out=output; out[7]=input; input>>=8; out[6]=input; input>>=8; out[5]=input; input>>=8; out[4]=input; input>>=8; out[3]=input; input>>=8; out[2]=input; input>>=8; out[1]=input; input>>=8; out[0]=input; } struct sha256Context { u64 index; u64 length; u32 h[8]; u8 c[SHA256_BLOCK_SIZE]; }; struct sha256HmacContext { u64 index; u64 length; u32 h[8]; u8 c[SHA256_BLOCK_SIZE+SHA256_DIGEST_SIZE]; u8 key[SHA256_BLOCK_SIZE]; }; struct sha256CryptContext { struct sha256HmacContext maccontext; u8 kv[SHA256_DIGEST_SIZE]; u8 stream[SHA256_DIGEST_SIZE]; u64 length; }; static inline void sha256Init(struct sha256Context *context) { context->index=0; context->length=0; context->h[0]=0x6a09e667; context->h[1]=0xbb67ae85; context->h[2]=0x3c6ef372; context->h[3]=0xa54ff53a; context->h[4]=0x510e527f; context->h[5]=0x9b05688c; context->h[6]=0x1f83d9ab; context->h[7]=0x5be0cd19; } static inline void sha256Chunk(struct sha256Context *context, u8 *buffer) { u32 k[]= { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; u32 i, w[SHA256_BLOCK_SIZE], a[8], t[2], s[2], ch, maj; for(i=0; i<16; ++i) { w[i]=sha256BytesToU32(buffer+4*i); } for(i=16; i>3); s[1]=sha256RorCountU32(w[i-2], 17)^sha256RorCountU32(w[i-2], 19)^(w[i-2]>>10); w[i]=w[i-16]+s[0]+w[i-7]+s[1]; } for(i=0; i<8; ++i) { a[i]=context->h[i]; } for(i=0; ih[i]+=a[i]; } } static inline void sha256Update(struct sha256Context *context, void *data, u64 length) { u8 *d=(u8 *)data; context->length+=length; if(context->index) { while((context->index)0) { --length; context->c[context->index++]=*(d++); } if((context->index)==SHA256_BLOCK_SIZE) { sha256Chunk(context, context->c); context->index=0; } } while(length>=SHA256_BLOCK_SIZE) { sha256Chunk(context, d); length-=SHA256_BLOCK_SIZE; d+=SHA256_BLOCK_SIZE; } while(length>0) { --length; context->c[context->index++]=*(d++); } } static inline void sha256Final(struct sha256Context *context, u8 *digest) { u64 i; context->c[context->index++]=0x80; if(context->index+8>SHA256_BLOCK_SIZE) { while(context->indexc[context->index++]=0; } for(i=context->index; ic[i]=0; } sha256Chunk(context, context->c); context->index=0; } for(i=context->index; i<(SHA256_BLOCK_SIZE-8); ++i) { context->c[i]=0; } context->length*=8; for(i=0; i<8; ++i) { context->c[63-i]=(context->length)>>(8*i); } sha256Chunk(context, context->c); for(i=0; ih[i>>2])>>(8*(3-(i&3))); } } static inline void sha256(void *data, u64 length, u8 *digest) { struct sha256Context context; sha256Init(&context); sha256Update(&context, data, length); sha256Final(&context, digest); } static inline void sha256v(void **datas, u64 *lengths, u64 count, u8 *digest) { struct sha256Context context; sha256Init(&context); while(count) { sha256Update(&context, *datas, *lengths); ++datas; ++lengths; --count; } sha256Final(&context, digest); } static inline void sha256HmacInit(struct sha256HmacContext *context, void *key, u64 length) { u64 i; u8 ipad=0x36; u8 *b=key; sha256Init((struct sha256Context *)context); if(length>SHA256_BLOCK_SIZE) { sha256(key, length, context->key); i=SHA256_DIGEST_SIZE; } else { for(i=0; ikey[i]=b[i]; } i=length; } for(; ikey[i]=0; } for(i=0; ic[i]=context->key[i]^ipad; } sha256Update((struct sha256Context *)context, context->c, SHA256_BLOCK_SIZE); } static inline void sha256HmacUpdate(struct sha256HmacContext *context, void *data, u64 length) { sha256Update((struct sha256Context *)context, data, length); } static inline void sha256HmacFinal(struct sha256HmacContext *context, u8 *digest) { u64 i; u8 opad=0x5c; sha256Final((struct sha256Context *)context, context->c+SHA256_BLOCK_SIZE); for(i=0; ic[i]=context->key[i]^opad; } sha256(context->c, SHA256_BLOCK_SIZE+SHA256_DIGEST_SIZE, digest); } static inline void sha256Hmac(void *data, u64 length, void *key, u64 size, u8 *digest) { struct sha256HmacContext context; sha256HmacInit(&context, key, size); sha256HmacUpdate(&context, data, length); sha256HmacFinal(&context, digest); } static inline void sha256HmacV(void **datas, u64 *lengths, u64 count, void *key, u64 size, u8 *digest) { struct sha256HmacContext context; sha256HmacInit(&context, key, size); while(count) { sha256HmacUpdate(&context, *datas, *lengths); ++datas; ++lengths; --count; } sha256HmacFinal(&context, digest); } static inline void sha256CryptInit(struct sha256CryptContext *context, void *key, u64 keyLength, u8 *vector, u64 vectorLength) { struct sha256Context streamcontext; context->length=0; sha256Init(&streamcontext); sha256Update(&streamcontext, key, keyLength); sha256Update(&streamcontext, vector, vectorLength); sha256Final(&streamcontext, context->kv); sha256HmacInit(&(context->maccontext), context->kv, SHA256_DIGEST_SIZE); sha256HmacUpdate(&(context->maccontext), vector, vectorLength); } static inline void sha256CryptUpdate(struct sha256CryptContext *context, void *data, u64 length, u8 action) { u64 i; u8 *d=data; if(!action) { sha256HmacUpdate(&(context->maccontext), d, length); } for(i=0; ilength)%SHA256_DIGEST_SIZE)) { u8 temp[sizeof(u64)]; struct sha256Context streamcontext; sha256Init(&streamcontext); sha256Update(&streamcontext, context->kv, SHA256_DIGEST_SIZE); sha256U64ToArray(context->length, temp); sha256Update(&streamcontext, temp, sizeof(temp)); sha256Final(&streamcontext, context->stream); } d[i]^=(context->stream)[(context->length)%SHA256_DIGEST_SIZE]; ++(context->length); } if(action) { sha256HmacUpdate(&(context->maccontext), d, length); } } static inline void sha256CryptFinal(struct sha256CryptContext *context, u8 *mac) { sha256HmacFinal(&(context->maccontext), mac); } static inline void sha256Crypt(void *data, u64 dataLength, void *key, u64 keyLength, u8 *vector, u64 vectorLength, u8 *mac, u8 action) { struct sha256CryptContext context; sha256CryptInit(&context, key, keyLength, vector, vectorLength); sha256CryptUpdate(&context, data, dataLength, action); sha256CryptFinal(&context, mac); } static inline u8 sha256Compare(void *mac1, void *mac2) { u8 sum=0, count=SHA256_DIGEST_SIZE; u8 *m1=mac1, *m2=mac2; while(count) { sum|=((*m1)^(*m2)); ++m1; ++m2; --count; } return(sum); } #endif