Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
sha1.c
Go to the documentation of this file.
00001 /** 00002 * @file sha1.c 00003 * @brief SHA-1 (Secure Hash Algorithm 1) 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-1 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 "sha1.h" 00041 00042 //Check crypto library configuration 00043 #if (SHA1_SUPPORT == ENABLED) 00044 00045 //Macro to access the workspace as a circular buffer 00046 #define W(t) w[(t) & 0x0F] 00047 00048 //SHA-1 auxiliary functions 00049 #define CH(x, y, z) (((x) & (y)) | (~(x) & (z))) 00050 #define PARITY(x, y, z) ((x) ^ (y) ^ (z)) 00051 #define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 00052 00053 //SHA-1 padding 00054 static const uint8_t padding[64] = 00055 { 00056 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00060 }; 00061 00062 //SHA-1 constants 00063 static const uint32_t k[4] = 00064 { 00065 0x5A827999, 00066 0x6ED9EBA1, 00067 0x8F1BBCDC, 00068 0xCA62C1D6 00069 }; 00070 00071 //SHA-1 object identifier (1.3.14.3.2.26) 00072 static const uint8_t sha1Oid[] = {0x2B, 0x0E, 0x03, 0x02, 0x1A}; 00073 00074 //Common interface for hash algorithms 00075 const HashAlgo sha1HashAlgo = 00076 { 00077 "SHA-1", 00078 sha1Oid, 00079 sizeof(sha1Oid), 00080 sizeof(Sha1Context), 00081 SHA1_BLOCK_SIZE, 00082 SHA1_DIGEST_SIZE, 00083 (HashAlgoCompute) sha1Compute, 00084 (HashAlgoInit) sha1Init, 00085 (HashAlgoUpdate) sha1Update, 00086 (HashAlgoFinal) sha1Final 00087 }; 00088 00089 00090 /** 00091 * @brief Digest a message using SHA-1 00092 * @param[in] data Pointer to the message being hashed 00093 * @param[in] length Length of the message 00094 * @param[out] digest Pointer to the calculated digest 00095 * @return Error code 00096 **/ 00097 00098 error_t sha1Compute(const void *data, size_t length, uint8_t *digest) 00099 { 00100 //Allocate a memory buffer to hold the SHA-1 context 00101 Sha1Context *context = cryptoAllocMem(sizeof(Sha1Context)); 00102 //Failed to allocate memory? 00103 if(context == NULL) 00104 return ERROR_OUT_OF_MEMORY; 00105 00106 //Initialize the SHA-1 context 00107 sha1Init(context); 00108 //Digest the message 00109 sha1Update(context, data, length); 00110 //Finalize the SHA-1 message digest 00111 sha1Final(context, digest); 00112 00113 //Free previously allocated memory 00114 cryptoFreeMem(context); 00115 //Successful processing 00116 return NO_ERROR; 00117 } 00118 00119 00120 /** 00121 * @brief Initialize SHA-1 message digest context 00122 * @param[in] context Pointer to the SHA-1 context to initialize 00123 **/ 00124 00125 void sha1Init(Sha1Context *context) 00126 { 00127 //Set initial hash value 00128 context->h[0] = 0x67452301; 00129 context->h[1] = 0xEFCDAB89; 00130 context->h[2] = 0x98BADCFE; 00131 context->h[3] = 0x10325476; 00132 context->h[4] = 0xC3D2E1F0; 00133 00134 //Number of bytes in the buffer 00135 context->size = 0; 00136 //Total length of the message 00137 context->totalSize = 0; 00138 } 00139 00140 00141 /** 00142 * @brief Update the SHA-1 context with a portion of the message being hashed 00143 * @param[in] context Pointer to the SHA-1 context 00144 * @param[in] data Pointer to the buffer being hashed 00145 * @param[in] length Length of the buffer 00146 **/ 00147 00148 void sha1Update(Sha1Context *context, const void *data, size_t length) 00149 { 00150 size_t n; 00151 00152 //Process the incoming data 00153 while(length > 0) 00154 { 00155 //The buffer can hold at most 64 bytes 00156 n = MIN(length, 64 - context->size); 00157 00158 //Copy the data to the buffer 00159 memcpy(context->buffer + context->size, data, n); 00160 00161 //Update the SHA-1 context 00162 context->size += n; 00163 context->totalSize += n; 00164 //Advance the data pointer 00165 data = (uint8_t *) data + n; 00166 //Remaining bytes to process 00167 length -= n; 00168 00169 //Process message in 16-word blocks 00170 if(context->size == 64) 00171 { 00172 //Transform the 16-word block 00173 sha1ProcessBlock(context); 00174 //Empty the buffer 00175 context->size = 0; 00176 } 00177 } 00178 } 00179 00180 00181 /** 00182 * @brief Finish the SHA-1 message digest 00183 * @param[in] context Pointer to the SHA-1 context 00184 * @param[out] digest Calculated digest (optional parameter) 00185 **/ 00186 00187 void sha1Final(Sha1Context *context, uint8_t *digest) 00188 { 00189 uint_t i; 00190 size_t paddingSize; 00191 uint64_t totalSize; 00192 00193 //Length of the original message (before padding) 00194 totalSize = context->totalSize * 8; 00195 00196 //Pad the message so that its length is congruent to 56 modulo 64 00197 if(context->size < 56) 00198 paddingSize = 56 - context->size; 00199 else 00200 paddingSize = 64 + 56 - context->size; 00201 00202 //Append padding 00203 sha1Update(context, padding, paddingSize); 00204 00205 //Append the length of the original message 00206 context->w[14] = htobe32((uint32_t) (totalSize >> 32)); 00207 context->w[15] = htobe32((uint32_t) totalSize); 00208 00209 //Calculate the message digest 00210 sha1ProcessBlock(context); 00211 00212 //Convert from host byte order to big-endian byte order 00213 for(i = 0; i < 5; i++) 00214 context->h[i] = htobe32(context->h[i]); 00215 00216 //Copy the resulting digest 00217 if(digest != NULL) 00218 memcpy(digest, context->digest, SHA1_DIGEST_SIZE); 00219 } 00220 00221 00222 /** 00223 * @brief Process message in 16-word blocks 00224 * @param[in] context Pointer to the SHA-1 context 00225 **/ 00226 00227 void sha1ProcessBlock(Sha1Context *context) 00228 { 00229 uint_t t; 00230 uint32_t temp; 00231 00232 //Initialize the 5 working registers 00233 uint32_t a = context->h[0]; 00234 uint32_t b = context->h[1]; 00235 uint32_t c = context->h[2]; 00236 uint32_t d = context->h[3]; 00237 uint32_t e = context->h[4]; 00238 00239 //Process message in 16-word blocks 00240 uint32_t *w = context->w; 00241 00242 //Convert from big-endian byte order to host byte order 00243 for(t = 0; t < 16; t++) 00244 w[t] = betoh32(w[t]); 00245 00246 //SHA-1 hash computation (alternate method) 00247 for(t = 0; t < 80; t++) 00248 { 00249 //Prepare the message schedule 00250 if(t >= 16) 00251 W(t) = ROL32(W(t + 13) ^ W(t + 8) ^ W(t + 2) ^ W(t), 1); 00252 00253 //Calculate T 00254 if(t < 20) 00255 temp = ROL32(a, 5) + CH(b, c, d) + e + W(t) + k[0]; 00256 else if(t < 40) 00257 temp = ROL32(a, 5) + PARITY(b, c, d) + e + W(t) + k[1]; 00258 else if(t < 60) 00259 temp = ROL32(a, 5) + MAJ(b, c, d) + e + W(t) + k[2]; 00260 else 00261 temp = ROL32(a, 5) + PARITY(b, c, d) + e + W(t) + k[3]; 00262 00263 //Update the working registers 00264 e = d; 00265 d = c; 00266 c = ROL32(b, 30); 00267 b = a; 00268 a = temp; 00269 } 00270 00271 //Update the hash value 00272 context->h[0] += a; 00273 context->h[1] += b; 00274 context->h[2] += c; 00275 context->h[3] += d; 00276 context->h[4] += e; 00277 } 00278 00279 #endif 00280
Generated on Tue Jul 12 2022 17:10:16 by
