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