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.

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
+}