Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sha256.c Source File

sha256.c

Go to the documentation of this file.
00001 /**
00002  * @file sha256.c
00003  * @brief SHA-256 (Secure Hash Algorithm 256)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @section Description
00026  *
00027  * SHA-256 is a secure hash algorithm for computing a condensed representation
00028  * of an electronic message. Refer to FIPS 180-4 for more details
00029  *
00030  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00031  * @version 1.7.6
00032  **/
00033 
00034 //Switch to the appropriate trace level
00035 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00036 
00037 //Dependencies
00038 #include <string.h>
00039 #include "crypto.h"
00040 #include "sha256.h"
00041 
00042 //Check crypto library configuration
00043 #if (SHA224_SUPPORT == ENABLED || SHA256_SUPPORT == ENABLED)
00044 
00045 //Macro to access the workspace as a circular buffer
00046 #define W(t) w[(t) & 0x0F]
00047 
00048 //SHA-256 auxiliary functions
00049 #define CH(x, y, z) (((x) & (y)) | (~(x) & (z)))
00050 #define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
00051 #define SIGMA1(x) (ROR32(x, 2) ^ ROR32(x, 13) ^ ROR32(x, 22))
00052 #define SIGMA2(x) (ROR32(x, 6) ^ ROR32(x, 11) ^ ROR32(x, 25))
00053 #define SIGMA3(x) (ROR32(x, 7) ^ ROR32(x, 18) ^ SHR32(x, 3))
00054 #define SIGMA4(x) (ROR32(x, 17) ^ ROR32(x, 19) ^ SHR32(x, 10))
00055 
00056 //SHA-256 padding
00057 static const uint8_t padding[64] =
00058 {
00059    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00060    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00061    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00062    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00063 };
00064 
00065 //SHA-256 constants
00066 static const uint32_t k[64] =
00067 {
00068    0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
00069    0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
00070    0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
00071    0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
00072    0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
00073    0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
00074    0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
00075    0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
00076 };
00077 
00078 //SHA-256 object identifier (2.16.840.1.101.3.4.2.1)
00079 static const uint8_t sha256Oid[] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01};
00080 
00081 //Common interface for hash algorithms
00082 const HashAlgo sha256HashAlgo =
00083 {
00084    "SHA-256",
00085    sha256Oid,
00086    sizeof(sha256Oid),
00087    sizeof(Sha256Context),
00088    SHA256_BLOCK_SIZE,
00089    SHA256_DIGEST_SIZE,
00090    (HashAlgoCompute) sha256Compute,
00091    (HashAlgoInit) sha256Init,
00092    (HashAlgoUpdate) sha256Update,
00093    (HashAlgoFinal) sha256Final
00094 };
00095 
00096 
00097 /**
00098  * @brief Digest a message using SHA-256
00099  * @param[in] data Pointer to the message being hashed
00100  * @param[in] length Length of the message
00101  * @param[out] digest Pointer to the calculated digest
00102  * @return Error code
00103  **/
00104 
00105 error_t sha256Compute(const void *data, size_t length, uint8_t *digest)
00106 {
00107    //Allocate a memory buffer to hold the SHA-256 context
00108    Sha256Context *context = cryptoAllocMem(sizeof(Sha256Context));
00109    //Failed to allocate memory?
00110    if(context == NULL)
00111       return ERROR_OUT_OF_MEMORY;
00112 
00113    //Initialize the SHA-256 context
00114    sha256Init(context);
00115    //Digest the message
00116    sha256Update(context, data, length);
00117    //Finalize the SHA-256 message digest
00118    sha256Final(context, digest);
00119 
00120    //Free previously allocated memory
00121    cryptoFreeMem(context);
00122    //Successful processing
00123    return NO_ERROR;
00124 }
00125 
00126 
00127 /**
00128  * @brief Initialize SHA-256 message digest context
00129  * @param[in] context Pointer to the SHA-256 context to initialize
00130  **/
00131 
00132 void sha256Init(Sha256Context *context)
00133 {
00134    //Set initial hash value
00135    context->h[0] = 0x6A09E667;
00136    context->h[1] = 0xBB67AE85;
00137    context->h[2] = 0x3C6EF372;
00138    context->h[3] = 0xA54FF53A;
00139    context->h[4] = 0x510E527F;
00140    context->h[5] = 0x9B05688C;
00141    context->h[6] = 0x1F83D9AB;
00142    context->h[7] = 0x5BE0CD19;
00143 
00144    //Number of bytes in the buffer
00145    context->size = 0;
00146    //Total length of the message
00147    context->totalSize = 0;
00148 }
00149 
00150 
00151 /**
00152  * @brief Update the SHA-256 context with a portion of the message being hashed
00153  * @param[in] context Pointer to the SHA-256 context
00154  * @param[in] data Pointer to the buffer being hashed
00155  * @param[in] length Length of the buffer
00156  **/
00157 
00158 void sha256Update(Sha256Context *context, const void *data, size_t length)
00159 {
00160    size_t n;
00161 
00162    //Process the incoming data
00163    while(length > 0)
00164    {
00165       //The buffer can hold at most 64 bytes
00166       n = MIN(length, 64 - context->size);
00167 
00168       //Copy the data to the buffer
00169       memcpy(context->buffer + context->size, data, n);
00170 
00171       //Update the SHA-256 context
00172       context->size += n;
00173       context->totalSize += n;
00174       //Advance the data pointer
00175       data = (uint8_t *) data + n;
00176       //Remaining bytes to process
00177       length -= n;
00178 
00179       //Process message in 16-word blocks
00180       if(context->size == 64)
00181       {
00182          //Transform the 16-word block
00183          sha256ProcessBlock(context);
00184          //Empty the buffer
00185          context->size = 0;
00186       }
00187    }
00188 }
00189 
00190 
00191 /**
00192  * @brief Finish the SHA-256 message digest
00193  * @param[in] context Pointer to the SHA-256 context
00194  * @param[out] digest Calculated digest (optional parameter)
00195  **/
00196 
00197 void sha256Final(Sha256Context *context, uint8_t *digest)
00198 {
00199    uint_t i;
00200    size_t paddingSize;
00201    uint64_t totalSize;
00202 
00203    //Length of the original message (before padding)
00204    totalSize = context->totalSize * 8;
00205 
00206    //Pad the message so that its length is congruent to 56 modulo 64
00207    if(context->size < 56)
00208       paddingSize = 56 - context->size;
00209    else
00210       paddingSize = 64 + 56 - context->size;
00211 
00212    //Append padding
00213    sha256Update(context, padding, paddingSize);
00214 
00215    //Append the length of the original message
00216    context->w[14] = htobe32((uint32_t) (totalSize >> 32));
00217    context->w[15] = htobe32((uint32_t) totalSize);
00218 
00219    //Calculate the message digest
00220    sha256ProcessBlock(context);
00221 
00222    //Convert from host byte order to big-endian byte order
00223    for(i = 0; i < 8; i++)
00224       context->h[i] = htobe32(context->h[i]);
00225 
00226    //Copy the resulting digest
00227    if(digest != NULL)
00228       memcpy(digest, context->digest, SHA256_DIGEST_SIZE);
00229 }
00230 
00231 
00232 /**
00233  * @brief Process message in 16-word blocks
00234  * @param[in] context Pointer to the SHA-256 context
00235  **/
00236 
00237 void sha256ProcessBlock(Sha256Context *context)
00238 {
00239    uint_t t;
00240    uint32_t temp1;
00241    uint32_t temp2;
00242 
00243    //Initialize the 8 working registers
00244    uint32_t a = context->h[0];
00245    uint32_t b = context->h[1];
00246    uint32_t c = context->h[2];
00247    uint32_t d = context->h[3];
00248    uint32_t e = context->h[4];
00249    uint32_t f = context->h[5];
00250    uint32_t g = context->h[6];
00251    uint32_t h = context->h[7];
00252 
00253    //Process message in 16-word blocks
00254    uint32_t *w = context->w;
00255 
00256    //Convert from big-endian byte order to host byte order
00257    for(t = 0; t < 16; t++)
00258       w[t] = betoh32(w[t]);
00259 
00260    //SHA-256 hash computation (alternate method)
00261    for(t = 0; t < 64; t++)
00262    {
00263       //Prepare the message schedule
00264       if(t >= 16)
00265          W(t) += SIGMA4(W(t + 14)) + W(t + 9) + SIGMA3(W(t + 1));
00266 
00267       //Calculate T1 and T2
00268       temp1 = h + SIGMA2(e) + CH(e, f, g) + k[t] + W(t);
00269       temp2 = SIGMA1(a) + MAJ(a, b, c);
00270 
00271       //Update the working registers
00272       h = g;
00273       g = f;
00274       f = e;
00275       e = d + temp1;
00276       d = c;
00277       c = b;
00278       b = a;
00279       a = temp1 + temp2;
00280    }
00281 
00282    //Update the hash value
00283    context->h[0] += a;
00284    context->h[1] += b;
00285    context->h[2] += c;
00286    context->h[3] += d;
00287    context->h[4] += e;
00288    context->h[5] += f;
00289    context->h[6] += g;
00290    context->h[7] += h;
00291 }
00292 
00293 #endif
00294