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