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
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 #define WOLFSSL_MISC_INCLUDED 00059 #include <wolfcrypt/src/misc.c> 00060 #endif 00061 00062 00063 #ifndef NO_SHA 00064 /* PBKDF1 needs at least SHA available */ 00065 int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, 00066 int sLen, int iterations, int kLen, int hashType) 00067 { 00068 Sha sha; 00069 #ifndef NO_MD5 00070 Md5 md5; 00071 #endif 00072 int hLen = (int)SHA_DIGEST_SIZE; 00073 int i, ret = 0; 00074 byte buffer[SHA_DIGEST_SIZE]; /* max size */ 00075 00076 if (hashType != MD5 && hashType != SHA) 00077 return BAD_FUNC_ARG; 00078 00079 #ifndef NO_MD5 00080 if (hashType == MD5) 00081 hLen = (int)MD5_DIGEST_SIZE; 00082 #endif 00083 00084 if ((kLen > hLen) || (kLen < 0)) 00085 return BAD_FUNC_ARG; 00086 00087 if (iterations < 1) 00088 return BAD_FUNC_ARG; 00089 00090 switch (hashType) { 00091 #ifndef NO_MD5 00092 case MD5: 00093 wc_InitMd5(&md5); 00094 wc_Md5Update(&md5, passwd, pLen); 00095 wc_Md5Update(&md5, salt, sLen); 00096 wc_Md5Final(&md5, buffer); 00097 break; 00098 #endif /* NO_MD5 */ 00099 case SHA: 00100 default: 00101 ret = wc_InitSha(&sha); 00102 if (ret != 0) 00103 return ret; 00104 wc_ShaUpdate(&sha, passwd, pLen); 00105 wc_ShaUpdate(&sha, salt, sLen); 00106 wc_ShaFinal(&sha, buffer); 00107 break; 00108 } 00109 00110 for (i = 1; i < iterations; i++) { 00111 if (hashType == SHA) { 00112 wc_ShaUpdate(&sha, buffer, hLen); 00113 wc_ShaFinal(&sha, buffer); 00114 } 00115 #ifndef NO_MD5 00116 else { 00117 wc_Md5Update(&md5, buffer, hLen); 00118 wc_Md5Final(&md5, buffer); 00119 } 00120 #endif 00121 } 00122 XMEMCPY(output, buffer, kLen); 00123 00124 return 0; 00125 } 00126 #endif /* NO_SHA */ 00127 00128 00129 int GetDigestSize(int hashType) 00130 { 00131 int hLen; 00132 00133 switch (hashType) { 00134 #ifndef NO_MD5 00135 case MD5: 00136 hLen = MD5_DIGEST_SIZE; 00137 break; 00138 #endif 00139 #ifndef NO_SHA 00140 case SHA: 00141 hLen = SHA_DIGEST_SIZE; 00142 break; 00143 #endif 00144 #ifndef NO_SHA256 00145 case SHA256: 00146 hLen = SHA256_DIGEST_SIZE; 00147 break; 00148 #endif 00149 #ifdef WOLFSSL_SHA512 00150 case SHA512: 00151 hLen = SHA512_DIGEST_SIZE; 00152 break; 00153 #endif 00154 default: 00155 return BAD_FUNC_ARG; 00156 } 00157 00158 return hLen; 00159 } 00160 00161 00162 int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, 00163 int sLen, int iterations, int kLen, int hashType) 00164 { 00165 word32 i = 1; 00166 int hLen; 00167 int j, ret; 00168 Hmac hmac; 00169 #ifdef WOLFSSL_SMALL_STACK 00170 byte* buffer; 00171 #else 00172 byte buffer[MAX_DIGEST_SIZE]; 00173 #endif 00174 00175 hLen = GetDigestSize(hashType); 00176 if (hLen < 0) 00177 return BAD_FUNC_ARG; 00178 00179 #ifdef WOLFSSL_SMALL_STACK 00180 buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00181 if (buffer == NULL) 00182 return MEMORY_E; 00183 #endif 00184 00185 ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); 00186 if (ret == 0) { 00187 ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); 00188 00189 while (ret == 0 && kLen) { 00190 int currentLen; 00191 00192 ret = wc_HmacUpdate(&hmac, salt, sLen); 00193 if (ret != 0) 00194 break; 00195 00196 /* encode i */ 00197 for (j = 0; j < 4; j++) { 00198 byte b = (byte)(i >> ((3-j) * 8)); 00199 00200 ret = wc_HmacUpdate(&hmac, &b, 1); 00201 if (ret != 0) 00202 break; 00203 } 00204 00205 /* check ret from inside for loop */ 00206 if (ret != 0) 00207 break; 00208 00209 ret = wc_HmacFinal(&hmac, buffer); 00210 if (ret != 0) 00211 break; 00212 00213 currentLen = min(kLen, hLen); 00214 XMEMCPY(output, buffer, currentLen); 00215 00216 for (j = 1; j < iterations; j++) { 00217 ret = wc_HmacUpdate(&hmac, buffer, hLen); 00218 if (ret != 0) 00219 break; 00220 ret = wc_HmacFinal(&hmac, buffer); 00221 if (ret != 0) 00222 break; 00223 xorbuf(output, buffer, currentLen); 00224 } 00225 00226 /* check ret from inside for loop */ 00227 if (ret != 0) 00228 break; 00229 00230 output += currentLen; 00231 kLen -= currentLen; 00232 i++; 00233 } 00234 wc_HmacFree(&hmac); 00235 } 00236 00237 #ifdef WOLFSSL_SMALL_STACK 00238 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00239 #endif 00240 00241 return ret; 00242 } 00243 00244 #ifdef WOLFSSL_SHA512 00245 #define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE 00246 #elif !defined(NO_SHA256) 00247 #define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE 00248 #else 00249 #define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE 00250 #endif 00251 00252 /* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */ 00253 int GetPKCS12HashSizes(int hashType, word32* v, word32* u) 00254 { 00255 if (!v || !u) 00256 return BAD_FUNC_ARG; 00257 00258 switch (hashType) { 00259 #ifndef NO_MD5 00260 case MD5: 00261 *v = MD5_BLOCK_SIZE; 00262 *u = MD5_DIGEST_SIZE; 00263 break; 00264 #endif 00265 #ifndef NO_SHA 00266 case SHA: 00267 *v = SHA_BLOCK_SIZE; 00268 *u = SHA_DIGEST_SIZE; 00269 break; 00270 #endif 00271 #ifndef NO_SHA256 00272 case SHA256: 00273 *v = SHA256_BLOCK_SIZE; 00274 *u = SHA256_DIGEST_SIZE; 00275 break; 00276 #endif 00277 #ifdef WOLFSSL_SHA512 00278 case SHA512: 00279 *v = SHA512_BLOCK_SIZE; 00280 *u = SHA512_DIGEST_SIZE; 00281 break; 00282 #endif 00283 default: 00284 return BAD_FUNC_ARG; 00285 } 00286 00287 return 0; 00288 } 00289 00290 /* helper for PKCS12_PBKDF(), does hash operation */ 00291 int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, 00292 byte* Ai, word32 u, int iterations) 00293 { 00294 int i; 00295 int ret = 0; 00296 00297 if (buffer == NULL || Ai == NULL) 00298 return BAD_FUNC_ARG; 00299 00300 switch (hashType) { 00301 #ifndef NO_MD5 00302 case MD5: 00303 { 00304 Md5 md5; 00305 wc_InitMd5(&md5); 00306 wc_Md5Update(&md5, buffer, totalLen); 00307 wc_Md5Final(&md5, Ai); 00308 00309 for (i = 1; i < iterations; i++) { 00310 wc_Md5Update(&md5, Ai, u); 00311 wc_Md5Final(&md5, Ai); 00312 } 00313 } 00314 break; 00315 #endif /* NO_MD5 */ 00316 #ifndef NO_SHA 00317 case SHA: 00318 { 00319 Sha sha; 00320 ret = wc_InitSha(&sha); 00321 if (ret != 0) 00322 break; 00323 wc_ShaUpdate(&sha, buffer, totalLen); 00324 wc_ShaFinal(&sha, Ai); 00325 00326 for (i = 1; i < iterations; i++) { 00327 wc_ShaUpdate(&sha, Ai, u); 00328 wc_ShaFinal(&sha, Ai); 00329 } 00330 } 00331 break; 00332 #endif /* NO_SHA */ 00333 #ifndef NO_SHA256 00334 case SHA256: 00335 { 00336 Sha256 sha256; 00337 ret = wc_InitSha256(&sha256); 00338 if (ret != 0) 00339 break; 00340 00341 ret = wc_Sha256Update(&sha256, buffer, totalLen); 00342 if (ret != 0) 00343 break; 00344 00345 ret = wc_Sha256Final(&sha256, Ai); 00346 if (ret != 0) 00347 break; 00348 00349 for (i = 1; i < iterations; i++) { 00350 ret = wc_Sha256Update(&sha256, Ai, u); 00351 if (ret != 0) 00352 break; 00353 00354 ret = wc_Sha256Final(&sha256, Ai); 00355 if (ret != 0) 00356 break; 00357 } 00358 } 00359 break; 00360 #endif /* NO_SHA256 */ 00361 #ifdef WOLFSSL_SHA512 00362 case SHA512: 00363 { 00364 Sha512 sha512; 00365 ret = wc_InitSha512(&sha512); 00366 if (ret != 0) 00367 break; 00368 00369 ret = wc_Sha512Update(&sha512, buffer, totalLen); 00370 if (ret != 0) 00371 break; 00372 00373 ret = wc_Sha512Final(&sha512, Ai); 00374 if (ret != 0) 00375 break; 00376 00377 for (i = 1; i < iterations; i++) { 00378 ret = wc_Sha512Update(&sha512, Ai, u); 00379 if (ret != 0) 00380 break; 00381 00382 ret = wc_Sha512Final(&sha512, Ai); 00383 if (ret != 0) 00384 break; 00385 } 00386 } 00387 break; 00388 #endif /* WOLFSSL_SHA512 */ 00389 00390 default: 00391 ret = BAD_FUNC_ARG; 00392 break; 00393 } 00394 00395 return ret; 00396 } 00397 00398 00399 int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, 00400 int saltLen, int iterations, int kLen, int hashType, int id) 00401 { 00402 return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen, 00403 iterations, kLen, hashType, id, NULL); 00404 } 00405 00406 00407 /* extended API that allows a heap hint to be used */ 00408 int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, 00409 const byte* salt, int saltLen, int iterations, int kLen, 00410 int hashType, int id, void* heap) 00411 { 00412 /* all in bytes instead of bits */ 00413 word32 u, v, dLen, pLen, iLen, sLen, totalLen; 00414 int dynamic = 0; 00415 int ret = 0; 00416 int i; 00417 byte *D, *S, *P, *I; 00418 #ifdef WOLFSSL_SMALL_STACK 00419 byte staticBuffer[1]; /* force dynamic usage */ 00420 #else 00421 byte staticBuffer[1024]; 00422 #endif 00423 byte* buffer = staticBuffer; 00424 00425 #ifdef WOLFSSL_SMALL_STACK 00426 byte* Ai; 00427 byte* B; 00428 #else 00429 byte Ai[PBKDF_DIGEST_SIZE]; 00430 byte B[PBKDF_DIGEST_SIZE]; 00431 #endif 00432 00433 if (!iterations) 00434 iterations = 1; 00435 00436 ret = GetPKCS12HashSizes(hashType, &v, &u); 00437 if (ret < 0) 00438 return BAD_FUNC_ARG; 00439 00440 #ifdef WOLFSSL_SMALL_STACK 00441 Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00442 if (Ai == NULL) 00443 return MEMORY_E; 00444 00445 B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00446 if (B == NULL) { 00447 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00448 return MEMORY_E; 00449 } 00450 #endif 00451 00452 XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE); 00453 XMEMSET(B, 0, PBKDF_DIGEST_SIZE); 00454 00455 dLen = v; 00456 sLen = v * ((saltLen + v - 1) / v); 00457 if (passLen) 00458 pLen = v * ((passLen + v - 1) / v); 00459 else 00460 pLen = 0; 00461 iLen = sLen + pLen; 00462 00463 totalLen = dLen + sLen + pLen; 00464 00465 if (totalLen > sizeof(staticBuffer)) { 00466 buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY); 00467 if (buffer == NULL) { 00468 #ifdef WOLFSSL_SMALL_STACK 00469 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00470 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00471 #endif 00472 return MEMORY_E; 00473 } 00474 dynamic = 1; 00475 } 00476 00477 D = buffer; 00478 S = D + dLen; 00479 P = S + sLen; 00480 I = S; 00481 00482 XMEMSET(D, id, dLen); 00483 00484 for (i = 0; i < (int)sLen; i++) 00485 S[i] = salt[i % saltLen]; 00486 for (i = 0; i < (int)pLen; i++) 00487 P[i] = passwd[i % passLen]; 00488 00489 while (kLen > 0) { 00490 word32 currentLen; 00491 mp_int B1; 00492 00493 ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations); 00494 if (ret < 0) 00495 break; 00496 00497 for (i = 0; i < (int)v; i++) 00498 B[i] = Ai[i % u]; 00499 00500 if (mp_init(&B1) != MP_OKAY) 00501 ret = MP_INIT_E; 00502 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY) 00503 ret = MP_READ_E; 00504 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY) 00505 ret = MP_ADD_E; 00506 00507 if (ret != 0) { 00508 mp_clear(&B1); 00509 break; 00510 } 00511 00512 for (i = 0; i < (int)iLen; i += v) { 00513 int outSz; 00514 mp_int i1; 00515 mp_int res; 00516 00517 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) { 00518 ret = MP_INIT_E; 00519 break; 00520 } 00521 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY) 00522 ret = MP_READ_E; 00523 else if (mp_add(&i1, &B1, &res) != MP_OKAY) 00524 ret = MP_ADD_E; 00525 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0) 00526 ret = MP_TO_E; 00527 else { 00528 if (outSz > (int)v) { 00529 /* take off MSB */ 00530 byte tmp[129]; 00531 ret = mp_to_unsigned_bin(&res, tmp); 00532 XMEMCPY(I + i, tmp + 1, v); 00533 } 00534 else if (outSz < (int)v) { 00535 XMEMSET(I + i, 0, v - outSz); 00536 ret = mp_to_unsigned_bin(&res, I + i + v - outSz); 00537 } 00538 else 00539 ret = mp_to_unsigned_bin(&res, I + i); 00540 } 00541 00542 mp_clear(&i1); 00543 mp_clear(&res); 00544 if (ret < 0) break; 00545 } 00546 00547 currentLen = min(kLen, (int)u); 00548 XMEMCPY(output, Ai, currentLen); 00549 output += currentLen; 00550 kLen -= currentLen; 00551 mp_clear(&B1); 00552 } 00553 00554 if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY); 00555 00556 #ifdef WOLFSSL_SMALL_STACK 00557 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00558 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00559 #endif 00560 00561 return ret; 00562 } 00563 00564 #ifdef HAVE_SCRYPT 00565 /* Rotate the 32-bit value a by b bits to the left. 00566 * 00567 * a 32-bit value. 00568 * b Number of bits to rotate. 00569 * returns rotated value. 00570 */ 00571 #define R(a, b) rotlFixed(a, b) 00572 00573 /* One round of Salsa20/8. 00574 * Code taken from RFC 7914: scrypt PBKDF. 00575 * 00576 * out Output buffer. 00577 * in Input data to hash. 00578 */ 00579 static void scryptSalsa(word32* out, word32* in) 00580 { 00581 int i; 00582 word32 x[16]; 00583 00584 #ifdef LITTLE_ENDIAN_ORDER 00585 for (i = 0; i < 16; ++i) 00586 x[i] = in[i]; 00587 #else 00588 for (i = 0; i < 16; i++) 00589 x[i] = ByteReverseWord32(in[i]); 00590 #endif 00591 for (i = 8; i > 0; i -= 2) { 00592 x[ 4] ^= R(x[ 0] + x[12], 7); x[ 8] ^= R(x[ 4] + x[ 0], 9); 00593 x[12] ^= R(x[ 8] + x[ 4], 13); x[ 0] ^= R(x[12] + x[ 8], 18); 00594 x[ 9] ^= R(x[ 5] + x[ 1], 7); x[13] ^= R(x[ 9] + x[ 5], 9); 00595 x[ 1] ^= R(x[13] + x[ 9], 13); x[ 5] ^= R(x[ 1] + x[13], 18); 00596 x[14] ^= R(x[10] + x[ 6], 7); x[ 2] ^= R(x[14] + x[10], 9); 00597 x[ 6] ^= R(x[ 2] + x[14], 13); x[10] ^= R(x[ 6] + x[ 2], 18); 00598 x[ 3] ^= R(x[15] + x[11], 7); x[ 7] ^= R(x[ 3] + x[15], 9); 00599 x[11] ^= R(x[ 7] + x[ 3], 13); x[15] ^= R(x[11] + x[ 7], 18); 00600 x[ 1] ^= R(x[ 0] + x[ 3], 7); x[ 2] ^= R(x[ 1] + x[ 0], 9); 00601 x[ 3] ^= R(x[ 2] + x[ 1], 13); x[ 0] ^= R(x[ 3] + x[ 2], 18); 00602 x[ 6] ^= R(x[ 5] + x[ 4], 7); x[ 7] ^= R(x[ 6] + x[ 5], 9); 00603 x[ 4] ^= R(x[ 7] + x[ 6], 13); x[ 5] ^= R(x[ 4] + x[ 7], 18); 00604 x[11] ^= R(x[10] + x[ 9], 7); x[ 8] ^= R(x[11] + x[10], 9); 00605 x[ 9] ^= R(x[ 8] + x[11], 13); x[10] ^= R(x[ 9] + x[ 8], 18); 00606 x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9); 00607 x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18); 00608 } 00609 #ifdef LITTLE_ENDIAN_ORDER 00610 for (i = 0; i < 16; ++i) 00611 out[i] = in[i] + x[i]; 00612 #else 00613 for (i = 0; i < 16; i++) 00614 out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]); 00615 #endif 00616 } 00617 00618 /* Mix a block using Salsa20/8. 00619 * Based on RFC 7914: scrypt PBKDF. 00620 * 00621 * b Blocks to mix. 00622 * y Temporary storage. 00623 * r Size of the block. 00624 */ 00625 static void scryptBlockMix(byte* b, byte* y, int r) 00626 { 00627 byte x[64]; 00628 #ifdef WORD64_AVAILABLE 00629 word64* b64 = (word64*)b; 00630 word64* y64 = (word64*)y; 00631 word64* x64 = (word64*)x; 00632 #else 00633 word32* b32 = (word32*)b; 00634 word32* y32 = (word32*)y; 00635 word32* x32 = (word32*)x; 00636 #endif 00637 int i; 00638 int j; 00639 00640 /* Step 1. */ 00641 XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x)); 00642 /* Step 2. */ 00643 for (i = 0; i < 2 * r; i++) 00644 { 00645 #ifdef WORD64_AVAILABLE 00646 for (j = 0; j < 8; j++) 00647 x64[j] ^= b64[i * 8 + j]; 00648 #else 00649 for (j = 0; j < 16; j++) 00650 x32[j] ^= b32[i * 16 + j]; 00651 #endif 00652 scryptSalsa((word32*)x, (word32*)x); 00653 XMEMCPY(y + i * 64, x, sizeof(x)); 00654 } 00655 /* Step 3. */ 00656 for (i = 0; i < r; i++) { 00657 #ifdef WORD64_AVAILABLE 00658 for (j = 0; j < 8; j++) { 00659 b64[i * 8 + j] = y64[2 * i * 8 + j]; 00660 b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j]; 00661 } 00662 #else 00663 for (j = 0; j < 16; j++) { 00664 b32[i * 16 + j] = y32[2 * i * 16 + j]; 00665 b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j]; 00666 } 00667 #endif 00668 } 00669 } 00670 00671 /* Random oracles mix. 00672 * Based on RFC 7914: scrypt PBKDF. 00673 * 00674 * x Data to mix. 00675 * v Temporary buffer. 00676 * y Temporary buffer for the block mix. 00677 * r Block size parameter. 00678 * n CPU/Memory cost parameter. 00679 */ 00680 static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n) 00681 { 00682 word32 i; 00683 word32 j; 00684 word32 k; 00685 word32 bSz = 128 * r; 00686 #ifdef WORD64_AVAILABLE 00687 word64* x64 = (word64*)x; 00688 word64* v64 = (word64*)v; 00689 #else 00690 word32* x32 = (word32*)x; 00691 word32* v32 = (word32*)v; 00692 #endif 00693 00694 /* Step 1. X = B (B not needed therefore not implemented) */ 00695 /* Step 2. */ 00696 for (i = 0; i < n; i++) 00697 { 00698 XMEMCPY(v + i * bSz, x, bSz); 00699 scryptBlockMix(x, y, r); 00700 } 00701 00702 /* Step 3. */ 00703 for (i = 0; i < n; i++) 00704 { 00705 #ifdef LITTLE_ENDIAN_ORDER 00706 #ifdef WORD64_AVAILABLE 00707 j = *(word64*)(x + (2*r - 1) * 64) & (n-1); 00708 #else 00709 j = *(word32*)(x + (2*r - 1) * 64) & (n-1); 00710 #endif 00711 #else 00712 byte* t = x + (2*r - 1) * 64; 00713 j = (t[0] | (t[1] << 8) | (t[2] << 16) | (t[3] << 24)) & (n-1); 00714 #endif 00715 #ifdef WORD64_AVAILABLE 00716 for (k = 0; k < bSz / 8; k++) 00717 x64[k] ^= v64[j * bSz / 8 + k]; 00718 #else 00719 for (k = 0; k < bSz / 4; k++) 00720 x32[k] ^= v32[j * bSz / 4 + k]; 00721 #endif 00722 scryptBlockMix(x, y, r); 00723 } 00724 /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */ 00725 } 00726 00727 /* Generates an key derived from a password and salt using a memory hard 00728 * algorithm. 00729 * Implements RFC 7914: scrypt PBKDF. 00730 * 00731 * output The derived key. 00732 * passwd The password to derive key from. 00733 * passLen The length of the password. 00734 * salt The key specific data. 00735 * saltLen The length of the salt data. 00736 * cost The CPU/memory cost parameter. Range: 1..(128*r/8-1) 00737 * (Iterations = 2^cost) 00738 * blockSize The number of 128 byte octets in a working block. 00739 * parallel The number of parallel mix operations to perform. 00740 * (Note: this implementation does not use threads.) 00741 * dkLen The length of the derived key in bytes. 00742 * returns BAD_FUNC_ARG when: parallel not 1, blockSize is too large for cost. 00743 */ 00744 int wc_scrypt(byte* output, const byte* passwd, int passLen, 00745 const byte* salt, int saltLen, int cost, int blockSize, 00746 int parallel, int dkLen) 00747 { 00748 int ret = 0; 00749 int i; 00750 byte* v = NULL; 00751 byte* y = NULL; 00752 byte* blocks = NULL; 00753 word32 blocksSz; 00754 word32 bSz; 00755 00756 if (blockSize > 8) 00757 return BAD_FUNC_ARG; 00758 00759 if (cost < 1 || cost >= 128 * blockSize / 8) 00760 return BAD_FUNC_ARG; 00761 00762 bSz = 128 * blockSize; 00763 blocksSz = bSz * parallel; 00764 blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00765 if (blocks == NULL) 00766 goto end; 00767 /* Temporary for scryptROMix. */ 00768 v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00769 if (v == NULL) 00770 goto end; 00771 /* Temporary for scryptBlockMix. */ 00772 y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00773 if (y == NULL) 00774 goto end; 00775 00776 /* Step 1. */ 00777 ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz, 00778 SHA256); 00779 if (ret != 0) 00780 goto end; 00781 00782 /* Step 2. */ 00783 for (i = 0; i < parallel; i++) 00784 scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost); 00785 00786 /* Step 3. */ 00787 ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen, 00788 SHA256); 00789 end: 00790 if (blocks != NULL) 00791 XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00792 if (v != NULL) 00793 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00794 if (y != NULL) 00795 XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00796 00797 return ret; 00798 } 00799 #endif 00800 00801 #undef PBKDF_DIGEST_SIZE 00802 00803 #endif /* NO_PWDBASED */ 00804 00805
Generated on Tue Jul 12 2022 23:30:59 by
1.7.2
