A super trimmed down TLS stack, GPL licensed
Dependents: MiniTLS-HTTPS-Example
MiniTLS - A super trimmed down TLS/SSL Library for embedded devices Author: Donatien Garnier Copyright (C) 2013-2014 AppNearMe Ltd
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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Diff: crypto/crypto_sha1.c
- Revision:
- 4:cbaf466d717d
- Parent:
- 2:527a66d0a1a9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crypto/crypto_sha1.c Tue Jun 10 14:23:09 2014 +0000 @@ -0,0 +1,231 @@ +/* +MiniTLS - A super trimmed down TLS/SSL Library for embedded devices +Author: Donatien Garnier +Copyright (C) 2013-2014 AppNearMe Ltd + +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 2 +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*//** + * \file crypto_sha1.c + * \copyright Copyright (c) AppNearMe Ltd 2013 + * \author Donatien Garnier + */ + +#define __DEBUG__ 0 +#define __MODULE__ "crypto_sha1.c" + +//This module has been adapted from libtomcrypt (http://libtom.org/) + +#include "core/fwk.h" +#include "crypto_sha1.h" +#include "inc/minitls_errors.h" +#include "crypto_macros.h" + +#define fatal(x) do{ ERR("Fatal error %s - %d", #x, x); while(1); }while(0) + +static void crypto_sha1_compress(crypto_sha1_t* hash, unsigned char *buf); + +void crypto_sha1_init(crypto_sha1_t* hash) +{ + hash->state[0] = 0x67452301UL; + hash->state[1] = 0xefcdab89UL; + hash->state[2] = 0x98badcfeUL; + hash->state[3] = 0x10325476UL; + hash->state[4] = 0xc3d2e1f0UL; + hash->curlen = 0; + hash->length = 0; +} + +void crypto_sha1_update(crypto_sha1_t* hash, const uint8_t* data, size_t size) +{ + unsigned long n; + + if ( hash->curlen > sizeof( hash->buf)) { + fatal(CRYPTO_ERR_PARAMETERS); + } + while (size > 0) { + if ( hash->curlen == 0 && size >= 64) { + crypto_sha1_compress(hash, (unsigned char *)data); + hash->length += 64 * 8; + data += 64; + size -= 64; + } else { + n = ( ((size)<((64 - hash->curlen)))?(size):((64 - hash->curlen)) ); + memcpy( hash->buf + hash->curlen, data, (size_t)n); + hash->curlen += n; + data += n; + size -= n; + if ( hash->curlen == 64) { + crypto_sha1_compress (hash, hash->buf); + hash->length += 8*64; + hash->curlen = 0; + } + } + } +} + +void crypto_sha1_end(crypto_sha1_t* hash, uint8_t* out) +{ + int i; + + if (hash->curlen >= sizeof(hash->buf)) { + fatal(CRYPTO_ERR_PARAMETERS); + } + + /* increase the length of the message */ + hash->length += hash->curlen * 8; + + /* append the '1' bit */ + hash->buf[hash->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (hash->curlen > 56) { + while (hash->curlen < 64) { + hash->buf[hash->curlen++] = (unsigned char)0; + } + crypto_sha1_compress(hash, hash->buf); + hash->curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (hash->curlen < 56) { + hash->buf[hash->curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(hash->length, hash->buf+56); + crypto_sha1_compress(hash, hash->buf); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32H(hash->state[i], out+(4*i)); + } +#ifdef CRYPT_CLEAN_STACK + zeromem(hash, sizeof(hash)); +#endif +} + +void crypto_sha1_copy(crypto_sha1_t* hashTo, crypto_sha1_t* hashFrom) +{ + memcpy(hashTo, hashFrom, sizeof(crypto_sha1_t)); +} + +void crypto_sha1_compress(crypto_sha1_t* hash, unsigned char *buf) +{ + ulong32 a,b,c,d,e,W[80],i; + + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* copy state */ + a = hash->state[0]; + b = hash->state[1]; + c = hash->state[2]; + d = hash->state[3]; + e = hash->state[4]; + + /* expand it */ + for (i = 16; i < 80; i++) { + W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + } + + /* compress */ + /* round one */ + #define F0(x,y,z) (z ^ (x & (y ^ z))) + #define F1(x,y,z) (x ^ y ^ z) + #define F2(x,y,z) ((x & y) | (z & (x | y))) + #define F3(x,y,z) (x ^ y ^ z) + #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); + #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); + #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); + #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); + +#ifdef CRYPT_SMALL_CODE + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + +#else + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); + FF0(e,a,b,c,d,i++); + FF0(d,e,a,b,c,i++); + FF0(c,d,e,a,b,i++); + FF0(b,c,d,e,a,i++); + } + + /* round two */ + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); + FF1(e,a,b,c,d,i++); + FF1(d,e,a,b,c,i++); + FF1(c,d,e,a,b,i++); + FF1(b,c,d,e,a,i++); + } + + /* round three */ + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); + FF2(e,a,b,c,d,i++); + FF2(d,e,a,b,c,i++); + FF2(c,d,e,a,b,i++); + FF2(b,c,d,e,a,i++); + } + + /* round four */ + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); + FF3(e,a,b,c,d,i++); + FF3(d,e,a,b,c,i++); + FF3(c,d,e,a,b,i++); + FF3(b,c,d,e,a,i++); + } +#endif + + #undef FF0 + #undef FF1 + #undef FF2 + #undef FF3 + + /* store */ + hash->state[0] = hash->state[0] + a; + hash->state[1] = hash->state[1] + b; + hash->state[2] = hash->state[2] + c; + hash->state[3] = hash->state[3] + d; + hash->state[4] = hash->state[4] + e; + +#if CRYPT_CLEAN_STACK + burn_stack(sizeof(ulong32) * 87); +#endif +}