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