Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sha512.c Source File

sha512.c

Go to the documentation of this file.
00001 /**
00002  * @file sha512.c
00003  * @brief SHA-512 (Secure Hash Algorithm 512)
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-512 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 "sha512.h"
00041 
00042 //Check crypto library configuration
00043 #if (SHA384_SUPPORT == ENABLED || SHA512_SUPPORT == ENABLED || \
00044    SHA512_224_SUPPORT == ENABLED || SHA512_256_SUPPORT == ENABLED)
00045 
00046 //Macro to access the workspace as a circular buffer
00047 #define W(t) w[(t) & 0x0F]
00048 
00049 //SHA-512 auxiliary functions
00050 #define CH(x, y, z) (((x) & (y)) | (~(x) & (z)))
00051 #define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
00052 #define SIGMA1(x) (ROR64(x, 28) ^ ROR64(x, 34) ^ ROR64(x, 39))
00053 #define SIGMA2(x) (ROR64(x, 14) ^ ROR64(x, 18) ^ ROR64(x, 41))
00054 #define SIGMA3(x) (ROR64(x, 1) ^ ROR64(x, 8) ^ SHR64(x, 7))
00055 #define SIGMA4(x) (ROR64(x, 19) ^ ROR64(x, 61) ^ SHR64(x, 6))
00056 
00057 //SHA-512 padding
00058 static const uint8_t padding[128] =
00059 {
00060    0x80, 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    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00064    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00065    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00066    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00067    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00068 };
00069 
00070 //SHA-512 constants
00071 static const uint64_t k[80] =
00072 {
00073    0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
00074    0x3956C25BF348B538, 0x59F111F1B605D019, 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
00075    0xD807AA98A3030242, 0x12835B0145706FBE, 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
00076    0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, 0x9BDC06A725C71235, 0xC19BF174CF692694,
00077    0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
00078    0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
00079    0x983E5152EE66DFAB, 0xA831C66D2DB43210, 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
00080    0xC6E00BF33DA88FC2, 0xD5A79147930AA725, 0x06CA6351E003826F, 0x142929670A0E6E70,
00081    0x27B70A8546D22FFC, 0x2E1B21385C26C926, 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
00082    0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, 0x81C2C92E47EDAEE6, 0x92722C851482353B,
00083    0xA2BFE8A14CF10364, 0xA81A664BBC423001, 0xC24B8B70D0F89791, 0xC76C51A30654BE30,
00084    0xD192E819D6EF5218, 0xD69906245565A910, 0xF40E35855771202A, 0x106AA07032BBD1B8,
00085    0x19A4C116B8D2D0C8, 0x1E376C085141AB53, 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
00086    0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
00087    0x748F82EE5DEFB2FC, 0x78A5636F43172F60, 0x84C87814A1F0AB72, 0x8CC702081A6439EC,
00088    0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, 0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
00089    0xCA273ECEEA26619C, 0xD186B8C721C0C207, 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
00090    0x06F067AA72176FBA, 0x0A637DC5A2C898A6, 0x113F9804BEF90DAE, 0x1B710B35131C471B,
00091    0x28DB77F523047D84, 0x32CAAB7B40C72493, 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
00092    0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817
00093 };
00094 
00095 //SHA-512 object identifier (2.16.840.1.101.3.4.2.3)
00096 static const uint8_t sha512Oid[] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03};
00097 
00098 //Common interface for hash algorithms
00099 const HashAlgo sha512HashAlgo =
00100 {
00101    "SHA-512",
00102    sha512Oid,
00103    sizeof(sha512Oid),
00104    sizeof(Sha512Context),
00105    SHA512_BLOCK_SIZE,
00106    SHA512_DIGEST_SIZE,
00107    (HashAlgoCompute) sha512Compute,
00108    (HashAlgoInit) sha512Init,
00109    (HashAlgoUpdate) sha512Update,
00110    (HashAlgoFinal) sha512Final
00111 };
00112 
00113 
00114 /**
00115  * @brief Digest a message using SHA-512
00116  * @param[in] data Pointer to the message being hashed
00117  * @param[in] length Length of the message
00118  * @param[out] digest Pointer to the calculated digest
00119  * @return Error code
00120  **/
00121 
00122 error_t sha512Compute(const void *data, size_t length, uint8_t *digest)
00123 {
00124    //Allocate a memory buffer to hold the SHA-512 context
00125    Sha512Context *context = cryptoAllocMem(sizeof(Sha512Context));
00126    //Failed to allocate memory?
00127    if(context == NULL)
00128       return ERROR_OUT_OF_MEMORY;
00129 
00130    //Initialize the SHA-512 context
00131    sha512Init(context);
00132    //Digest the message
00133    sha512Update(context, data, length);
00134    //Finalize the SHA-512 message digest
00135    sha512Final(context, digest);
00136 
00137    //Free previously allocated memory
00138    cryptoFreeMem(context);
00139    //Successful processing
00140    return NO_ERROR;
00141 }
00142 
00143 
00144 /**
00145  * @brief Initialize SHA-512 message digest context
00146  * @param[in] context Pointer to the SHA-512 context to initialize
00147  **/
00148 
00149 void sha512Init(Sha512Context *context)
00150 {
00151    //Set initial hash value
00152    context->h[0] = 0x6A09E667F3BCC908;
00153    context->h[1] = 0xBB67AE8584CAA73B;
00154    context->h[2] = 0x3C6EF372FE94F82B;
00155    context->h[3] = 0xA54FF53A5F1D36F1;
00156    context->h[4] = 0x510E527FADE682D1;
00157    context->h[5] = 0x9B05688C2B3E6C1F;
00158    context->h[6] = 0x1F83D9ABFB41BD6B;
00159    context->h[7] = 0x5BE0CD19137E2179;
00160 
00161    //Number of bytes in the buffer
00162    context->size = 0;
00163    //Total length of the message
00164    context->totalSize = 0;
00165 }
00166 
00167 
00168 /**
00169  * @brief Update the SHA-512 context with a portion of the message being hashed
00170  * @param[in] context Pointer to the SHA-512 context
00171  * @param[in] data Pointer to the buffer being hashed
00172  * @param[in] length Length of the buffer
00173  **/
00174 
00175 void sha512Update(Sha512Context *context, const void *data, size_t length)
00176 {
00177    size_t n;
00178 
00179    //Process the incoming data
00180    while(length > 0)
00181    {
00182       //The buffer can hold at most 128 bytes
00183       n = MIN(length, 128 - context->size);
00184 
00185       //Copy the data to the buffer
00186       memcpy(context->buffer + context->size, data, n);
00187 
00188       //Update the SHA-512 context
00189       context->size += n;
00190       context->totalSize += n;
00191       //Advance the data pointer
00192       data = (uint8_t *) data + n;
00193       //Remaining bytes to process
00194       length -= n;
00195 
00196       //Process message in 16-word blocks
00197       if(context->size == 128)
00198       {
00199          //Transform the 16-word block
00200          sha512ProcessBlock(context);
00201          //Empty the buffer
00202          context->size = 0;
00203       }
00204    }
00205 }
00206 
00207 
00208 /**
00209  * @brief Finish the SHA-512 message digest
00210  * @param[in] context Pointer to the SHA-512 context
00211  * @param[out] digest Calculated digest (optional parameter)
00212  **/
00213 
00214 void sha512Final(Sha512Context *context, uint8_t *digest)
00215 {
00216    uint_t i;
00217    size_t paddingSize;
00218    uint64_t totalSize;
00219 
00220    //Length of the original message (before padding)
00221    totalSize = context->totalSize * 8;
00222 
00223    //Pad the message so that its length is congruent to 112 modulo 128
00224    if(context->size < 112)
00225       paddingSize = 112 - context->size;
00226    else
00227       paddingSize = 128 + 112 - context->size;
00228 
00229    //Append padding
00230    sha512Update(context, padding, paddingSize);
00231 
00232    //Append the length of the original message
00233    context->w[14] = 0;
00234    context->w[15] = htobe64(totalSize);
00235 
00236    //Calculate the message digest
00237    sha512ProcessBlock(context);
00238 
00239    //Convert from host byte order to big-endian byte order
00240    for(i = 0; i < 8; i++)
00241       context->h[i] = htobe64(context->h[i]);
00242 
00243    //Copy the resulting digest
00244    if(digest != NULL)
00245       memcpy(digest, context->digest, SHA512_DIGEST_SIZE);
00246 }
00247 
00248 
00249 /**
00250  * @brief Process message in 16-word blocks
00251  * @param[in] context Pointer to the SHA-512 context
00252  **/
00253 
00254 void sha512ProcessBlock(Sha512Context *context)
00255 {
00256    uint_t t;
00257    uint64_t temp1;
00258    uint64_t temp2;
00259 
00260    //Initialize the 8 working registers
00261    uint64_t a = context->h[0];
00262    uint64_t b = context->h[1];
00263    uint64_t c = context->h[2];
00264    uint64_t d = context->h[3];
00265    uint64_t e = context->h[4];
00266    uint64_t f = context->h[5];
00267    uint64_t g = context->h[6];
00268    uint64_t h = context->h[7];
00269 
00270    //Process message in 16-word blocks
00271    uint64_t *w = context->w;
00272 
00273    //Convert from big-endian byte order to host byte order
00274    for(t = 0; t < 16; t++)
00275       w[t] = betoh64(w[t]);
00276 
00277    //SHA-512 hash computation (alternate method)
00278    for(t = 0; t < 80; t++)
00279    {
00280       //Prepare the message schedule
00281       if(t >= 16)
00282          W(t) += SIGMA4(W(t + 14)) + W(t + 9) + SIGMA3(W(t + 1));
00283 
00284       //Calculate T1 and T2
00285       temp1 = h + SIGMA2(e) + CH(e, f, g) + k[t] + W(t);
00286       temp2 = SIGMA1(a) + MAJ(a, b, c);
00287 
00288       //Update the working registers
00289       h = g;
00290       g = f;
00291       f = e;
00292       e = d + temp1;
00293       d = c;
00294       c = b;
00295       b = a;
00296       a = temp1 + temp2;
00297    }
00298 
00299    //Update the hash value
00300    context->h[0] += a;
00301    context->h[1] += b;
00302    context->h[2] += c;
00303    context->h[3] += d;
00304    context->h[4] += e;
00305    context->h[5] += f;
00306    context->h[6] += g;
00307    context->h[7] += h;
00308 }
00309 
00310 #endif
00311