ARM Shanghai IoT Team (Internal) / newMiniTLS-GPL

Fork of MiniTLS-GPL by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers crypto_sha1.c Source File

crypto_sha1.c

Go to the documentation of this file.
00001 /*
00002 MiniTLS - A super trimmed down TLS/SSL Library for embedded devices
00003 Author: Donatien Garnier
00004 Copyright (C) 2013-2014 AppNearMe Ltd
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU General Public License
00008 as published by the Free Software Foundation; either version 2
00009 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019 *//**
00020  * \file crypto_sha1.c
00021  * \copyright Copyright (c) AppNearMe Ltd 2013
00022  * \author Donatien Garnier
00023  */
00024 
00025 #define __DEBUG__ 0
00026 #define __MODULE__ "crypto_sha1.c"
00027 
00028 //This module has been adapted from libtomcrypt (http://libtom.org/)
00029 
00030 #include "core/fwk.h"
00031 #include "crypto_sha1.h"
00032 #include "inc/minitls_errors.h"
00033 #include "crypto_macros.h"
00034 
00035 #define fatal(x) do{ ERR("Fatal error %s - %d", #x, x); while(1); }while(0)
00036 
00037 static void crypto_sha1_compress(crypto_sha1_t* hash, unsigned char *buf);
00038 
00039 void crypto_sha1_init(crypto_sha1_t* hash)
00040 {
00041   hash->state[0] = 0x67452301UL;
00042   hash->state[1] = 0xefcdab89UL;
00043   hash->state[2] = 0x98badcfeUL;
00044   hash->state[3] = 0x10325476UL;
00045   hash->state[4] = 0xc3d2e1f0UL;
00046   hash->curlen = 0;
00047   hash->length = 0;
00048 }
00049 
00050 void crypto_sha1_update(crypto_sha1_t* hash, const uint8_t* data, size_t size)
00051 {
00052     unsigned long n;
00053 
00054     if ( hash->curlen > sizeof( hash->buf)) {
00055       fatal(CRYPTO_ERR_PARAMETERS);
00056     }
00057     while (size > 0) {
00058         if ( hash->curlen == 0 && size >= 64) {
00059            crypto_sha1_compress(hash, (unsigned char *)data);
00060            hash->length += 64 * 8;
00061            data             += 64;
00062            size          -= 64;
00063         } else {
00064            n = ( ((size)<((64 -  hash->curlen)))?(size):((64 -  hash->curlen)) );
00065            memcpy( hash->buf + hash->curlen, data, (size_t)n);
00066            hash->curlen += n;
00067            data         += n;
00068            size         -= n;
00069            if ( hash->curlen == 64) {
00070                crypto_sha1_compress (hash,  hash->buf);
00071                hash->length += 8*64;
00072                hash->curlen = 0;
00073            }
00074        }
00075     }
00076 }
00077 
00078 void crypto_sha1_end(crypto_sha1_t* hash, uint8_t* out)
00079 {
00080   int i;
00081 
00082   if (hash->curlen >= sizeof(hash->buf)) {
00083     fatal(CRYPTO_ERR_PARAMETERS);
00084   }
00085 
00086   /* increase the length of the message */
00087   hash->length += hash->curlen * 8;
00088 
00089   /* append the '1' bit */
00090   hash->buf[hash->curlen++] = (unsigned char)0x80;
00091 
00092   /* if the length is currently above 56 bytes we append zeros
00093    * then compress.  Then we can fall back to padding zeros and length
00094    * encoding like normal.
00095    */
00096   if (hash->curlen > 56) {
00097       while (hash->curlen < 64) {
00098           hash->buf[hash->curlen++] = (unsigned char)0;
00099       }
00100       crypto_sha1_compress(hash, hash->buf);
00101       hash->curlen = 0;
00102   }
00103 
00104   /* pad upto 56 bytes of zeroes */
00105   while (hash->curlen < 56) {
00106       hash->buf[hash->curlen++] = (unsigned char)0;
00107   }
00108 
00109   /* store length */
00110   STORE64H(hash->length, hash->buf+56);
00111   crypto_sha1_compress(hash, hash->buf);
00112 
00113   /* copy output */
00114   for (i = 0; i < 5; i++) {
00115       STORE32H(hash->state[i], out+(4*i));
00116   }
00117 #ifdef CRYPT_CLEAN_STACK
00118   zeromem(hash, sizeof(hash));
00119 #endif
00120 }
00121 
00122 void crypto_sha1_copy(crypto_sha1_t* hashTo, crypto_sha1_t* hashFrom)
00123 {
00124   memcpy(hashTo, hashFrom, sizeof(crypto_sha1_t));
00125 }
00126 
00127 void crypto_sha1_compress(crypto_sha1_t* hash, unsigned char *buf)
00128 {
00129     ulong32 a,b,c,d,e,W[80],i;
00130 
00131 
00132     /* copy the state into 512-bits into W[0..15] */
00133     for (i = 0; i < 16; i++) {
00134         LOAD32H(W[i], buf + (4*i));
00135     }
00136 
00137     /* copy state */
00138     a = hash->state[0];
00139     b = hash->state[1];
00140     c = hash->state[2];
00141     d = hash->state[3];
00142     e = hash->state[4];
00143 
00144     /* expand it */
00145     for (i = 16; i < 80; i++) {
00146         W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
00147     }
00148 
00149     /* compress */
00150     /* round one */
00151     #define F0(x,y,z)  (z ^ (x & (y ^ z)))
00152     #define F1(x,y,z)  (x ^ y ^ z)
00153     #define F2(x,y,z)  ((x & y) | (z & (x | y)))
00154     #define F3(x,y,z)  (x ^ y ^ z)
00155     #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
00156     #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
00157     #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
00158     #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
00159 
00160 #ifdef CRYPT_SMALL_CODE
00161 
00162     for (i = 0; i < 20; ) {
00163        FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
00164     }
00165 
00166     for (; i < 40; ) {
00167        FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
00168     }
00169 
00170     for (; i < 60; ) {
00171        FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
00172     }
00173 
00174     for (; i < 80; ) {
00175        FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
00176     }
00177 
00178 #else
00179 
00180     for (i = 0; i < 20; ) {
00181        FF0(a,b,c,d,e,i++);
00182        FF0(e,a,b,c,d,i++);
00183        FF0(d,e,a,b,c,i++);
00184        FF0(c,d,e,a,b,i++);
00185        FF0(b,c,d,e,a,i++);
00186     }
00187 
00188     /* round two */
00189     for (; i < 40; )  {
00190        FF1(a,b,c,d,e,i++);
00191        FF1(e,a,b,c,d,i++);
00192        FF1(d,e,a,b,c,i++);
00193        FF1(c,d,e,a,b,i++);
00194        FF1(b,c,d,e,a,i++);
00195     }
00196 
00197     /* round three */
00198     for (; i < 60; )  {
00199        FF2(a,b,c,d,e,i++);
00200        FF2(e,a,b,c,d,i++);
00201        FF2(d,e,a,b,c,i++);
00202        FF2(c,d,e,a,b,i++);
00203        FF2(b,c,d,e,a,i++);
00204     }
00205 
00206     /* round four */
00207     for (; i < 80; )  {
00208        FF3(a,b,c,d,e,i++);
00209        FF3(e,a,b,c,d,i++);
00210        FF3(d,e,a,b,c,i++);
00211        FF3(c,d,e,a,b,i++);
00212        FF3(b,c,d,e,a,i++);
00213     }
00214 #endif
00215 
00216     #undef FF0
00217     #undef FF1
00218     #undef FF2
00219     #undef FF3
00220 
00221     /* store */
00222     hash->state[0] = hash->state[0] + a;
00223     hash->state[1] = hash->state[1] + b;
00224     hash->state[2] = hash->state[2] + c;
00225     hash->state[3] = hash->state[3] + d;
00226     hash->state[4] = hash->state[4] + e;
00227 
00228 #if CRYPT_CLEAN_STACK
00229     burn_stack(sizeof(ulong32) * 87);
00230 #endif
00231 }