Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pwdbased.c Source File

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