Xuyi Wang / wolfcrypt

Dependents:   OS

Committer:
sPymbed
Date:
Mon Nov 25 14:23:49 2019 +0000
Revision:
1:e4ea39eba2fb
Parent:
0:1387ff3eed4a
improved

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sPymbed 0:1387ff3eed4a 1 /* pwdbased.c
sPymbed 0:1387ff3eed4a 2 *
sPymbed 0:1387ff3eed4a 3 * Copyright (C) 2006-2017 wolfSSL Inc.
sPymbed 0:1387ff3eed4a 4 *
sPymbed 0:1387ff3eed4a 5 * This file is part of wolfSSL.
sPymbed 0:1387ff3eed4a 6 *
sPymbed 0:1387ff3eed4a 7 * wolfSSL is free software; you can redistribute it and/or modify
sPymbed 0:1387ff3eed4a 8 * it under the terms of the GNU General Public License as published by
sPymbed 0:1387ff3eed4a 9 * the Free Software Foundation; either version 2 of the License, or
sPymbed 0:1387ff3eed4a 10 * (at your option) any later version.
sPymbed 0:1387ff3eed4a 11 *
sPymbed 0:1387ff3eed4a 12 * wolfSSL is distributed in the hope that it will be useful,
sPymbed 0:1387ff3eed4a 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sPymbed 0:1387ff3eed4a 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
sPymbed 0:1387ff3eed4a 15 * GNU General Public License for more details.
sPymbed 0:1387ff3eed4a 16 *
sPymbed 0:1387ff3eed4a 17 * You should have received a copy of the GNU General Public License
sPymbed 0:1387ff3eed4a 18 * along with this program; if not, write to the Free Software
sPymbed 0:1387ff3eed4a 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
sPymbed 0:1387ff3eed4a 20 */
sPymbed 0:1387ff3eed4a 21
sPymbed 0:1387ff3eed4a 22
sPymbed 0:1387ff3eed4a 23 #ifdef HAVE_CONFIG_H
sPymbed 0:1387ff3eed4a 24 #include <config.h>
sPymbed 0:1387ff3eed4a 25 #endif
sPymbed 0:1387ff3eed4a 26
sPymbed 0:1387ff3eed4a 27 #include <wolfcrypt/settings.h>
sPymbed 0:1387ff3eed4a 28
sPymbed 0:1387ff3eed4a 29 #ifndef NO_PWDBASED
sPymbed 0:1387ff3eed4a 30
sPymbed 0:1387ff3eed4a 31 #include <wolfcrypt/pwdbased.h>
sPymbed 0:1387ff3eed4a 32 #include <wolfcrypt/hmac.h>
sPymbed 0:1387ff3eed4a 33 #include <wolfcrypt/hash.h>
sPymbed 0:1387ff3eed4a 34 #include <wolfcrypt/integer.h>
sPymbed 0:1387ff3eed4a 35 #include <wolfcrypt/error-crypt.h>
sPymbed 0:1387ff3eed4a 36
sPymbed 0:1387ff3eed4a 37 #ifdef NO_INLINE
sPymbed 0:1387ff3eed4a 38 #include <wolfcrypt/misc.h>
sPymbed 0:1387ff3eed4a 39 #else
sPymbed 0:1387ff3eed4a 40 #define WOLFSSL_MISC_INCLUDED
sPymbed 0:1387ff3eed4a 41 #include <wolfcrypt/src/misc.c>
sPymbed 0:1387ff3eed4a 42 #endif
sPymbed 0:1387ff3eed4a 43
sPymbed 0:1387ff3eed4a 44
sPymbed 0:1387ff3eed4a 45 /* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */
sPymbed 0:1387ff3eed4a 46 int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
sPymbed 0:1387ff3eed4a 47 const byte* passwd, int passwdLen, const byte* salt, int saltLen,
sPymbed 0:1387ff3eed4a 48 int iterations, int hashType, void* heap)
sPymbed 0:1387ff3eed4a 49 {
sPymbed 0:1387ff3eed4a 50 int err;
sPymbed 0:1387ff3eed4a 51 int keyLeft, ivLeft, i;
sPymbed 0:1387ff3eed4a 52 int digestLeft, store;
sPymbed 0:1387ff3eed4a 53 int keyOutput = 0;
sPymbed 0:1387ff3eed4a 54 int diestLen;
sPymbed 0:1387ff3eed4a 55 byte digest[WC_MAX_DIGEST_SIZE];
sPymbed 0:1387ff3eed4a 56 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 57 wc_HashAlg* hash = NULL;
sPymbed 0:1387ff3eed4a 58 #else
sPymbed 0:1387ff3eed4a 59 wc_HashAlg hash[1];
sPymbed 0:1387ff3eed4a 60 #endif
sPymbed 0:1387ff3eed4a 61 enum wc_HashType hashT;
sPymbed 0:1387ff3eed4a 62
sPymbed 0:1387ff3eed4a 63 (void)heap;
sPymbed 0:1387ff3eed4a 64
sPymbed 0:1387ff3eed4a 65 if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){
sPymbed 0:1387ff3eed4a 66 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 67 }
sPymbed 0:1387ff3eed4a 68
sPymbed 0:1387ff3eed4a 69 if (iterations <= 0)
sPymbed 0:1387ff3eed4a 70 iterations = 1;
sPymbed 0:1387ff3eed4a 71
sPymbed 0:1387ff3eed4a 72 hashT = wc_HashTypeConvert(hashType);
sPymbed 0:1387ff3eed4a 73 err = wc_HashGetDigestSize(hashT);
sPymbed 0:1387ff3eed4a 74 if (err < 0)
sPymbed 0:1387ff3eed4a 75 return err;
sPymbed 0:1387ff3eed4a 76 diestLen = err;
sPymbed 0:1387ff3eed4a 77
sPymbed 0:1387ff3eed4a 78 /* initialize hash */
sPymbed 0:1387ff3eed4a 79 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 80 hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap,
sPymbed 0:1387ff3eed4a 81 DYNAMIC_TYPE_HASHCTX);
sPymbed 0:1387ff3eed4a 82 if (hash == NULL)
sPymbed 0:1387ff3eed4a 83 return MEMORY_E;
sPymbed 0:1387ff3eed4a 84 #endif
sPymbed 0:1387ff3eed4a 85
sPymbed 0:1387ff3eed4a 86 err = wc_HashInit(hash, hashT);
sPymbed 0:1387ff3eed4a 87 if (err != 0) {
sPymbed 0:1387ff3eed4a 88 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 89 XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
sPymbed 0:1387ff3eed4a 90 #endif
sPymbed 0:1387ff3eed4a 91 return err;
sPymbed 0:1387ff3eed4a 92 }
sPymbed 0:1387ff3eed4a 93
sPymbed 0:1387ff3eed4a 94 keyLeft = keyLen;
sPymbed 0:1387ff3eed4a 95 ivLeft = ivLen;
sPymbed 0:1387ff3eed4a 96 while (keyOutput < (keyLen + ivLen)) {
sPymbed 0:1387ff3eed4a 97 digestLeft = diestLen;
sPymbed 0:1387ff3eed4a 98 /* D_(i - 1) */
sPymbed 0:1387ff3eed4a 99 if (keyOutput) { /* first time D_0 is empty */
sPymbed 0:1387ff3eed4a 100 err = wc_HashUpdate(hash, hashT, digest, diestLen);
sPymbed 0:1387ff3eed4a 101 if (err != 0) break;
sPymbed 0:1387ff3eed4a 102 }
sPymbed 0:1387ff3eed4a 103
sPymbed 0:1387ff3eed4a 104 /* data */
sPymbed 0:1387ff3eed4a 105 err = wc_HashUpdate(hash, hashT, passwd, passwdLen);
sPymbed 0:1387ff3eed4a 106 if (err != 0) break;
sPymbed 0:1387ff3eed4a 107
sPymbed 0:1387ff3eed4a 108 /* salt */
sPymbed 0:1387ff3eed4a 109 if (salt) {
sPymbed 0:1387ff3eed4a 110 err = wc_HashUpdate(hash, hashT, salt, saltLen);
sPymbed 0:1387ff3eed4a 111 if (err != 0) break;
sPymbed 0:1387ff3eed4a 112 }
sPymbed 0:1387ff3eed4a 113
sPymbed 0:1387ff3eed4a 114 err = wc_HashFinal(hash, hashT, digest);
sPymbed 0:1387ff3eed4a 115 if (err != 0) break;
sPymbed 0:1387ff3eed4a 116
sPymbed 0:1387ff3eed4a 117 /* count */
sPymbed 0:1387ff3eed4a 118 for (i = 1; i < iterations; i++) {
sPymbed 0:1387ff3eed4a 119 err = wc_HashUpdate(hash, hashT, digest, diestLen);
sPymbed 0:1387ff3eed4a 120 if (err != 0) break;
sPymbed 0:1387ff3eed4a 121
sPymbed 0:1387ff3eed4a 122 err = wc_HashFinal(hash, hashT, digest);
sPymbed 0:1387ff3eed4a 123 if (err != 0) break;
sPymbed 0:1387ff3eed4a 124 }
sPymbed 0:1387ff3eed4a 125
sPymbed 0:1387ff3eed4a 126 if (keyLeft) {
sPymbed 0:1387ff3eed4a 127 store = min(keyLeft, diestLen);
sPymbed 0:1387ff3eed4a 128 XMEMCPY(&key[keyLen - keyLeft], digest, store);
sPymbed 0:1387ff3eed4a 129
sPymbed 0:1387ff3eed4a 130 keyOutput += store;
sPymbed 0:1387ff3eed4a 131 keyLeft -= store;
sPymbed 0:1387ff3eed4a 132 digestLeft -= store;
sPymbed 0:1387ff3eed4a 133 }
sPymbed 0:1387ff3eed4a 134
sPymbed 0:1387ff3eed4a 135 if (ivLeft && digestLeft) {
sPymbed 0:1387ff3eed4a 136 store = min(ivLeft, digestLeft);
sPymbed 0:1387ff3eed4a 137 if (iv != NULL)
sPymbed 0:1387ff3eed4a 138 XMEMCPY(&iv[ivLen - ivLeft],
sPymbed 0:1387ff3eed4a 139 &digest[diestLen - digestLeft], store);
sPymbed 0:1387ff3eed4a 140 keyOutput += store;
sPymbed 0:1387ff3eed4a 141 ivLeft -= store;
sPymbed 0:1387ff3eed4a 142 }
sPymbed 0:1387ff3eed4a 143 }
sPymbed 0:1387ff3eed4a 144
sPymbed 0:1387ff3eed4a 145 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 146 XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
sPymbed 0:1387ff3eed4a 147 #endif
sPymbed 0:1387ff3eed4a 148
sPymbed 0:1387ff3eed4a 149 if (err != 0)
sPymbed 0:1387ff3eed4a 150 return err;
sPymbed 0:1387ff3eed4a 151
sPymbed 0:1387ff3eed4a 152 if (keyOutput != (keyLen + ivLen))
sPymbed 0:1387ff3eed4a 153 return BUFFER_E;
sPymbed 0:1387ff3eed4a 154
sPymbed 0:1387ff3eed4a 155 return err;
sPymbed 0:1387ff3eed4a 156 }
sPymbed 0:1387ff3eed4a 157
sPymbed 0:1387ff3eed4a 158 /* PKCS#5 v1.5 */
sPymbed 0:1387ff3eed4a 159 int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
sPymbed 0:1387ff3eed4a 160 int sLen, int iterations, int kLen, int hashType)
sPymbed 0:1387ff3eed4a 161 {
sPymbed 0:1387ff3eed4a 162 return wc_PBKDF1_ex(output, kLen, NULL, 0,
sPymbed 0:1387ff3eed4a 163 passwd, pLen, salt, sLen, iterations, hashType, NULL);
sPymbed 0:1387ff3eed4a 164 }
sPymbed 0:1387ff3eed4a 165
sPymbed 0:1387ff3eed4a 166
sPymbed 0:1387ff3eed4a 167 int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
sPymbed 0:1387ff3eed4a 168 int sLen, int iterations, int kLen, int hashType)
sPymbed 0:1387ff3eed4a 169 {
sPymbed 0:1387ff3eed4a 170 word32 i = 1;
sPymbed 0:1387ff3eed4a 171 int hLen;
sPymbed 0:1387ff3eed4a 172 int j, ret;
sPymbed 0:1387ff3eed4a 173 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 174 byte* buffer;
sPymbed 0:1387ff3eed4a 175 Hmac* hmac;
sPymbed 0:1387ff3eed4a 176 #else
sPymbed 0:1387ff3eed4a 177 byte buffer[WC_MAX_DIGEST_SIZE];
sPymbed 0:1387ff3eed4a 178 Hmac hmac[1];
sPymbed 0:1387ff3eed4a 179 #endif
sPymbed 0:1387ff3eed4a 180 enum wc_HashType hashT;
sPymbed 0:1387ff3eed4a 181
sPymbed 0:1387ff3eed4a 182 if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) {
sPymbed 0:1387ff3eed4a 183 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 184 }
sPymbed 0:1387ff3eed4a 185
sPymbed 0:1387ff3eed4a 186 if (iterations <= 0)
sPymbed 0:1387ff3eed4a 187 iterations = 1;
sPymbed 0:1387ff3eed4a 188
sPymbed 0:1387ff3eed4a 189 hashT = wc_HashTypeConvert(hashType);
sPymbed 0:1387ff3eed4a 190 hLen = wc_HashGetDigestSize(hashT);
sPymbed 0:1387ff3eed4a 191 if (hLen < 0)
sPymbed 0:1387ff3eed4a 192 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 193
sPymbed 0:1387ff3eed4a 194 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 195 buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 196 if (buffer == NULL)
sPymbed 0:1387ff3eed4a 197 return MEMORY_E;
sPymbed 0:1387ff3eed4a 198 hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC);
sPymbed 0:1387ff3eed4a 199 if (buffer == NULL)
sPymbed 0:1387ff3eed4a 200 return MEMORY_E;
sPymbed 0:1387ff3eed4a 201 #endif
sPymbed 0:1387ff3eed4a 202
sPymbed 0:1387ff3eed4a 203 ret = wc_HmacInit(hmac, NULL, INVALID_DEVID);
sPymbed 0:1387ff3eed4a 204 if (ret == 0) {
sPymbed 0:1387ff3eed4a 205 /* use int hashType here, since HMAC FIPS uses the old unique value */
sPymbed 0:1387ff3eed4a 206 ret = wc_HmacSetKey(hmac, hashType, passwd, pLen);
sPymbed 0:1387ff3eed4a 207
sPymbed 0:1387ff3eed4a 208 while (ret == 0 && kLen) {
sPymbed 0:1387ff3eed4a 209 int currentLen;
sPymbed 0:1387ff3eed4a 210
sPymbed 0:1387ff3eed4a 211 ret = wc_HmacUpdate(hmac, salt, sLen);
sPymbed 0:1387ff3eed4a 212 if (ret != 0)
sPymbed 0:1387ff3eed4a 213 break;
sPymbed 0:1387ff3eed4a 214
sPymbed 0:1387ff3eed4a 215 /* encode i */
sPymbed 0:1387ff3eed4a 216 for (j = 0; j < 4; j++) {
sPymbed 0:1387ff3eed4a 217 byte b = (byte)(i >> ((3-j) * 8));
sPymbed 0:1387ff3eed4a 218
sPymbed 0:1387ff3eed4a 219 ret = wc_HmacUpdate(hmac, &b, 1);
sPymbed 0:1387ff3eed4a 220 if (ret != 0)
sPymbed 0:1387ff3eed4a 221 break;
sPymbed 0:1387ff3eed4a 222 }
sPymbed 0:1387ff3eed4a 223
sPymbed 0:1387ff3eed4a 224 /* check ret from inside for loop */
sPymbed 0:1387ff3eed4a 225 if (ret != 0)
sPymbed 0:1387ff3eed4a 226 break;
sPymbed 0:1387ff3eed4a 227
sPymbed 0:1387ff3eed4a 228 ret = wc_HmacFinal(hmac, buffer);
sPymbed 0:1387ff3eed4a 229 if (ret != 0)
sPymbed 0:1387ff3eed4a 230 break;
sPymbed 0:1387ff3eed4a 231
sPymbed 0:1387ff3eed4a 232 currentLen = min(kLen, hLen);
sPymbed 0:1387ff3eed4a 233 XMEMCPY(output, buffer, currentLen);
sPymbed 0:1387ff3eed4a 234
sPymbed 0:1387ff3eed4a 235 for (j = 1; j < iterations; j++) {
sPymbed 0:1387ff3eed4a 236 ret = wc_HmacUpdate(hmac, buffer, hLen);
sPymbed 0:1387ff3eed4a 237 if (ret != 0)
sPymbed 0:1387ff3eed4a 238 break;
sPymbed 0:1387ff3eed4a 239 ret = wc_HmacFinal(hmac, buffer);
sPymbed 0:1387ff3eed4a 240 if (ret != 0)
sPymbed 0:1387ff3eed4a 241 break;
sPymbed 0:1387ff3eed4a 242 xorbuf(output, buffer, currentLen);
sPymbed 0:1387ff3eed4a 243 }
sPymbed 0:1387ff3eed4a 244
sPymbed 0:1387ff3eed4a 245 /* check ret from inside for loop */
sPymbed 0:1387ff3eed4a 246 if (ret != 0)
sPymbed 0:1387ff3eed4a 247 break;
sPymbed 0:1387ff3eed4a 248
sPymbed 0:1387ff3eed4a 249 output += currentLen;
sPymbed 0:1387ff3eed4a 250 kLen -= currentLen;
sPymbed 0:1387ff3eed4a 251 i++;
sPymbed 0:1387ff3eed4a 252 }
sPymbed 0:1387ff3eed4a 253 wc_HmacFree(hmac);
sPymbed 0:1387ff3eed4a 254 }
sPymbed 0:1387ff3eed4a 255
sPymbed 0:1387ff3eed4a 256 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 257 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 258 XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC);
sPymbed 0:1387ff3eed4a 259 #endif
sPymbed 0:1387ff3eed4a 260
sPymbed 0:1387ff3eed4a 261 return ret;
sPymbed 0:1387ff3eed4a 262 }
sPymbed 0:1387ff3eed4a 263
sPymbed 0:1387ff3eed4a 264 /* helper for PKCS12_PBKDF(), does hash operation */
sPymbed 0:1387ff3eed4a 265 static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
sPymbed 0:1387ff3eed4a 266 byte* Ai, word32 u, int iterations)
sPymbed 0:1387ff3eed4a 267 {
sPymbed 0:1387ff3eed4a 268 int i;
sPymbed 0:1387ff3eed4a 269 int ret = 0;
sPymbed 0:1387ff3eed4a 270 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 271 wc_HashAlg* hash = NULL;
sPymbed 0:1387ff3eed4a 272 #else
sPymbed 0:1387ff3eed4a 273 wc_HashAlg hash[1];
sPymbed 0:1387ff3eed4a 274 #endif
sPymbed 0:1387ff3eed4a 275 enum wc_HashType hashT;
sPymbed 0:1387ff3eed4a 276
sPymbed 0:1387ff3eed4a 277 if (buffer == NULL || Ai == NULL) {
sPymbed 0:1387ff3eed4a 278 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 279 }
sPymbed 0:1387ff3eed4a 280
sPymbed 0:1387ff3eed4a 281 hashT = wc_HashTypeConvert(hashType);
sPymbed 0:1387ff3eed4a 282
sPymbed 0:1387ff3eed4a 283 /* initialize hash */
sPymbed 0:1387ff3eed4a 284 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 285 hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL,
sPymbed 0:1387ff3eed4a 286 DYNAMIC_TYPE_HASHCTX);
sPymbed 0:1387ff3eed4a 287 if (hash == NULL)
sPymbed 0:1387ff3eed4a 288 return MEMORY_E;
sPymbed 0:1387ff3eed4a 289 #endif
sPymbed 0:1387ff3eed4a 290
sPymbed 0:1387ff3eed4a 291 ret = wc_HashInit(hash, hashT);
sPymbed 0:1387ff3eed4a 292 if (ret != 0) {
sPymbed 0:1387ff3eed4a 293 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 294 XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
sPymbed 0:1387ff3eed4a 295 #endif
sPymbed 0:1387ff3eed4a 296 return ret;
sPymbed 0:1387ff3eed4a 297 }
sPymbed 0:1387ff3eed4a 298
sPymbed 0:1387ff3eed4a 299 ret = wc_HashUpdate(hash, hashT, buffer, totalLen);
sPymbed 0:1387ff3eed4a 300
sPymbed 0:1387ff3eed4a 301 if (ret == 0)
sPymbed 0:1387ff3eed4a 302 ret = wc_HashFinal(hash, hashT, Ai);
sPymbed 0:1387ff3eed4a 303
sPymbed 0:1387ff3eed4a 304 for (i = 1; i < iterations; i++) {
sPymbed 0:1387ff3eed4a 305 if (ret == 0)
sPymbed 0:1387ff3eed4a 306 ret = wc_HashUpdate(hash, hashT, Ai, u);
sPymbed 0:1387ff3eed4a 307 if (ret == 0)
sPymbed 0:1387ff3eed4a 308 ret = wc_HashFinal(hash, hashT, Ai);
sPymbed 0:1387ff3eed4a 309 }
sPymbed 0:1387ff3eed4a 310
sPymbed 0:1387ff3eed4a 311 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 312 XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
sPymbed 0:1387ff3eed4a 313 #endif
sPymbed 0:1387ff3eed4a 314
sPymbed 0:1387ff3eed4a 315 return ret;
sPymbed 0:1387ff3eed4a 316 }
sPymbed 0:1387ff3eed4a 317
sPymbed 0:1387ff3eed4a 318
sPymbed 0:1387ff3eed4a 319 int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,
sPymbed 0:1387ff3eed4a 320 const byte* salt, int saltLen, int iterations, int kLen, int hashType,
sPymbed 0:1387ff3eed4a 321 int id)
sPymbed 0:1387ff3eed4a 322 {
sPymbed 0:1387ff3eed4a 323 return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen,
sPymbed 0:1387ff3eed4a 324 iterations, kLen, hashType, id, NULL);
sPymbed 0:1387ff3eed4a 325 }
sPymbed 0:1387ff3eed4a 326
sPymbed 0:1387ff3eed4a 327
sPymbed 0:1387ff3eed4a 328 /* extended API that allows a heap hint to be used */
sPymbed 0:1387ff3eed4a 329 int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
sPymbed 0:1387ff3eed4a 330 const byte* salt, int saltLen, int iterations, int kLen,
sPymbed 0:1387ff3eed4a 331 int hashType, int id, void* heap)
sPymbed 0:1387ff3eed4a 332 {
sPymbed 0:1387ff3eed4a 333 /* all in bytes instead of bits */
sPymbed 0:1387ff3eed4a 334 word32 u, v, dLen, pLen, iLen, sLen, totalLen;
sPymbed 0:1387ff3eed4a 335 int dynamic = 0;
sPymbed 0:1387ff3eed4a 336 int ret = 0;
sPymbed 0:1387ff3eed4a 337 int i;
sPymbed 0:1387ff3eed4a 338 byte *D, *S, *P, *I;
sPymbed 0:1387ff3eed4a 339 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 340 byte staticBuffer[1]; /* force dynamic usage */
sPymbed 0:1387ff3eed4a 341 #else
sPymbed 0:1387ff3eed4a 342 byte staticBuffer[1024];
sPymbed 0:1387ff3eed4a 343 #endif
sPymbed 0:1387ff3eed4a 344 byte* buffer = staticBuffer;
sPymbed 0:1387ff3eed4a 345
sPymbed 0:1387ff3eed4a 346 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 347 byte* Ai;
sPymbed 0:1387ff3eed4a 348 byte* B;
sPymbed 0:1387ff3eed4a 349 #else
sPymbed 0:1387ff3eed4a 350 byte Ai[WC_MAX_DIGEST_SIZE];
sPymbed 0:1387ff3eed4a 351 byte B[WC_MAX_BLOCK_SIZE];
sPymbed 0:1387ff3eed4a 352 #endif
sPymbed 0:1387ff3eed4a 353 enum wc_HashType hashT;
sPymbed 0:1387ff3eed4a 354
sPymbed 0:1387ff3eed4a 355 (void)heap;
sPymbed 0:1387ff3eed4a 356
sPymbed 0:1387ff3eed4a 357 if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) {
sPymbed 0:1387ff3eed4a 358 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 359 }
sPymbed 0:1387ff3eed4a 360
sPymbed 0:1387ff3eed4a 361 if (iterations <= 0)
sPymbed 0:1387ff3eed4a 362 iterations = 1;
sPymbed 0:1387ff3eed4a 363
sPymbed 0:1387ff3eed4a 364 hashT = wc_HashTypeConvert(hashType);
sPymbed 0:1387ff3eed4a 365 ret = wc_HashGetDigestSize(hashT);
sPymbed 0:1387ff3eed4a 366 if (ret < 0)
sPymbed 0:1387ff3eed4a 367 return ret;
sPymbed 0:1387ff3eed4a 368 u = ret;
sPymbed 0:1387ff3eed4a 369
sPymbed 0:1387ff3eed4a 370 ret = wc_HashGetBlockSize(hashT);
sPymbed 0:1387ff3eed4a 371 if (ret < 0)
sPymbed 0:1387ff3eed4a 372 return ret;
sPymbed 0:1387ff3eed4a 373 v = ret;
sPymbed 0:1387ff3eed4a 374
sPymbed 0:1387ff3eed4a 375 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 376 Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 377 if (Ai == NULL)
sPymbed 0:1387ff3eed4a 378 return MEMORY_E;
sPymbed 0:1387ff3eed4a 379
sPymbed 0:1387ff3eed4a 380 B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 381 if (B == NULL) {
sPymbed 0:1387ff3eed4a 382 XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 383 return MEMORY_E;
sPymbed 0:1387ff3eed4a 384 }
sPymbed 0:1387ff3eed4a 385 #endif
sPymbed 0:1387ff3eed4a 386
sPymbed 0:1387ff3eed4a 387 XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE);
sPymbed 0:1387ff3eed4a 388 XMEMSET(B, 0, WC_MAX_BLOCK_SIZE);
sPymbed 0:1387ff3eed4a 389
sPymbed 0:1387ff3eed4a 390 dLen = v;
sPymbed 0:1387ff3eed4a 391 sLen = v * ((saltLen + v - 1) / v);
sPymbed 0:1387ff3eed4a 392 if (passLen)
sPymbed 0:1387ff3eed4a 393 pLen = v * ((passLen + v - 1) / v);
sPymbed 0:1387ff3eed4a 394 else
sPymbed 0:1387ff3eed4a 395 pLen = 0;
sPymbed 0:1387ff3eed4a 396 iLen = sLen + pLen;
sPymbed 0:1387ff3eed4a 397
sPymbed 0:1387ff3eed4a 398 totalLen = dLen + sLen + pLen;
sPymbed 0:1387ff3eed4a 399
sPymbed 0:1387ff3eed4a 400 if (totalLen > sizeof(staticBuffer)) {
sPymbed 0:1387ff3eed4a 401 buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
sPymbed 0:1387ff3eed4a 402 if (buffer == NULL) {
sPymbed 0:1387ff3eed4a 403 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 404 XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 405 XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 406 #endif
sPymbed 0:1387ff3eed4a 407 return MEMORY_E;
sPymbed 0:1387ff3eed4a 408 }
sPymbed 0:1387ff3eed4a 409 dynamic = 1;
sPymbed 0:1387ff3eed4a 410 }
sPymbed 0:1387ff3eed4a 411
sPymbed 0:1387ff3eed4a 412 D = buffer;
sPymbed 0:1387ff3eed4a 413 S = D + dLen;
sPymbed 0:1387ff3eed4a 414 P = S + sLen;
sPymbed 0:1387ff3eed4a 415 I = S;
sPymbed 0:1387ff3eed4a 416
sPymbed 0:1387ff3eed4a 417 XMEMSET(D, id, dLen);
sPymbed 0:1387ff3eed4a 418
sPymbed 0:1387ff3eed4a 419 for (i = 0; i < (int)sLen; i++)
sPymbed 0:1387ff3eed4a 420 S[i] = salt[i % saltLen];
sPymbed 0:1387ff3eed4a 421 for (i = 0; i < (int)pLen; i++)
sPymbed 0:1387ff3eed4a 422 P[i] = passwd[i % passLen];
sPymbed 0:1387ff3eed4a 423
sPymbed 0:1387ff3eed4a 424 while (kLen > 0) {
sPymbed 0:1387ff3eed4a 425 word32 currentLen;
sPymbed 0:1387ff3eed4a 426 mp_int B1;
sPymbed 0:1387ff3eed4a 427
sPymbed 0:1387ff3eed4a 428 ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
sPymbed 0:1387ff3eed4a 429 if (ret < 0)
sPymbed 0:1387ff3eed4a 430 break;
sPymbed 0:1387ff3eed4a 431
sPymbed 0:1387ff3eed4a 432 for (i = 0; i < (int)v; i++)
sPymbed 0:1387ff3eed4a 433 B[i] = Ai[i % u];
sPymbed 0:1387ff3eed4a 434
sPymbed 0:1387ff3eed4a 435 if (mp_init(&B1) != MP_OKAY)
sPymbed 0:1387ff3eed4a 436 ret = MP_INIT_E;
sPymbed 0:1387ff3eed4a 437 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
sPymbed 0:1387ff3eed4a 438 ret = MP_READ_E;
sPymbed 0:1387ff3eed4a 439 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
sPymbed 0:1387ff3eed4a 440 ret = MP_ADD_E;
sPymbed 0:1387ff3eed4a 441
sPymbed 0:1387ff3eed4a 442 if (ret != 0) {
sPymbed 0:1387ff3eed4a 443 mp_clear(&B1);
sPymbed 0:1387ff3eed4a 444 break;
sPymbed 0:1387ff3eed4a 445 }
sPymbed 0:1387ff3eed4a 446
sPymbed 0:1387ff3eed4a 447 for (i = 0; i < (int)iLen; i += v) {
sPymbed 0:1387ff3eed4a 448 int outSz;
sPymbed 0:1387ff3eed4a 449 mp_int i1;
sPymbed 0:1387ff3eed4a 450 mp_int res;
sPymbed 0:1387ff3eed4a 451
sPymbed 0:1387ff3eed4a 452 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
sPymbed 0:1387ff3eed4a 453 ret = MP_INIT_E;
sPymbed 0:1387ff3eed4a 454 break;
sPymbed 0:1387ff3eed4a 455 }
sPymbed 0:1387ff3eed4a 456 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
sPymbed 0:1387ff3eed4a 457 ret = MP_READ_E;
sPymbed 0:1387ff3eed4a 458 else if (mp_add(&i1, &B1, &res) != MP_OKAY)
sPymbed 0:1387ff3eed4a 459 ret = MP_ADD_E;
sPymbed 0:1387ff3eed4a 460 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
sPymbed 0:1387ff3eed4a 461 ret = MP_TO_E;
sPymbed 0:1387ff3eed4a 462 else {
sPymbed 0:1387ff3eed4a 463 if (outSz > (int)v) {
sPymbed 0:1387ff3eed4a 464 /* take off MSB */
sPymbed 0:1387ff3eed4a 465 byte tmp[129];
sPymbed 0:1387ff3eed4a 466 ret = mp_to_unsigned_bin(&res, tmp);
sPymbed 0:1387ff3eed4a 467 XMEMCPY(I + i, tmp + 1, v);
sPymbed 0:1387ff3eed4a 468 }
sPymbed 0:1387ff3eed4a 469 else if (outSz < (int)v) {
sPymbed 0:1387ff3eed4a 470 XMEMSET(I + i, 0, v - outSz);
sPymbed 0:1387ff3eed4a 471 ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
sPymbed 0:1387ff3eed4a 472 }
sPymbed 0:1387ff3eed4a 473 else
sPymbed 0:1387ff3eed4a 474 ret = mp_to_unsigned_bin(&res, I + i);
sPymbed 0:1387ff3eed4a 475 }
sPymbed 0:1387ff3eed4a 476
sPymbed 0:1387ff3eed4a 477 mp_clear(&i1);
sPymbed 0:1387ff3eed4a 478 mp_clear(&res);
sPymbed 0:1387ff3eed4a 479 if (ret < 0) break;
sPymbed 0:1387ff3eed4a 480 }
sPymbed 0:1387ff3eed4a 481
sPymbed 0:1387ff3eed4a 482 currentLen = min(kLen, (int)u);
sPymbed 0:1387ff3eed4a 483 XMEMCPY(output, Ai, currentLen);
sPymbed 0:1387ff3eed4a 484 output += currentLen;
sPymbed 0:1387ff3eed4a 485 kLen -= currentLen;
sPymbed 0:1387ff3eed4a 486 mp_clear(&B1);
sPymbed 0:1387ff3eed4a 487 }
sPymbed 0:1387ff3eed4a 488
sPymbed 0:1387ff3eed4a 489 if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
sPymbed 0:1387ff3eed4a 490
sPymbed 0:1387ff3eed4a 491 #ifdef WOLFSSL_SMALL_STACK
sPymbed 0:1387ff3eed4a 492 XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 493 XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 494 #endif
sPymbed 0:1387ff3eed4a 495
sPymbed 0:1387ff3eed4a 496 return ret;
sPymbed 0:1387ff3eed4a 497 }
sPymbed 0:1387ff3eed4a 498
sPymbed 0:1387ff3eed4a 499 #ifdef HAVE_SCRYPT
sPymbed 0:1387ff3eed4a 500 /* Rotate the 32-bit value a by b bits to the left.
sPymbed 0:1387ff3eed4a 501 *
sPymbed 0:1387ff3eed4a 502 * a 32-bit value.
sPymbed 0:1387ff3eed4a 503 * b Number of bits to rotate.
sPymbed 0:1387ff3eed4a 504 * returns rotated value.
sPymbed 0:1387ff3eed4a 505 */
sPymbed 0:1387ff3eed4a 506 #define R(a, b) rotlFixed(a, b)
sPymbed 0:1387ff3eed4a 507
sPymbed 0:1387ff3eed4a 508 /* One round of Salsa20/8.
sPymbed 0:1387ff3eed4a 509 * Code taken from RFC 7914: scrypt PBKDF.
sPymbed 0:1387ff3eed4a 510 *
sPymbed 0:1387ff3eed4a 511 * out Output buffer.
sPymbed 0:1387ff3eed4a 512 * in Input data to hash.
sPymbed 0:1387ff3eed4a 513 */
sPymbed 0:1387ff3eed4a 514 static void scryptSalsa(word32* out, word32* in)
sPymbed 0:1387ff3eed4a 515 {
sPymbed 0:1387ff3eed4a 516 int i;
sPymbed 0:1387ff3eed4a 517 word32 x[16];
sPymbed 0:1387ff3eed4a 518
sPymbed 0:1387ff3eed4a 519 #ifdef LITTLE_ENDIAN_ORDER
sPymbed 0:1387ff3eed4a 520 for (i = 0; i < 16; ++i)
sPymbed 0:1387ff3eed4a 521 x[i] = in[i];
sPymbed 0:1387ff3eed4a 522 #else
sPymbed 0:1387ff3eed4a 523 for (i = 0; i < 16; i++)
sPymbed 0:1387ff3eed4a 524 x[i] = ByteReverseWord32(in[i]);
sPymbed 0:1387ff3eed4a 525 #endif
sPymbed 0:1387ff3eed4a 526 for (i = 8; i > 0; i -= 2) {
sPymbed 0:1387ff3eed4a 527 x[ 4] ^= R(x[ 0] + x[12], 7); x[ 8] ^= R(x[ 4] + x[ 0], 9);
sPymbed 0:1387ff3eed4a 528 x[12] ^= R(x[ 8] + x[ 4], 13); x[ 0] ^= R(x[12] + x[ 8], 18);
sPymbed 0:1387ff3eed4a 529 x[ 9] ^= R(x[ 5] + x[ 1], 7); x[13] ^= R(x[ 9] + x[ 5], 9);
sPymbed 0:1387ff3eed4a 530 x[ 1] ^= R(x[13] + x[ 9], 13); x[ 5] ^= R(x[ 1] + x[13], 18);
sPymbed 0:1387ff3eed4a 531 x[14] ^= R(x[10] + x[ 6], 7); x[ 2] ^= R(x[14] + x[10], 9);
sPymbed 0:1387ff3eed4a 532 x[ 6] ^= R(x[ 2] + x[14], 13); x[10] ^= R(x[ 6] + x[ 2], 18);
sPymbed 0:1387ff3eed4a 533 x[ 3] ^= R(x[15] + x[11], 7); x[ 7] ^= R(x[ 3] + x[15], 9);
sPymbed 0:1387ff3eed4a 534 x[11] ^= R(x[ 7] + x[ 3], 13); x[15] ^= R(x[11] + x[ 7], 18);
sPymbed 0:1387ff3eed4a 535 x[ 1] ^= R(x[ 0] + x[ 3], 7); x[ 2] ^= R(x[ 1] + x[ 0], 9);
sPymbed 0:1387ff3eed4a 536 x[ 3] ^= R(x[ 2] + x[ 1], 13); x[ 0] ^= R(x[ 3] + x[ 2], 18);
sPymbed 0:1387ff3eed4a 537 x[ 6] ^= R(x[ 5] + x[ 4], 7); x[ 7] ^= R(x[ 6] + x[ 5], 9);
sPymbed 0:1387ff3eed4a 538 x[ 4] ^= R(x[ 7] + x[ 6], 13); x[ 5] ^= R(x[ 4] + x[ 7], 18);
sPymbed 0:1387ff3eed4a 539 x[11] ^= R(x[10] + x[ 9], 7); x[ 8] ^= R(x[11] + x[10], 9);
sPymbed 0:1387ff3eed4a 540 x[ 9] ^= R(x[ 8] + x[11], 13); x[10] ^= R(x[ 9] + x[ 8], 18);
sPymbed 0:1387ff3eed4a 541 x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9);
sPymbed 0:1387ff3eed4a 542 x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18);
sPymbed 0:1387ff3eed4a 543 }
sPymbed 0:1387ff3eed4a 544 #ifdef LITTLE_ENDIAN_ORDER
sPymbed 0:1387ff3eed4a 545 for (i = 0; i < 16; ++i)
sPymbed 0:1387ff3eed4a 546 out[i] = in[i] + x[i];
sPymbed 0:1387ff3eed4a 547 #else
sPymbed 0:1387ff3eed4a 548 for (i = 0; i < 16; i++)
sPymbed 0:1387ff3eed4a 549 out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]);
sPymbed 0:1387ff3eed4a 550 #endif
sPymbed 0:1387ff3eed4a 551 }
sPymbed 0:1387ff3eed4a 552
sPymbed 0:1387ff3eed4a 553 /* Mix a block using Salsa20/8.
sPymbed 0:1387ff3eed4a 554 * Based on RFC 7914: scrypt PBKDF.
sPymbed 0:1387ff3eed4a 555 *
sPymbed 0:1387ff3eed4a 556 * b Blocks to mix.
sPymbed 0:1387ff3eed4a 557 * y Temporary storage.
sPymbed 0:1387ff3eed4a 558 * r Size of the block.
sPymbed 0:1387ff3eed4a 559 */
sPymbed 0:1387ff3eed4a 560 static void scryptBlockMix(byte* b, byte* y, int r)
sPymbed 0:1387ff3eed4a 561 {
sPymbed 0:1387ff3eed4a 562 byte x[64];
sPymbed 0:1387ff3eed4a 563 #ifdef WORD64_AVAILABLE
sPymbed 0:1387ff3eed4a 564 word64* b64 = (word64*)b;
sPymbed 0:1387ff3eed4a 565 word64* y64 = (word64*)y;
sPymbed 0:1387ff3eed4a 566 word64* x64 = (word64*)x;
sPymbed 0:1387ff3eed4a 567 #else
sPymbed 0:1387ff3eed4a 568 word32* b32 = (word32*)b;
sPymbed 0:1387ff3eed4a 569 word32* y32 = (word32*)y;
sPymbed 0:1387ff3eed4a 570 word32* x32 = (word32*)x;
sPymbed 0:1387ff3eed4a 571 #endif
sPymbed 0:1387ff3eed4a 572 int i;
sPymbed 0:1387ff3eed4a 573 int j;
sPymbed 0:1387ff3eed4a 574
sPymbed 0:1387ff3eed4a 575 /* Step 1. */
sPymbed 0:1387ff3eed4a 576 XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x));
sPymbed 0:1387ff3eed4a 577 /* Step 2. */
sPymbed 0:1387ff3eed4a 578 for (i = 0; i < 2 * r; i++)
sPymbed 0:1387ff3eed4a 579 {
sPymbed 0:1387ff3eed4a 580 #ifdef WORD64_AVAILABLE
sPymbed 0:1387ff3eed4a 581 for (j = 0; j < 8; j++)
sPymbed 0:1387ff3eed4a 582 x64[j] ^= b64[i * 8 + j];
sPymbed 0:1387ff3eed4a 583 #else
sPymbed 0:1387ff3eed4a 584 for (j = 0; j < 16; j++)
sPymbed 0:1387ff3eed4a 585 x32[j] ^= b32[i * 16 + j];
sPymbed 0:1387ff3eed4a 586 #endif
sPymbed 0:1387ff3eed4a 587 scryptSalsa((word32*)x, (word32*)x);
sPymbed 0:1387ff3eed4a 588 XMEMCPY(y + i * 64, x, sizeof(x));
sPymbed 0:1387ff3eed4a 589 }
sPymbed 0:1387ff3eed4a 590 /* Step 3. */
sPymbed 0:1387ff3eed4a 591 for (i = 0; i < r; i++) {
sPymbed 0:1387ff3eed4a 592 #ifdef WORD64_AVAILABLE
sPymbed 0:1387ff3eed4a 593 for (j = 0; j < 8; j++) {
sPymbed 0:1387ff3eed4a 594 b64[i * 8 + j] = y64[2 * i * 8 + j];
sPymbed 0:1387ff3eed4a 595 b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j];
sPymbed 0:1387ff3eed4a 596 }
sPymbed 0:1387ff3eed4a 597 #else
sPymbed 0:1387ff3eed4a 598 for (j = 0; j < 16; j++) {
sPymbed 0:1387ff3eed4a 599 b32[i * 16 + j] = y32[2 * i * 16 + j];
sPymbed 0:1387ff3eed4a 600 b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j];
sPymbed 0:1387ff3eed4a 601 }
sPymbed 0:1387ff3eed4a 602 #endif
sPymbed 0:1387ff3eed4a 603 }
sPymbed 0:1387ff3eed4a 604 }
sPymbed 0:1387ff3eed4a 605
sPymbed 0:1387ff3eed4a 606 /* Random oracles mix.
sPymbed 0:1387ff3eed4a 607 * Based on RFC 7914: scrypt PBKDF.
sPymbed 0:1387ff3eed4a 608 *
sPymbed 0:1387ff3eed4a 609 * x Data to mix.
sPymbed 0:1387ff3eed4a 610 * v Temporary buffer.
sPymbed 0:1387ff3eed4a 611 * y Temporary buffer for the block mix.
sPymbed 0:1387ff3eed4a 612 * r Block size parameter.
sPymbed 0:1387ff3eed4a 613 * n CPU/Memory cost parameter.
sPymbed 0:1387ff3eed4a 614 */
sPymbed 0:1387ff3eed4a 615 static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
sPymbed 0:1387ff3eed4a 616 {
sPymbed 0:1387ff3eed4a 617 word32 i;
sPymbed 0:1387ff3eed4a 618 word32 j;
sPymbed 0:1387ff3eed4a 619 word32 k;
sPymbed 0:1387ff3eed4a 620 word32 bSz = 128 * r;
sPymbed 0:1387ff3eed4a 621 #ifdef WORD64_AVAILABLE
sPymbed 0:1387ff3eed4a 622 word64* x64 = (word64*)x;
sPymbed 0:1387ff3eed4a 623 word64* v64 = (word64*)v;
sPymbed 0:1387ff3eed4a 624 #else
sPymbed 0:1387ff3eed4a 625 word32* x32 = (word32*)x;
sPymbed 0:1387ff3eed4a 626 word32* v32 = (word32*)v;
sPymbed 0:1387ff3eed4a 627 #endif
sPymbed 0:1387ff3eed4a 628
sPymbed 0:1387ff3eed4a 629 /* Step 1. X = B (B not needed therefore not implemented) */
sPymbed 0:1387ff3eed4a 630 /* Step 2. */
sPymbed 0:1387ff3eed4a 631 for (i = 0; i < n; i++)
sPymbed 0:1387ff3eed4a 632 {
sPymbed 0:1387ff3eed4a 633 XMEMCPY(v + i * bSz, x, bSz);
sPymbed 0:1387ff3eed4a 634 scryptBlockMix(x, y, r);
sPymbed 0:1387ff3eed4a 635 }
sPymbed 0:1387ff3eed4a 636
sPymbed 0:1387ff3eed4a 637 /* Step 3. */
sPymbed 0:1387ff3eed4a 638 for (i = 0; i < n; i++)
sPymbed 0:1387ff3eed4a 639 {
sPymbed 0:1387ff3eed4a 640 #ifdef LITTLE_ENDIAN_ORDER
sPymbed 0:1387ff3eed4a 641 #ifdef WORD64_AVAILABLE
sPymbed 0:1387ff3eed4a 642 j = *(word64*)(x + (2*r - 1) * 64) & (n-1);
sPymbed 0:1387ff3eed4a 643 #else
sPymbed 0:1387ff3eed4a 644 j = *(word32*)(x + (2*r - 1) * 64) & (n-1);
sPymbed 0:1387ff3eed4a 645 #endif
sPymbed 0:1387ff3eed4a 646 #else
sPymbed 0:1387ff3eed4a 647 byte* t = x + (2*r - 1) * 64;
sPymbed 0:1387ff3eed4a 648 j = (t[0] | (t[1] << 8) | (t[2] << 16) | ((word32)t[3] << 24)) & (n-1);
sPymbed 0:1387ff3eed4a 649 #endif
sPymbed 0:1387ff3eed4a 650 #ifdef WORD64_AVAILABLE
sPymbed 0:1387ff3eed4a 651 for (k = 0; k < bSz / 8; k++)
sPymbed 0:1387ff3eed4a 652 x64[k] ^= v64[j * bSz / 8 + k];
sPymbed 0:1387ff3eed4a 653 #else
sPymbed 0:1387ff3eed4a 654 for (k = 0; k < bSz / 4; k++)
sPymbed 0:1387ff3eed4a 655 x32[k] ^= v32[j * bSz / 4 + k];
sPymbed 0:1387ff3eed4a 656 #endif
sPymbed 0:1387ff3eed4a 657 scryptBlockMix(x, y, r);
sPymbed 0:1387ff3eed4a 658 }
sPymbed 0:1387ff3eed4a 659 /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
sPymbed 0:1387ff3eed4a 660 }
sPymbed 0:1387ff3eed4a 661
sPymbed 0:1387ff3eed4a 662 /* Generates an key derived from a password and salt using a memory hard
sPymbed 0:1387ff3eed4a 663 * algorithm.
sPymbed 0:1387ff3eed4a 664 * Implements RFC 7914: scrypt PBKDF.
sPymbed 0:1387ff3eed4a 665 *
sPymbed 0:1387ff3eed4a 666 * output The derived key.
sPymbed 0:1387ff3eed4a 667 * passwd The password to derive key from.
sPymbed 0:1387ff3eed4a 668 * passLen The length of the password.
sPymbed 0:1387ff3eed4a 669 * salt The key specific data.
sPymbed 0:1387ff3eed4a 670 * saltLen The length of the salt data.
sPymbed 0:1387ff3eed4a 671 * cost The CPU/memory cost parameter. Range: 1..(128*r/8-1)
sPymbed 0:1387ff3eed4a 672 * (Iterations = 2^cost)
sPymbed 0:1387ff3eed4a 673 * blockSize The number of 128 byte octets in a working block.
sPymbed 0:1387ff3eed4a 674 * parallel The number of parallel mix operations to perform.
sPymbed 0:1387ff3eed4a 675 * (Note: this implementation does not use threads.)
sPymbed 0:1387ff3eed4a 676 * dkLen The length of the derived key in bytes.
sPymbed 0:1387ff3eed4a 677 * returns BAD_FUNC_ARG when: parallel not 1, blockSize is too large for cost.
sPymbed 0:1387ff3eed4a 678 */
sPymbed 0:1387ff3eed4a 679 int wc_scrypt(byte* output, const byte* passwd, int passLen,
sPymbed 0:1387ff3eed4a 680 const byte* salt, int saltLen, int cost, int blockSize,
sPymbed 0:1387ff3eed4a 681 int parallel, int dkLen)
sPymbed 0:1387ff3eed4a 682 {
sPymbed 0:1387ff3eed4a 683 int ret = 0;
sPymbed 0:1387ff3eed4a 684 int i;
sPymbed 0:1387ff3eed4a 685 byte* v = NULL;
sPymbed 0:1387ff3eed4a 686 byte* y = NULL;
sPymbed 0:1387ff3eed4a 687 byte* blocks = NULL;
sPymbed 0:1387ff3eed4a 688 word32 blocksSz;
sPymbed 0:1387ff3eed4a 689 word32 bSz;
sPymbed 0:1387ff3eed4a 690
sPymbed 0:1387ff3eed4a 691 if (blockSize > 8)
sPymbed 0:1387ff3eed4a 692 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 693
sPymbed 0:1387ff3eed4a 694 if (cost < 1 || cost >= 128 * blockSize / 8)
sPymbed 0:1387ff3eed4a 695 return BAD_FUNC_ARG;
sPymbed 0:1387ff3eed4a 696
sPymbed 0:1387ff3eed4a 697 bSz = 128 * blockSize;
sPymbed 0:1387ff3eed4a 698 blocksSz = bSz * parallel;
sPymbed 0:1387ff3eed4a 699 blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 700 if (blocks == NULL)
sPymbed 0:1387ff3eed4a 701 goto end;
sPymbed 0:1387ff3eed4a 702 /* Temporary for scryptROMix. */
sPymbed 0:1387ff3eed4a 703 v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 704 if (v == NULL)
sPymbed 0:1387ff3eed4a 705 goto end;
sPymbed 0:1387ff3eed4a 706 /* Temporary for scryptBlockMix. */
sPymbed 0:1387ff3eed4a 707 y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 708 if (y == NULL)
sPymbed 0:1387ff3eed4a 709 goto end;
sPymbed 0:1387ff3eed4a 710
sPymbed 0:1387ff3eed4a 711 /* Step 1. */
sPymbed 0:1387ff3eed4a 712 ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz,
sPymbed 0:1387ff3eed4a 713 WC_SHA256);
sPymbed 0:1387ff3eed4a 714 if (ret != 0)
sPymbed 0:1387ff3eed4a 715 goto end;
sPymbed 0:1387ff3eed4a 716
sPymbed 0:1387ff3eed4a 717 /* Step 2. */
sPymbed 0:1387ff3eed4a 718 for (i = 0; i < parallel; i++)
sPymbed 0:1387ff3eed4a 719 scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost);
sPymbed 0:1387ff3eed4a 720
sPymbed 0:1387ff3eed4a 721 /* Step 3. */
sPymbed 0:1387ff3eed4a 722 ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen,
sPymbed 0:1387ff3eed4a 723 WC_SHA256);
sPymbed 0:1387ff3eed4a 724 end:
sPymbed 0:1387ff3eed4a 725 if (blocks != NULL)
sPymbed 0:1387ff3eed4a 726 XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 727 if (v != NULL)
sPymbed 0:1387ff3eed4a 728 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 729 if (y != NULL)
sPymbed 0:1387ff3eed4a 730 XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 0:1387ff3eed4a 731
sPymbed 0:1387ff3eed4a 732 return ret;
sPymbed 0:1387ff3eed4a 733 }
sPymbed 0:1387ff3eed4a 734 #endif
sPymbed 0:1387ff3eed4a 735
sPymbed 0:1387ff3eed4a 736 #undef WC_MAX_DIGEST_SIZE
sPymbed 0:1387ff3eed4a 737
sPymbed 0:1387ff3eed4a 738 #endif /* NO_PWDBASED */
sPymbed 0:1387ff3eed4a 739
sPymbed 0:1387ff3eed4a 740