Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 17:10:16 by
