wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

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-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