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.
pwdbased.c
00001 /* pwdbased.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 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #ifndef NO_PWDBASED 00030 00031 #ifdef WOLFSSL_PIC32MZ_HASH 00032 #ifndef NO_MD5 00033 #define wc_InitMd5 wc_InitMd5_sw 00034 #define wc_Md5Update wc_Md5Update_sw 00035 #define wc_Md5Final wc_Md5Final_sw 00036 #endif /* NO_MD5 */ 00037 00038 #define wc_InitSha wc_InitSha_sw 00039 #define wc_ShaUpdate wc_ShaUpdate_sw 00040 #define wc_ShaFinal wc_ShaFinal_sw 00041 00042 #define wc_InitSha256 wc_InitSha256_sw 00043 #define wc_Sha256Update wc_Sha256Update_sw 00044 #define wc_Sha256Final wc_Sha256Final_sw 00045 #endif 00046 00047 #include <wolfssl/wolfcrypt/pwdbased.h> 00048 #include <wolfssl/wolfcrypt/hmac.h> 00049 #include <wolfssl/wolfcrypt/integer.h> 00050 #include <wolfssl/wolfcrypt/error-crypt.h> 00051 #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) 00052 #include <wolfssl/wolfcrypt/sha512.h> 00053 #endif 00054 00055 #ifdef NO_INLINE 00056 #include <wolfssl/wolfcrypt/misc.h> 00057 #else 00058 #include <wolfcrypt/src/misc.c> 00059 #endif 00060 00061 #ifndef WOLFSSL_HAVE_MIN 00062 #define WOLFSSL_HAVE_MIN 00063 00064 static INLINE word32 min(word32 a, word32 b) 00065 { 00066 return a > b ? b : a; 00067 } 00068 00069 #endif /* WOLFSSL_HAVE_MIN */ 00070 00071 00072 #ifndef NO_SHA 00073 /* PBKDF1 needs at least SHA available */ 00074 int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, 00075 int sLen, int iterations, int kLen, int hashType) 00076 { 00077 Sha sha; 00078 #ifndef NO_MD5 00079 Md5 md5; 00080 #endif 00081 int hLen = (int)SHA_DIGEST_SIZE; 00082 int i, ret = 0; 00083 byte buffer[SHA_DIGEST_SIZE]; /* max size */ 00084 00085 if (hashType != MD5 && hashType != SHA) 00086 return BAD_FUNC_ARG; 00087 00088 #ifndef NO_MD5 00089 if (hashType == MD5) 00090 hLen = (int)MD5_DIGEST_SIZE; 00091 #endif 00092 00093 if (kLen > hLen) 00094 return BAD_FUNC_ARG; 00095 00096 if (iterations < 1) 00097 return BAD_FUNC_ARG; 00098 00099 switch (hashType) { 00100 #ifndef NO_MD5 00101 case MD5: 00102 wc_InitMd5(&md5); 00103 wc_Md5Update(&md5, passwd, pLen); 00104 wc_Md5Update(&md5, salt, sLen); 00105 wc_Md5Final(&md5, buffer); 00106 break; 00107 #endif /* NO_MD5 */ 00108 case SHA: 00109 default: 00110 ret = wc_InitSha(&sha); 00111 if (ret != 0) 00112 return ret; 00113 wc_ShaUpdate(&sha, passwd, pLen); 00114 wc_ShaUpdate(&sha, salt, sLen); 00115 wc_ShaFinal(&sha, buffer); 00116 break; 00117 } 00118 00119 for (i = 1; i < iterations; i++) { 00120 if (hashType == SHA) { 00121 wc_ShaUpdate(&sha, buffer, hLen); 00122 wc_ShaFinal(&sha, buffer); 00123 } 00124 #ifndef NO_MD5 00125 else { 00126 wc_Md5Update(&md5, buffer, hLen); 00127 wc_Md5Final(&md5, buffer); 00128 } 00129 #endif 00130 } 00131 XMEMCPY(output, buffer, kLen); 00132 00133 return 0; 00134 } 00135 #endif /* NO_SHA */ 00136 00137 00138 int GetDigestSize(int hashType) 00139 { 00140 int hLen; 00141 00142 switch (hashType) { 00143 #ifndef NO_MD5 00144 case MD5: 00145 hLen = MD5_DIGEST_SIZE; 00146 break; 00147 #endif 00148 #ifndef NO_SHA 00149 case SHA: 00150 hLen = SHA_DIGEST_SIZE; 00151 break; 00152 #endif 00153 #ifndef NO_SHA256 00154 case SHA256: 00155 hLen = SHA256_DIGEST_SIZE; 00156 break; 00157 #endif 00158 #ifdef WOLFSSL_SHA512 00159 case SHA512: 00160 hLen = SHA512_DIGEST_SIZE; 00161 break; 00162 #endif 00163 default: 00164 return BAD_FUNC_ARG; 00165 } 00166 00167 return hLen; 00168 } 00169 00170 00171 int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, 00172 int sLen, int iterations, int kLen, int hashType) 00173 { 00174 word32 i = 1; 00175 int hLen; 00176 int j, ret; 00177 Hmac hmac; 00178 #ifdef WOLFSSL_SMALL_STACK 00179 byte* buffer; 00180 #else 00181 byte buffer[MAX_DIGEST_SIZE]; 00182 #endif 00183 00184 hLen = GetDigestSize(hashType); 00185 if (hLen < 0) 00186 return BAD_FUNC_ARG; 00187 00188 #ifdef WOLFSSL_SMALL_STACK 00189 buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00190 if (buffer == NULL) 00191 return MEMORY_E; 00192 #endif 00193 00194 ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); 00195 00196 if (ret == 0) { 00197 while (kLen) { 00198 int currentLen; 00199 00200 ret = wc_HmacUpdate(&hmac, salt, sLen); 00201 if (ret != 0) 00202 break; 00203 00204 /* encode i */ 00205 for (j = 0; j < 4; j++) { 00206 byte b = (byte)(i >> ((3-j) * 8)); 00207 00208 ret = wc_HmacUpdate(&hmac, &b, 1); 00209 if (ret != 0) 00210 break; 00211 } 00212 00213 /* check ret from inside for loop */ 00214 if (ret != 0) 00215 break; 00216 00217 ret = wc_HmacFinal(&hmac, buffer); 00218 if (ret != 0) 00219 break; 00220 00221 currentLen = min(kLen, hLen); 00222 XMEMCPY(output, buffer, currentLen); 00223 00224 for (j = 1; j < iterations; j++) { 00225 ret = wc_HmacUpdate(&hmac, buffer, hLen); 00226 if (ret != 0) 00227 break; 00228 ret = wc_HmacFinal(&hmac, buffer); 00229 if (ret != 0) 00230 break; 00231 xorbuf(output, buffer, currentLen); 00232 } 00233 00234 /* check ret from inside for loop */ 00235 if (ret != 0) 00236 break; 00237 00238 output += currentLen; 00239 kLen -= currentLen; 00240 i++; 00241 } 00242 } 00243 00244 #ifdef WOLFSSL_SMALL_STACK 00245 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00246 #endif 00247 00248 return ret; 00249 } 00250 00251 #ifdef WOLFSSL_SHA512 00252 #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE 00253 #elif !defined(NO_SHA256) 00254 #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE 00255 #else 00256 #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE 00257 #endif 00258 00259 /* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */ 00260 int GetPKCS12HashSizes(int hashType, word32* v, word32* u) 00261 { 00262 if (!v || !u) 00263 return BAD_FUNC_ARG; 00264 00265 switch (hashType) { 00266 #ifndef NO_MD5 00267 case MD5: 00268 *v = MD5_BLOCK_SIZE; 00269 *u = MD5_DIGEST_SIZE; 00270 break; 00271 #endif 00272 #ifndef NO_SHA 00273 case SHA: 00274 *v = SHA_BLOCK_SIZE; 00275 *u = SHA_DIGEST_SIZE; 00276 break; 00277 #endif 00278 #ifndef NO_SHA256 00279 case SHA256: 00280 *v = SHA256_BLOCK_SIZE; 00281 *u = SHA256_DIGEST_SIZE; 00282 break; 00283 #endif 00284 #ifdef WOLFSSL_SHA512 00285 case SHA512: 00286 *v = SHA512_BLOCK_SIZE; 00287 *u = SHA512_DIGEST_SIZE; 00288 break; 00289 #endif 00290 default: 00291 return BAD_FUNC_ARG; 00292 } 00293 00294 return 0; 00295 } 00296 00297 /* helper for PKCS12_PBKDF(), does hash operation */ 00298 int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, 00299 byte* Ai, word32 u, int iterations) 00300 { 00301 int i; 00302 int ret = 0; 00303 00304 if (buffer == NULL || Ai == NULL) 00305 return BAD_FUNC_ARG; 00306 00307 switch (hashType) { 00308 #ifndef NO_MD5 00309 case MD5: 00310 { 00311 Md5 md5; 00312 wc_InitMd5(&md5); 00313 wc_Md5Update(&md5, buffer, totalLen); 00314 wc_Md5Final(&md5, Ai); 00315 00316 for (i = 1; i < iterations; i++) { 00317 wc_Md5Update(&md5, Ai, u); 00318 wc_Md5Final(&md5, Ai); 00319 } 00320 } 00321 break; 00322 #endif /* NO_MD5 */ 00323 #ifndef NO_SHA 00324 case SHA: 00325 { 00326 Sha sha; 00327 ret = wc_InitSha(&sha); 00328 if (ret != 0) 00329 break; 00330 wc_ShaUpdate(&sha, buffer, totalLen); 00331 wc_ShaFinal(&sha, Ai); 00332 00333 for (i = 1; i < iterations; i++) { 00334 wc_ShaUpdate(&sha, Ai, u); 00335 wc_ShaFinal(&sha, Ai); 00336 } 00337 } 00338 break; 00339 #endif /* NO_SHA */ 00340 #ifndef NO_SHA256 00341 case SHA256: 00342 { 00343 Sha256 sha256; 00344 ret = wc_InitSha256(&sha256); 00345 if (ret != 0) 00346 break; 00347 00348 ret = wc_Sha256Update(&sha256, buffer, totalLen); 00349 if (ret != 0) 00350 break; 00351 00352 ret = wc_Sha256Final(&sha256, Ai); 00353 if (ret != 0) 00354 break; 00355 00356 for (i = 1; i < iterations; i++) { 00357 ret = wc_Sha256Update(&sha256, Ai, u); 00358 if (ret != 0) 00359 break; 00360 00361 ret = wc_Sha256Final(&sha256, Ai); 00362 if (ret != 0) 00363 break; 00364 } 00365 } 00366 break; 00367 #endif /* NO_SHA256 */ 00368 #ifdef WOLFSSL_SHA512 00369 case SHA512: 00370 { 00371 Sha512 sha512; 00372 ret = wc_InitSha512(&sha512); 00373 if (ret != 0) 00374 break; 00375 00376 ret = wc_Sha512Update(&sha512, buffer, totalLen); 00377 if (ret != 0) 00378 break; 00379 00380 ret = wc_Sha512Final(&sha512, Ai); 00381 if (ret != 0) 00382 break; 00383 00384 for (i = 1; i < iterations; i++) { 00385 ret = wc_Sha512Update(&sha512, Ai, u); 00386 if (ret != 0) 00387 break; 00388 00389 ret = wc_Sha512Final(&sha512, Ai); 00390 if (ret != 0) 00391 break; 00392 } 00393 } 00394 break; 00395 #endif /* WOLFSSL_SHA512 */ 00396 00397 default: 00398 ret = BAD_FUNC_ARG; 00399 break; 00400 } 00401 00402 return ret; 00403 } 00404 00405 int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, 00406 int saltLen, int iterations, int kLen, int hashType, int id) 00407 { 00408 /* all in bytes instead of bits */ 00409 word32 u, v, dLen, pLen, iLen, sLen, totalLen; 00410 int dynamic = 0; 00411 int ret = 0; 00412 int i; 00413 byte *D, *S, *P, *I; 00414 #ifdef WOLFSSL_SMALL_STACK 00415 byte staticBuffer[1]; /* force dynamic usage */ 00416 #else 00417 byte staticBuffer[1024]; 00418 #endif 00419 byte* buffer = staticBuffer; 00420 00421 #ifdef WOLFSSL_SMALL_STACK 00422 byte* Ai; 00423 byte* B; 00424 #else 00425 byte Ai[PBKDF_DIGEST_SIZE]; 00426 byte B[PBKDF_DIGEST_SIZE]; 00427 #endif 00428 00429 if (!iterations) 00430 iterations = 1; 00431 00432 ret = GetPKCS12HashSizes(hashType, &v, &u); 00433 if (ret < 0) 00434 return BAD_FUNC_ARG; 00435 00436 #ifdef WOLFSSL_SMALL_STACK 00437 Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00438 if (Ai == NULL) 00439 return MEMORY_E; 00440 00441 B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00442 if (B == NULL) { 00443 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00444 return MEMORY_E; 00445 } 00446 #endif 00447 00448 XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE); 00449 XMEMSET(B, 0, PBKDF_DIGEST_SIZE); 00450 00451 dLen = v; 00452 sLen = v * ((saltLen + v - 1) / v); 00453 if (passLen) 00454 pLen = v * ((passLen + v - 1) / v); 00455 else 00456 pLen = 0; 00457 iLen = sLen + pLen; 00458 00459 totalLen = dLen + sLen + pLen; 00460 00461 if (totalLen > sizeof(staticBuffer)) { 00462 buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY); 00463 if (buffer == NULL) { 00464 #ifdef WOLFSSL_SMALL_STACK 00465 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00466 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00467 #endif 00468 return MEMORY_E; 00469 } 00470 dynamic = 1; 00471 } 00472 00473 D = buffer; 00474 S = D + dLen; 00475 P = S + sLen; 00476 I = S; 00477 00478 XMEMSET(D, id, dLen); 00479 00480 for (i = 0; i < (int)sLen; i++) 00481 S[i] = salt[i % saltLen]; 00482 for (i = 0; i < (int)pLen; i++) 00483 P[i] = passwd[i % passLen]; 00484 00485 while (kLen > 0) { 00486 word32 currentLen; 00487 mp_int B1; 00488 00489 ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations); 00490 if (ret < 0) 00491 break; 00492 00493 for (i = 0; i < (int)v; i++) 00494 B[i] = Ai[i % u]; 00495 00496 if (mp_init(&B1) != MP_OKAY) 00497 ret = MP_INIT_E; 00498 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY) 00499 ret = MP_READ_E; 00500 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY) 00501 ret = MP_ADD_E; 00502 00503 if (ret != 0) { 00504 mp_clear(&B1); 00505 break; 00506 } 00507 00508 for (i = 0; i < (int)iLen; i += v) { 00509 int outSz; 00510 mp_int i1; 00511 mp_int res; 00512 00513 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) { 00514 ret = MP_INIT_E; 00515 break; 00516 } 00517 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY) 00518 ret = MP_READ_E; 00519 else if (mp_add(&i1, &B1, &res) != MP_OKAY) 00520 ret = MP_ADD_E; 00521 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0) 00522 ret = MP_TO_E; 00523 else { 00524 if (outSz > (int)v) { 00525 /* take off MSB */ 00526 byte tmp[129]; 00527 ret = mp_to_unsigned_bin(&res, tmp); 00528 XMEMCPY(I + i, tmp + 1, v); 00529 } 00530 else if (outSz < (int)v) { 00531 XMEMSET(I + i, 0, v - outSz); 00532 ret = mp_to_unsigned_bin(&res, I + i + v - outSz); 00533 } 00534 else 00535 ret = mp_to_unsigned_bin(&res, I + i); 00536 } 00537 00538 mp_clear(&i1); 00539 mp_clear(&res); 00540 if (ret < 0) break; 00541 } 00542 00543 currentLen = min(kLen, (int)u); 00544 XMEMCPY(output, Ai, currentLen); 00545 output += currentLen; 00546 kLen -= currentLen; 00547 mp_clear(&B1); 00548 } 00549 00550 if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY); 00551 00552 #ifdef WOLFSSL_SMALL_STACK 00553 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00554 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00555 #endif 00556 00557 return ret; 00558 } 00559 00560 #undef PBKDF_DIGEST_SIZE 00561 00562 #endif /* NO_PWDBASED */ 00563 00564
Generated on Tue Jul 12 2022 15:55:20 by
1.7.2