Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
md5.c
Go to the documentation of this file.
00001 /** 00002 * @file md5.c 00003 * @brief MD5 (Message-Digest Algorithm) 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 * The MD5 algorithm takes as input a message of arbitrary length and produces 00028 * as output a 128-bit message digest of the input. Refer to RFC 1321 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 "md5.h" 00041 00042 //Check crypto library configuration 00043 #if (MD5_SUPPORT == ENABLED) 00044 00045 //MD5 auxiliary functions 00046 #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 00047 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 00048 #define H(x, y, z) ((x) ^ (y) ^ (z)) 00049 #define I(x, y, z) ((y) ^ ((x) | ~(z))) 00050 00051 #define FF(a, b, c, d, x, s, k) a += F(b, c, d) + (x) + (k), a = ROL32(a, s) + (b) 00052 #define GG(a, b, c, d, x, s, k) a += G(b, c, d) + (x) + (k), a = ROL32(a, s) + (b) 00053 #define HH(a, b, c, d, x, s, k) a += H(b, c, d) + (x) + (k), a = ROL32(a, s) + (b) 00054 #define II(a, b, c, d, x, s, k) a += I(b, c, d) + (x) + (k), a = ROL32(a, s) + (b) 00055 00056 //MD5 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 //MD5 constants 00066 static const uint32_t k[64] = 00067 { 00068 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, 00069 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, 00070 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, 00071 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, 00072 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, 00073 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, 00074 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, 00075 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 00076 }; 00077 00078 //MD5 object identifier (1.2.840.113549.2.5) 00079 static const uint8_t md5Oid[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05}; 00080 00081 //Common interface for hash algorithms 00082 const HashAlgo md5HashAlgo = 00083 { 00084 "MD5", 00085 md5Oid, 00086 sizeof(md5Oid), 00087 sizeof(Md5Context), 00088 MD5_BLOCK_SIZE, 00089 MD5_DIGEST_SIZE, 00090 (HashAlgoCompute) md5Compute, 00091 (HashAlgoInit) md5Init, 00092 (HashAlgoUpdate) md5Update, 00093 (HashAlgoFinal) md5Final 00094 }; 00095 00096 00097 /** 00098 * @brief Digest a message using MD5 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 md5Compute(const void *data, size_t length, uint8_t *digest) 00106 { 00107 //Allocate a memory buffer to hold the MD5 context 00108 Md5Context *context = cryptoAllocMem(sizeof(Md5Context)); 00109 //Failed to allocate memory? 00110 if(context == NULL) 00111 return ERROR_OUT_OF_MEMORY; 00112 00113 //Initialize the MD5 context 00114 md5Init(context); 00115 //Digest the message 00116 md5Update(context, data, length); 00117 //Finalize the MD5 message digest 00118 md5Final(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 MD5 message digest context 00129 * @param[in] context Pointer to the MD5 context to initialize 00130 **/ 00131 00132 void md5Init(Md5Context *context) 00133 { 00134 //Set initial hash value 00135 context->h[0] = 0x67452301; 00136 context->h[1] = 0xEFCDAB89; 00137 context->h[2] = 0x98BADCFE; 00138 context->h[3] = 0x10325476; 00139 00140 //Number of bytes in the buffer 00141 context->size = 0; 00142 //Total length of the message 00143 context->totalSize = 0; 00144 } 00145 00146 00147 /** 00148 * @brief Update the MD5 context with a portion of the message being hashed 00149 * @param[in] context Pointer to the MD5 context 00150 * @param[in] data Pointer to the buffer being hashed 00151 * @param[in] length Length of the buffer 00152 **/ 00153 00154 void md5Update(Md5Context *context, const void *data, size_t length) 00155 { 00156 size_t n; 00157 00158 //Process the incoming data 00159 while(length > 0) 00160 { 00161 //The buffer can hold at most 64 bytes 00162 n = MIN(length, 64 - context->size); 00163 00164 //Copy the data to the buffer 00165 memcpy(context->buffer + context->size, data, n); 00166 00167 //Update the MD5 context 00168 context->size += n; 00169 context->totalSize += n; 00170 //Advance the data pointer 00171 data = (uint8_t *) data + n; 00172 //Remaining bytes to process 00173 length -= n; 00174 00175 //Process message in 16-word blocks 00176 if(context->size == 64) 00177 { 00178 //Transform the 16-word block 00179 md5ProcessBlock(context); 00180 //Empty the buffer 00181 context->size = 0; 00182 } 00183 } 00184 } 00185 00186 00187 /** 00188 * @brief Finish the MD5 message digest 00189 * @param[in] context Pointer to the MD5 context 00190 * @param[out] digest Calculated digest (optional parameter) 00191 **/ 00192 00193 void md5Final(Md5Context *context, uint8_t *digest) 00194 { 00195 uint_t i; 00196 size_t paddingSize; 00197 uint64_t totalSize; 00198 00199 //Length of the original message (before padding) 00200 totalSize = context->totalSize * 8; 00201 00202 //Pad the message so that its length is congruent to 56 modulo 64 00203 if(context->size < 56) 00204 paddingSize = 56 - context->size; 00205 else 00206 paddingSize = 64 + 56 - context->size; 00207 00208 //Append padding 00209 md5Update(context, padding, paddingSize); 00210 00211 //Append the length of the original message 00212 context->x[14] = htole32((uint32_t) totalSize); 00213 context->x[15] = htole32((uint32_t) (totalSize >> 32)); 00214 00215 //Calculate the message digest 00216 md5ProcessBlock(context); 00217 00218 //Convert from host byte order to little-endian byte order 00219 for(i = 0; i < 4; i++) 00220 context->h[i] = htole32(context->h[i]); 00221 00222 //Copy the resulting digest 00223 if(digest != NULL) 00224 memcpy(digest, context->digest, MD5_DIGEST_SIZE); 00225 } 00226 00227 00228 /** 00229 * @brief Process message in 16-word blocks 00230 * @param[in] context Pointer to the MD5 context 00231 **/ 00232 00233 void md5ProcessBlock(Md5Context *context) 00234 { 00235 uint_t i; 00236 00237 //Initialize the 4 working registers 00238 uint32_t a = context->h[0]; 00239 uint32_t b = context->h[1]; 00240 uint32_t c = context->h[2]; 00241 uint32_t d = context->h[3]; 00242 00243 //Process message in 16-word blocks 00244 uint32_t *x = context->x; 00245 00246 //Convert from little-endian byte order to host byte order 00247 for(i = 0; i < 16; i++) 00248 x[i] = letoh32(x[i]); 00249 00250 //Round 1 00251 FF(a, b, c, d, x[0], 7, k[0]); 00252 FF(d, a, b, c, x[1], 12, k[1]); 00253 FF(c, d, a, b, x[2], 17, k[2]); 00254 FF(b, c, d, a, x[3], 22, k[3]); 00255 FF(a, b, c, d, x[4], 7, k[4]); 00256 FF(d, a, b, c, x[5], 12, k[5]); 00257 FF(c, d, a, b, x[6], 17, k[6]); 00258 FF(b, c, d, a, x[7], 22, k[7]); 00259 FF(a, b, c, d, x[8], 7, k[8]); 00260 FF(d, a, b, c, x[9], 12, k[9]); 00261 FF(c, d, a, b, x[10], 17, k[10]); 00262 FF(b, c, d, a, x[11], 22, k[11]); 00263 FF(a, b, c, d, x[12], 7, k[12]); 00264 FF(d, a, b, c, x[13], 12, k[13]); 00265 FF(c, d, a, b, x[14], 17, k[14]); 00266 FF(b, c, d, a, x[15], 22, k[15]); 00267 00268 //Round 2 00269 GG(a, b, c, d, x[1], 5, k[16]); 00270 GG(d, a, b, c, x[6], 9, k[17]); 00271 GG(c, d, a, b, x[11], 14, k[18]); 00272 GG(b, c, d, a, x[0], 20, k[19]); 00273 GG(a, b, c, d, x[5], 5, k[20]); 00274 GG(d, a, b, c, x[10], 9, k[21]); 00275 GG(c, d, a, b, x[15], 14, k[22]); 00276 GG(b, c, d, a, x[4], 20, k[23]); 00277 GG(a, b, c, d, x[9], 5, k[24]); 00278 GG(d, a, b, c, x[14], 9, k[25]); 00279 GG(c, d, a, b, x[3], 14, k[26]); 00280 GG(b, c, d, a, x[8], 20, k[27]); 00281 GG(a, b, c, d, x[13], 5, k[28]); 00282 GG(d, a, b, c, x[2], 9, k[29]); 00283 GG(c, d, a, b, x[7], 14, k[30]); 00284 GG(b, c, d, a, x[12], 20, k[31]); 00285 00286 //Round 3 00287 HH(a, b, c, d, x[5], 4, k[32]); 00288 HH(d, a, b, c, x[8], 11, k[33]); 00289 HH(c, d, a, b, x[11], 16, k[34]); 00290 HH(b, c, d, a, x[14], 23, k[35]); 00291 HH(a, b, c, d, x[1], 4, k[36]); 00292 HH(d, a, b, c, x[4], 11, k[37]); 00293 HH(c, d, a, b, x[7], 16, k[38]); 00294 HH(b, c, d, a, x[10], 23, k[39]); 00295 HH(a, b, c, d, x[13], 4, k[40]); 00296 HH(d, a, b, c, x[0], 11, k[41]); 00297 HH(c, d, a, b, x[3], 16, k[42]); 00298 HH(b, c, d, a, x[6], 23, k[43]); 00299 HH(a, b, c, d, x[9], 4, k[44]); 00300 HH(d, a, b, c, x[12], 11, k[45]); 00301 HH(c, d, a, b, x[15], 16, k[46]); 00302 HH(b, c, d, a, x[2], 23, k[47]); 00303 00304 //Round 4 00305 II(a, b, c, d, x[0], 6, k[48]); 00306 II(d, a, b, c, x[7], 10, k[49]); 00307 II(c, d, a, b, x[14], 15, k[50]); 00308 II(b, c, d, a, x[5], 21, k[51]); 00309 II(a, b, c, d, x[12], 6, k[52]); 00310 II(d, a, b, c, x[3], 10, k[53]); 00311 II(c, d, a, b, x[10], 15, k[54]); 00312 II(b, c, d, a, x[1], 21, k[55]); 00313 II(a, b, c, d, x[8], 6, k[56]); 00314 II(d, a, b, c, x[15], 10, k[57]); 00315 II(c, d, a, b, x[6], 15, k[58]); 00316 II(b, c, d, a, x[13], 21, k[59]); 00317 II(a, b, c, d, x[4], 6, k[60]); 00318 II(d, a, b, c, x[11], 10, k[61]); 00319 II(c, d, a, b, x[2], 15, k[62]); 00320 II(b, c, d, a, x[9], 21, k[63]); 00321 00322 //Update the hash value 00323 context->h[0] += a; 00324 context->h[1] += b; 00325 context->h[2] += c; 00326 context->h[3] += d; 00327 } 00328 00329 #endif 00330
Generated on Tue Jul 12 2022 17:10:14 by
