Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wolfSSL by
md5.c
00001 /* md5.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include <config.h> 00026 #endif 00027 00028 #include <wolfssl/wolfcrypt/settings.h> 00029 00030 #if !defined(NO_MD5) 00031 00032 #if defined(WOLFSSL_TI_HASH) 00033 /* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */ 00034 00035 #else 00036 00037 #include <wolfssl/wolfcrypt/md5.h> 00038 #include <wolfssl/wolfcrypt/error-crypt.h> 00039 00040 #ifdef NO_INLINE 00041 #include <wolfssl/wolfcrypt/misc.h> 00042 #else 00043 #define WOLFSSL_MISC_INCLUDED 00044 #include <wolfcrypt/src/misc.c> 00045 #endif 00046 00047 00048 /* Hardware Acceleration */ 00049 #if defined(STM32F2_HASH) || defined(STM32F4_HASH) 00050 /* 00051 * STM32F2/F4 hardware MD5 support through the standard peripheral 00052 * library. (See note in README). 00053 */ 00054 00055 #define HAVE_MD5_CUST_API 00056 00057 int wc_InitMd5_ex(Md5* md5, void* heap, int devId) 00058 { 00059 (void)heap; 00060 (void)devId; 00061 00062 /* STM32 struct notes: 00063 * md5->buffer = first 4 bytes used to hold partial block if needed 00064 * md5->buffLen = num bytes currently stored in md5->buffer 00065 * md5->loLen = num bytes that have been written to STM32 FIFO 00066 */ 00067 XMEMSET(md5->buffer, 0, MD5_REG_SIZE); 00068 00069 md5->buffLen = 0; 00070 md5->loLen = 0; 00071 00072 /* initialize HASH peripheral */ 00073 HASH_DeInit(); 00074 00075 /* configure algo used, algo mode, datatype */ 00076 HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); 00077 HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH 00078 | HASH_DataType_8b); 00079 00080 /* reset HASH processor */ 00081 HASH->CR |= HASH_CR_INIT; 00082 00083 return 0; 00084 } 00085 00086 int wc_Md5Update(Md5* md5, const byte* data, word32 len) 00087 { 00088 word32 i = 0; 00089 word32 fill = 0; 00090 word32 diff = 0; 00091 00092 /* if saved partial block is available */ 00093 if (md5->buffLen > 0) { 00094 fill = 4 - md5->buffLen; 00095 00096 /* if enough data to fill, fill and push to FIFO */ 00097 if (fill <= len) { 00098 XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); 00099 HASH_DataIn(*(uint32_t*)md5->buffer); 00100 00101 data += fill; 00102 len -= fill; 00103 md5->loLen += 4; 00104 md5->buffLen = 0; 00105 } else { 00106 /* append partial to existing stored block */ 00107 XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); 00108 md5->buffLen += len; 00109 return 0; 00110 } 00111 } 00112 00113 /* write input block in the IN FIFO */ 00114 for (i = 0; i < len; i += 4) 00115 { 00116 diff = len - i; 00117 if (diff < 4) { 00118 /* store incomplete last block, not yet in FIFO */ 00119 XMEMSET(md5->buffer, 0, MD5_REG_SIZE); 00120 XMEMCPY((byte*)md5->buffer, data, diff); 00121 md5->buffLen = diff; 00122 } else { 00123 HASH_DataIn(*(uint32_t*)data); 00124 data+=4; 00125 } 00126 } 00127 00128 /* keep track of total data length thus far */ 00129 md5->loLen += (len - md5->buffLen); 00130 00131 return 0; 00132 } 00133 00134 int wc_Md5Final(Md5* md5, byte* hash) 00135 { 00136 __IO uint16_t nbvalidbitsdata = 0; 00137 00138 /* finish reading any trailing bytes into FIFO */ 00139 if (md5->buffLen > 0) { 00140 HASH_DataIn(*(uint32_t*)md5->buffer); 00141 md5->loLen += md5->buffLen; 00142 } 00143 00144 /* calculate number of valid bits in last word of input data */ 00145 nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); 00146 00147 /* configure number of valid bits in last word of the data */ 00148 HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); 00149 00150 /* start HASH processor */ 00151 HASH_StartDigest(); 00152 00153 /* wait until Busy flag == RESET */ 00154 while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} 00155 00156 /* read message digest */ 00157 md5->digest[0] = HASH->HR[0]; 00158 md5->digest[1] = HASH->HR[1]; 00159 md5->digest[2] = HASH->HR[2]; 00160 md5->digest[3] = HASH->HR[3]; 00161 00162 ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); 00163 00164 XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); 00165 00166 return wc_InitMd5(md5); /* reset state */ 00167 } 00168 00169 #elif defined(FREESCALE_MMCAU_SHA) 00170 #include "cau_api.h" 00171 #define XTRANSFORM(S,B) Transform((S), (B)) 00172 00173 static int Transform(Md5* md5, byte* data) 00174 { 00175 int ret = wolfSSL_CryptHwMutexLock(); 00176 if(ret == 0) { 00177 MMCAU_MD5_HashN(data, 1, (uint32_t*)md5->digest); 00178 wolfSSL_CryptHwMutexUnLock(); 00179 } 00180 return ret; 00181 } 00182 00183 #elif defined(WOLFSSL_PIC32MZ_HASH) 00184 #define wc_InitMd5 wc_InitMd5_sw 00185 #define wc_Md5Update wc_Md5Update_sw 00186 #define wc_Md5Final wc_Md5Final_sw 00187 00188 #define NEED_SOFT_MD5 00189 00190 #else 00191 #define NEED_SOFT_MD5 00192 00193 #endif /* End Hardware Acceleration */ 00194 00195 00196 #ifdef NEED_SOFT_MD5 00197 00198 #define XTRANSFORM(S,B) Transform((S)) 00199 00200 #define F1(x, y, z) (z ^ (x & (y ^ z))) 00201 #define F2(x, y, z) F1(z, x, y) 00202 #define F3(x, y, z) (x ^ y ^ z) 00203 #define F4(x, y, z) (y ^ (x | ~z)) 00204 00205 #define MD5STEP(f, w, x, y, z, data, s) \ 00206 w = rotlFixed(w + f(x, y, z) + data, s) + x 00207 00208 static int Transform(Md5* md5) 00209 { 00210 /* Copy context->state[] to working vars */ 00211 word32 a = md5->digest[0]; 00212 word32 b = md5->digest[1]; 00213 word32 c = md5->digest[2]; 00214 word32 d = md5->digest[3]; 00215 00216 MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); 00217 MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); 00218 MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); 00219 MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); 00220 MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); 00221 MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); 00222 MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); 00223 MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); 00224 MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); 00225 MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); 00226 MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); 00227 MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); 00228 MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); 00229 MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); 00230 MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); 00231 MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); 00232 00233 MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); 00234 MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); 00235 MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); 00236 MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); 00237 MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); 00238 MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); 00239 MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); 00240 MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); 00241 MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); 00242 MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); 00243 MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); 00244 MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); 00245 MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); 00246 MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); 00247 MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); 00248 MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); 00249 00250 MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); 00251 MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); 00252 MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); 00253 MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); 00254 MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); 00255 MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); 00256 MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); 00257 MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); 00258 MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); 00259 MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); 00260 MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); 00261 MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); 00262 MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); 00263 MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); 00264 MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); 00265 MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); 00266 00267 MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); 00268 MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); 00269 MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); 00270 MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); 00271 MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); 00272 MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); 00273 MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); 00274 MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); 00275 MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); 00276 MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); 00277 MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); 00278 MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); 00279 MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); 00280 MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); 00281 MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); 00282 MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); 00283 00284 /* Add the working vars back into digest state[] */ 00285 md5->digest[0] += a; 00286 md5->digest[1] += b; 00287 md5->digest[2] += c; 00288 md5->digest[3] += d; 00289 00290 return 0; 00291 } 00292 #endif /* NEED_SOFT_MD5 */ 00293 00294 00295 #ifndef HAVE_MD5_CUST_API 00296 static INLINE void AddMd5Length(Md5* md5, word32 len) 00297 { 00298 word32 tmp = md5->loLen; 00299 if ((md5->loLen += len) < tmp) { 00300 md5->hiLen++; /* carry low to high */ 00301 } 00302 } 00303 00304 static int _InitMd5(Md5* md5) 00305 { 00306 int ret = 0; 00307 00308 md5->digest[0] = 0x67452301L; 00309 md5->digest[1] = 0xefcdab89L; 00310 md5->digest[2] = 0x98badcfeL; 00311 md5->digest[3] = 0x10325476L; 00312 00313 md5->buffLen = 0; 00314 md5->loLen = 0; 00315 md5->hiLen = 0; 00316 00317 return ret; 00318 } 00319 00320 int wc_InitMd5_ex(Md5* md5, void* heap, int devId) 00321 { 00322 int ret = 0; 00323 00324 if (md5 == NULL) 00325 return BAD_FUNC_ARG; 00326 00327 md5->heap = heap; 00328 00329 ret = _InitMd5(md5); 00330 if (ret != 0) 00331 return ret; 00332 00333 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) 00334 ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5, 00335 md5->heap, devId); 00336 #else 00337 (void)devId; 00338 #endif 00339 return ret; 00340 } 00341 00342 int wc_Md5Update(Md5* md5, const byte* data, word32 len) 00343 { 00344 int ret = 0; 00345 byte* local; 00346 00347 if (md5 == NULL || (data == NULL && len > 0)) { 00348 return BAD_FUNC_ARG; 00349 } 00350 00351 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) 00352 if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { 00353 #if defined(HAVE_INTEL_QA) 00354 return IntelQaSymMd5(&md5->asyncDev, NULL, data, len); 00355 #endif 00356 } 00357 #endif /* WOLFSSL_ASYNC_CRYPT */ 00358 00359 /* do block size increments */ 00360 local = (byte*)md5->buffer; 00361 00362 /* check that internal buffLen is valid */ 00363 if (md5->buffLen >= MD5_BLOCK_SIZE) 00364 return BUFFER_E; 00365 00366 while (len) { 00367 word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); 00368 XMEMCPY(&local[md5->buffLen], data, add); 00369 00370 md5->buffLen += add; 00371 data += add; 00372 len -= add; 00373 00374 if (md5->buffLen == MD5_BLOCK_SIZE) { 00375 #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) 00376 ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); 00377 #endif 00378 XTRANSFORM(md5, local); 00379 AddMd5Length(md5, MD5_BLOCK_SIZE); 00380 md5->buffLen = 0; 00381 } 00382 } 00383 return ret; 00384 } 00385 00386 int wc_Md5Final(Md5* md5, byte* hash) 00387 { 00388 byte* local; 00389 00390 if (md5 == NULL || hash == NULL) { 00391 return BAD_FUNC_ARG; 00392 } 00393 00394 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) 00395 if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { 00396 #if defined(HAVE_INTEL_QA) 00397 return IntelQaSymMd5(&md5->asyncDev, hash, NULL, MD5_DIGEST_SIZE); 00398 #endif 00399 } 00400 #endif /* WOLFSSL_ASYNC_CRYPT */ 00401 00402 local = (byte*)md5->buffer; 00403 00404 AddMd5Length(md5, md5->buffLen); /* before adding pads */ 00405 local[md5->buffLen++] = 0x80; /* add 1 */ 00406 00407 /* pad with zeros */ 00408 if (md5->buffLen > MD5_PAD_SIZE) { 00409 XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); 00410 md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; 00411 00412 #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) 00413 ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); 00414 #endif 00415 XTRANSFORM(md5, local); 00416 md5->buffLen = 0; 00417 } 00418 XMEMSET(&local[md5->buffLen], 0, MD5_PAD_SIZE - md5->buffLen); 00419 00420 /* put lengths in bits */ 00421 md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + 00422 (md5->hiLen << 3); 00423 md5->loLen = md5->loLen << 3; 00424 00425 /* store lengths */ 00426 #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) 00427 ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); 00428 #endif 00429 /* ! length ordering dependent on digest endian type ! */ 00430 XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); 00431 XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); 00432 00433 XTRANSFORM(md5, local); 00434 #ifdef BIG_ENDIAN_ORDER 00435 ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); 00436 #endif 00437 XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); 00438 00439 return _InitMd5(md5); /* reset state */ 00440 } 00441 #endif /* !HAVE_MD5_CUST_API */ 00442 00443 00444 int wc_InitMd5(Md5* md5) 00445 { 00446 return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); 00447 } 00448 00449 void wc_Md5Free(Md5* md5) 00450 { 00451 if (md5 == NULL) 00452 return; 00453 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) 00454 wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5); 00455 #endif /* WOLFSSL_ASYNC_CRYPT */ 00456 } 00457 00458 int wc_Md5GetHash(Md5* md5, byte* hash) 00459 { 00460 int ret; 00461 Md5 tmpMd5; 00462 00463 if (md5 == NULL || hash == NULL) 00464 return BAD_FUNC_ARG; 00465 00466 ret = wc_Md5Copy(md5, &tmpMd5); 00467 if (ret == 0) { 00468 ret = wc_Md5Final(&tmpMd5, hash); 00469 } 00470 00471 return ret; 00472 } 00473 00474 int wc_Md5Copy(Md5* src, Md5* dst) 00475 { 00476 int ret = 0; 00477 00478 if (src == NULL || dst == NULL) 00479 return BAD_FUNC_ARG; 00480 00481 XMEMCPY(dst, src, sizeof(Md5)); 00482 00483 #ifdef WOLFSSL_ASYNC_CRYPT 00484 ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); 00485 #endif 00486 00487 return ret; 00488 } 00489 00490 #endif /* WOLFSSL_TI_HASH */ 00491 #endif /* NO_MD5 */ 00492
Generated on Tue Jul 12 2022 23:30:58 by
1.7.2
