1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_SCRYPT
18
19 #include <stdint.h>
20 #include "securec.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_sal.h"
23 #include "crypt_local_types.h"
24 #include "crypt_errno.h"
25 #include "crypt_utils.h"
26 #include "crypt_types.h"
27 #include "crypt_scrypt.h"
28 #include "eal_mac_local.h"
29 #include "pbkdf2_local.h"
30 #include "bsl_params.h"
31 #include "crypt_params_key.h"
32
33 #define SCRYPT_PR_MAX ((1 << 30) - 1)
34
35 // Convert the little-endian array to the host order.
36 #define SALSA_INPUT_TO_HOST(T, x) \
37 do { \
38 (x)[0] = CRYPT_LE32TOH((T)[0]); \
39 (x)[1] = CRYPT_LE32TOH((T)[1]); \
40 (x)[2] = CRYPT_LE32TOH((T)[2]); \
41 (x)[3] = CRYPT_LE32TOH((T)[3]); \
42 (x)[4] = CRYPT_LE32TOH((T)[4]); \
43 (x)[5] = CRYPT_LE32TOH((T)[5]); \
44 (x)[6] = CRYPT_LE32TOH((T)[6]); \
45 (x)[7] = CRYPT_LE32TOH((T)[7]); \
46 (x)[8] = CRYPT_LE32TOH((T)[8]); \
47 (x)[9] = CRYPT_LE32TOH((T)[9]); \
48 (x)[10] = CRYPT_LE32TOH((T)[10]); \
49 (x)[11] = CRYPT_LE32TOH((T)[11]); \
50 (x)[12] = CRYPT_LE32TOH((T)[12]); \
51 (x)[13] = CRYPT_LE32TOH((T)[13]); \
52 (x)[14] = CRYPT_LE32TOH((T)[14]); \
53 (x)[15] = CRYPT_LE32TOH((T)[15]); \
54 } while (0)
55
56 // Convert the host order to little endian order.
57 #define SALSA_OUTPUT_TO_LE32(T, x) \
58 do { \
59 (T)[0] = CRYPT_HTOLE32((x)[0] + CRYPT_LE32TOH((T)[0])); \
60 (T)[1] = CRYPT_HTOLE32((x)[1] + CRYPT_LE32TOH((T)[1])); \
61 (T)[2] = CRYPT_HTOLE32((x)[2] + CRYPT_LE32TOH((T)[2])); \
62 (T)[3] = CRYPT_HTOLE32((x)[3] + CRYPT_LE32TOH((T)[3])); \
63 (T)[4] = CRYPT_HTOLE32((x)[4] + CRYPT_LE32TOH((T)[4])); \
64 (T)[5] = CRYPT_HTOLE32((x)[5] + CRYPT_LE32TOH((T)[5])); \
65 (T)[6] = CRYPT_HTOLE32((x)[6] + CRYPT_LE32TOH((T)[6])); \
66 (T)[7] = CRYPT_HTOLE32((x)[7] + CRYPT_LE32TOH((T)[7])); \
67 (T)[8] = CRYPT_HTOLE32((x)[8] + CRYPT_LE32TOH((T)[8])); \
68 (T)[9] = CRYPT_HTOLE32((x)[9] + CRYPT_LE32TOH((T)[9])); \
69 (T)[10] = CRYPT_HTOLE32((x)[10] + CRYPT_LE32TOH((T)[10])); \
70 (T)[11] = CRYPT_HTOLE32((x)[11] + CRYPT_LE32TOH((T)[11])); \
71 (T)[12] = CRYPT_HTOLE32((x)[12] + CRYPT_LE32TOH((T)[12])); \
72 (T)[13] = CRYPT_HTOLE32((x)[13] + CRYPT_LE32TOH((T)[13])); \
73 (T)[14] = CRYPT_HTOLE32((x)[14] + CRYPT_LE32TOH((T)[14])); \
74 (T)[15] = CRYPT_HTOLE32((x)[15] + CRYPT_LE32TOH((T)[15])); \
75 } while (0)
76
77 #define SCRYPT_ELEMENTSIZE 64
78
79 struct CryptScryptCtx {
80 const EAL_MacMethod *macMeth;
81 const EAL_MdMethod *mdMeth;
82 PBKDF2_PRF pbkdf2Prf;
83 uint8_t *password;
84 uint32_t passLen;
85 uint8_t *salt;
86 uint32_t saltLen;
87 uint32_t n;
88 uint32_t r;
89 uint32_t p;
90 };
91
92 /* This function is implemented by referring to the RFC standard.
93 For details, see section 3 in https://www.rfc-editor.org/rfc/rfc7914.txt */
SCRYPT_Salsa20WordSpecification(uint32_t t[16])94 static void SCRYPT_Salsa20WordSpecification(uint32_t t[16])
95 {
96 uint32_t x[16];
97
98 SALSA_INPUT_TO_HOST(t, x);
99
100 for (int i = 0; i < 4; i++) {
101 x[4] ^= ROTL32(x[0] + x[12], 7);
102 x[8] ^= ROTL32(x[4] + x[0], 9);
103 x[12] ^= ROTL32(x[8] + x[4], 13);
104 x[0] ^= ROTL32(x[12] + x[8], 18);
105 x[9] ^= ROTL32(x[5] + x[1], 7);
106 x[13] ^= ROTL32(x[9] + x[5], 9);
107 x[1] ^= ROTL32(x[13] + x[9], 13);
108 x[5] ^= ROTL32(x[1] + x[13], 18);
109 x[14] ^= ROTL32(x[10] + x[6], 7);
110 x[2] ^= ROTL32(x[14] + x[10], 9);
111 x[6] ^= ROTL32(x[2] + x[14], 13);
112 x[10] ^= ROTL32(x[6] + x[2], 18);
113 x[3] ^= ROTL32(x[15] + x[11], 7);
114 x[7] ^= ROTL32(x[3] + x[15], 9);
115 x[11] ^= ROTL32(x[7] + x[3], 13);
116 x[15] ^= ROTL32(x[11] + x[7], 18);
117 x[1] ^= ROTL32(x[0] + x[3], 7);
118 x[2] ^= ROTL32(x[1] + x[0], 9);
119 x[3] ^= ROTL32(x[2] + x[1], 13);
120 x[0] ^= ROTL32(x[3] + x[2], 18);
121 x[6] ^= ROTL32(x[5] + x[4], 7);
122 x[7] ^= ROTL32(x[6] + x[5], 9);
123 x[4] ^= ROTL32(x[7] + x[6], 13);
124 x[5] ^= ROTL32(x[4] + x[7], 18);
125 x[11] ^= ROTL32(x[10] + x[9], 7);
126 x[8] ^= ROTL32(x[11] + x[10], 9);
127 x[9] ^= ROTL32(x[8] + x[11], 13);
128 x[10] ^= ROTL32(x[9] + x[8], 18);
129 x[12] ^= ROTL32(x[15] + x[14], 7);
130 x[13] ^= ROTL32(x[12] + x[15], 9);
131 x[14] ^= ROTL32(x[13] + x[12], 13);
132 x[15] ^= ROTL32(x[14] + x[13], 18);
133 }
134 SALSA_OUTPUT_TO_LE32(t, x);
135 }
136
SCRYPT_BlockMix(uint8_t * b,uint8_t * y,uint32_t r)137 static void SCRYPT_BlockMix(uint8_t *b, uint8_t *y, uint32_t r)
138 {
139 uint8_t *bTmp = b;
140 uint8_t *y0 = y;
141 uint8_t *y1 = y + (r << 6);
142
143 /* RFC7914 section 4
144 In this implementation, the output Y is split and processed separately based on the description in section 4.
145 The performance is slightly improved.
146 1. B' = Y, Y0 = Y, Y1 = Y[r], b=B,
147 The block size of each Y is 64 bytes. The processing unit in this function is 64 bytes.
148 2. Y0 = B[2 * r - 1] ^ B[0]
149 Salsa(Y0)
150 Y1 = Y0 ^ B[1]
151 Salsa(Y1)
152 3. for i = 1 to r -1 do
153 b += 2 // Two blocks have been processed in step 2.
154 Y0 += 1 // Process the next block of Y0.
155 Y0 = b[0] ^ Y1
156 Salsa(Y0)
157 Y1 += 1
158 Y1 = b[1] ^ Y0
159 Salsa(Y1)
160 4. B = Y // Copy Y to B.
161 */
162
163 // r << 7 is equal to r * 128, where r * 128 is the block size of the algorithm.
164 DATA32_XOR(b + (r << 7) - SCRYPT_ELEMENTSIZE, bTmp, y0, SCRYPT_ELEMENTSIZE);
165 SCRYPT_Salsa20WordSpecification((uint32_t*)y0);
166 DATA32_XOR(y0, bTmp + SCRYPT_ELEMENTSIZE, y1, SCRYPT_ELEMENTSIZE);
167 SCRYPT_Salsa20WordSpecification((uint32_t*)y1);
168
169 for (uint32_t i = 1; i < r; i++) {
170 bTmp += 128; // Process two pieces of 64-bit(SCRYPT_ELEMENTSIZE) data in one cycle. 64 * 2 = 128
171
172 y0 += SCRYPT_ELEMENTSIZE;
173 DATA32_XOR(y1, bTmp, y0, SCRYPT_ELEMENTSIZE);
174 SCRYPT_Salsa20WordSpecification((uint32_t*)y0);
175
176 y1 += SCRYPT_ELEMENTSIZE;
177 DATA32_XOR(y0, bTmp + SCRYPT_ELEMENTSIZE, y1, SCRYPT_ELEMENTSIZE);
178 SCRYPT_Salsa20WordSpecification((uint32_t*)y1);
179 }
180
181 (void)memcpy_s(b, r << 7, y, r << 7); // Length bit r of B and y: r << 7
182 }
183
184 /* For details about this function, see section 5 in RFC7914 */
SCRYPT_ROMix(uint8_t * b,uint32_t n,uint32_t r,uint8_t * v,uint8_t * y)185 static void SCRYPT_ROMix(uint8_t *b, uint32_t n, uint32_t r, uint8_t *v, uint8_t *y)
186 {
187 uint32_t i;
188 uint8_t *tmp = NULL;
189 uint32_t blockSize = r << 7;
190
191 for (i = 0, tmp = v; i < n; i++, tmp += blockSize) {
192 (void)memcpy_s(tmp, blockSize, b, blockSize);
193 SCRYPT_BlockMix(b, y, r);
194 }
195
196 for (i = 0; i < n; i++) {
197 uint32_t j = GET_UINT32_LE(b, blockSize - 64) & (n - 1);
198
199 // X= B, X = X ^ Vj
200 DATA32_XOR(b, &v[j * blockSize], b, blockSize);
201 SCRYPT_BlockMix(b, y, r);
202 }
203 }
204
SCRYPT_CheckParam(uint32_t n,uint32_t r,uint32_t p,const uint8_t * out,uint32_t len)205 static int32_t SCRYPT_CheckParam(uint32_t n, uint32_t r, uint32_t p, const uint8_t *out, uint32_t len)
206 {
207 if (r == 0 || p == 0 || n <= 1 || ((n & (n - 1)) != 0)) {
208 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
209 return CRYPT_SCRYPT_PARAM_ERROR;
210 }
211 if (p > SCRYPT_PR_MAX / r) {
212 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
213 return CRYPT_SCRYPT_PARAM_ERROR;
214 }
215 /* r <= 3 indicates 16 * r < (sizeof(uint64_t) * 8 - 1) */
216 if ((r <= 3) && (n >= (((uint64_t)1) << (16 * r)))) {
217 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
218 return CRYPT_SCRYPT_PARAM_ERROR;
219 }
220 /* (p * 128 * r < UINT32_MAX) && (32 * r * n * sizeof(uint32_t)) */
221 if ((r > ((UINT32_MAX / 128) / p)) || (n > ((UINT32_MAX / 128) / r))) {
222 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
223 return CRYPT_SCRYPT_PARAM_ERROR;
224 }
225 if (out == NULL || len == 0) {
226 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
227 return CRYPT_SCRYPT_PARAM_ERROR;
228 }
229
230 return CRYPT_SUCCESS;
231 }
232
SCRYPT_CheckPointer(PBKDF2_PRF pbkdf2Prf,const uint8_t * key,uint32_t keyLen,const uint8_t * salt,uint32_t saltLen)233 static int32_t SCRYPT_CheckPointer(PBKDF2_PRF pbkdf2Prf, const uint8_t *key, uint32_t keyLen,
234 const uint8_t *salt, uint32_t saltLen)
235 {
236 if (pbkdf2Prf == NULL) {
237 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
238 return CRYPT_NULL_INPUT;
239 }
240 if (key == NULL && keyLen > 0) {
241 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
242 return CRYPT_NULL_INPUT;
243 }
244 if (salt == NULL && saltLen > 0) {
245 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
246 return CRYPT_NULL_INPUT;
247 }
248 return CRYPT_SUCCESS;
249 }
250
251 /* For details about this function, see section 6 in RFC7914. */
CRYPT_SCRYPT(PBKDF2_PRF pbkdf2Prf,const EAL_MacMethod * macMeth,CRYPT_MAC_AlgId macId,const EAL_MdMethod * mdMeth,const uint8_t * key,uint32_t keyLen,const uint8_t * salt,uint32_t saltLen,uint32_t n,uint32_t r,uint32_t p,uint8_t * out,uint32_t len)252 int32_t CRYPT_SCRYPT(PBKDF2_PRF pbkdf2Prf, const EAL_MacMethod *macMeth, CRYPT_MAC_AlgId macId,
253 const EAL_MdMethod *mdMeth, const uint8_t *key, uint32_t keyLen, const uint8_t *salt,
254 uint32_t saltLen, uint32_t n, uint32_t r, uint32_t p, uint8_t *out, uint32_t len)
255 {
256 int32_t ret;
257 // V in ROMix and BlockMix is allocated here, reducing memory application and release costs
258 uint8_t *b = NULL, *v = NULL, *bi = NULL, *y = NULL;
259 uint32_t bLen, blockSize, sumLen;
260
261 if ((ret = SCRYPT_CheckParam(n, r, p, out, len)) != CRYPT_SUCCESS) {
262 BSL_ERR_PUSH_ERROR(ret);
263 return ret;
264 }
265 if ((ret = SCRYPT_CheckPointer(pbkdf2Prf, key, keyLen, salt, saltLen)) != CRYPT_SUCCESS) {
266 BSL_ERR_PUSH_ERROR(ret);
267 return ret;
268 }
269
270 blockSize = r << 7; // block length: r << 7 (r * 128)
271 bLen = blockSize * p;
272
273 sumLen = bLen + blockSize * n + blockSize;
274 if (sumLen < bLen) {
275 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_DATA_TOO_MAX);
276 return CRYPT_SCRYPT_DATA_TOO_MAX;
277 }
278 b = BSL_SAL_Malloc(sumLen);
279 if (b == NULL) {
280 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
281 return CRYPT_MEM_ALLOC_FAIL;
282 }
283
284 v = b + bLen;
285 y = v + blockSize * n;
286
287 GOTO_ERR_IF(pbkdf2Prf(macMeth, macId, mdMeth, key, keyLen, salt, saltLen, 1, b, bLen), ret);
288
289 bi = b;
290 for (uint32_t i = 0; i < p; i++, bi += blockSize) {
291 SCRYPT_ROMix(bi, n, r, v, y);
292 }
293
294 GOTO_ERR_IF(pbkdf2Prf(macMeth, macId, mdMeth, key, keyLen, b, bLen, 1, out, len), ret);
295
296 ERR:
297 BSL_SAL_FREE(b);
298
299 return ret;
300 }
301
CRYPT_SCRYPT_SetMacMethod(CRYPT_SCRYPT_Ctx * ctx)302 int32_t CRYPT_SCRYPT_SetMacMethod(CRYPT_SCRYPT_Ctx *ctx)
303 {
304 EAL_MacMethLookup method;
305 int32_t ret = EAL_MacFindMethod(CRYPT_MAC_HMAC_SHA256, &method);
306 if (ret != CRYPT_SUCCESS) {
307 BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_METH_NULL_NUMBER);
308 return CRYPT_EAL_ERR_METH_NULL_NUMBER;
309 }
310 ctx->macMeth = method.macMethod;
311 ctx->mdMeth = method.md;
312 return CRYPT_SUCCESS;
313 }
314
CRYPT_SCRYPT_InitCtx(CRYPT_SCRYPT_Ctx * ctx)315 int32_t CRYPT_SCRYPT_InitCtx(CRYPT_SCRYPT_Ctx *ctx)
316 {
317 int32_t ret = CRYPT_SCRYPT_SetMacMethod(ctx);
318 if (ret != CRYPT_SUCCESS) {
319 BSL_ERR_PUSH_ERROR(ret);
320 return ret;
321 }
322 ctx->pbkdf2Prf = CRYPT_PBKDF2_HMAC;
323 return CRYPT_SUCCESS;
324 }
325
CRYPT_SCRYPT_NewCtx(void)326 CRYPT_SCRYPT_Ctx* CRYPT_SCRYPT_NewCtx(void)
327 {
328 CRYPT_SCRYPT_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_SCRYPT_Ctx));
329 if (ctx == NULL) {
330 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
331 return NULL;
332 }
333 int32_t ret = CRYPT_SCRYPT_InitCtx(ctx);
334 if (ret != CRYPT_SUCCESS) {
335 BSL_ERR_PUSH_ERROR(ret);
336 BSL_SAL_FREE(ctx);
337 return NULL;
338 }
339 return ctx;
340 }
341
CRYPT_SCRYPT_SetPassWord(CRYPT_SCRYPT_Ctx * ctx,const uint8_t * password,uint32_t passLen)342 int32_t CRYPT_SCRYPT_SetPassWord(CRYPT_SCRYPT_Ctx *ctx, const uint8_t *password, uint32_t passLen)
343 {
344 if (password == NULL && passLen > 0) {
345 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
346 return CRYPT_NULL_INPUT;
347 }
348
349 BSL_SAL_ClearFree(ctx->password, ctx->passLen);
350
351 ctx->password = BSL_SAL_Dump(password, passLen);
352 if (ctx->password == NULL && passLen > 0) {
353 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
354 return CRYPT_MEM_ALLOC_FAIL;
355 }
356 ctx->passLen = passLen;
357 return CRYPT_SUCCESS;
358 }
359
CRYPT_SCRYPT_SetSalt(CRYPT_SCRYPT_Ctx * ctx,const uint8_t * salt,uint32_t saltLen)360 int32_t CRYPT_SCRYPT_SetSalt(CRYPT_SCRYPT_Ctx *ctx, const uint8_t *salt, uint32_t saltLen)
361 {
362 if (salt == NULL && saltLen > 0) {
363 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
364 return CRYPT_NULL_INPUT;
365 }
366
367 BSL_SAL_FREE(ctx->salt);
368
369 ctx->salt = BSL_SAL_Dump(salt, saltLen);
370 if (ctx->salt == NULL && saltLen > 0) {
371 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
372 return CRYPT_MEM_ALLOC_FAIL;
373 }
374 ctx->saltLen = saltLen;
375 return CRYPT_SUCCESS;
376 }
377
CRYPT_SCRYPT_SetN(CRYPT_SCRYPT_Ctx * ctx,const uint32_t n)378 int32_t CRYPT_SCRYPT_SetN(CRYPT_SCRYPT_Ctx *ctx, const uint32_t n)
379 {
380 if (n <= 1 || (n & (n - 1)) != 0) {
381 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
382 return CRYPT_SCRYPT_PARAM_ERROR;
383 }
384 ctx->n = n;
385 return CRYPT_SUCCESS;
386 }
387
CRYPT_SCRYPT_SetR(CRYPT_SCRYPT_Ctx * ctx,const uint32_t r)388 int32_t CRYPT_SCRYPT_SetR(CRYPT_SCRYPT_Ctx *ctx, const uint32_t r)
389 {
390 if (r == 0) {
391 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
392 return CRYPT_SCRYPT_PARAM_ERROR;
393 }
394 ctx->r = r;
395 return CRYPT_SUCCESS;
396 }
397
CRYPT_SCRYPT_SetP(CRYPT_SCRYPT_Ctx * ctx,const uint32_t p)398 int32_t CRYPT_SCRYPT_SetP(CRYPT_SCRYPT_Ctx *ctx, const uint32_t p)
399 {
400 if (p == 0) {
401 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_PARAM_ERROR);
402 return CRYPT_SCRYPT_PARAM_ERROR;
403 }
404 ctx->p = p;
405 return CRYPT_SUCCESS;
406 }
407
CRYPT_SCRYPT_SetParam(CRYPT_SCRYPT_Ctx * ctx,const BSL_Param * param)408 int32_t CRYPT_SCRYPT_SetParam(CRYPT_SCRYPT_Ctx *ctx, const BSL_Param *param)
409 {
410 uint32_t val = 0;
411 uint32_t len = 0;
412 const BSL_Param *temp = NULL;
413 int32_t ret = CRYPT_SCRYPT_PARAM_ERROR;
414 if (ctx == NULL || param == NULL) {
415 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
416 return CRYPT_NULL_INPUT;
417 }
418 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_PASSWORD)) != NULL) {
419 GOTO_ERR_IF(CRYPT_SCRYPT_SetPassWord(ctx, temp->value, temp->valueLen), ret);
420 }
421 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_SALT)) != NULL) {
422 GOTO_ERR_IF(CRYPT_SCRYPT_SetSalt(ctx, temp->value, temp->valueLen), ret);
423 }
424 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_N)) != NULL) {
425 len = sizeof(val);
426 GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_N,
427 BSL_PARAM_TYPE_UINT32, &val, &len), ret);
428 GOTO_ERR_IF(CRYPT_SCRYPT_SetN(ctx, val), ret);
429 }
430 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_R)) != NULL) {
431 len = sizeof(val);
432 GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_R,
433 BSL_PARAM_TYPE_UINT32, &val, &len), ret);
434 GOTO_ERR_IF(CRYPT_SCRYPT_SetR(ctx, val), ret);
435 }
436 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_P)) != NULL) {
437 len = sizeof(val);
438 GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_P,
439 BSL_PARAM_TYPE_UINT32, &val, &len), ret);
440 GOTO_ERR_IF(CRYPT_SCRYPT_SetP(ctx, val), ret);
441 }
442 ERR:
443 return ret;
444 }
445
CRYPT_SCRYPT_Derive(CRYPT_SCRYPT_Ctx * ctx,uint8_t * out,uint32_t len)446 int32_t CRYPT_SCRYPT_Derive(CRYPT_SCRYPT_Ctx *ctx, uint8_t *out, uint32_t len)
447 {
448 int32_t ret;
449
450 uint8_t *b = NULL, *v = NULL, *bi = NULL, *y = NULL;
451 uint32_t bLen, blockSize, sumLen;
452
453 const EAL_MacMethod *macMeth = ctx->macMeth;
454 const EAL_MdMethod *mdMeth = ctx->mdMeth;
455 PBKDF2_PRF pbkdf2Prf = ctx->pbkdf2Prf;
456 const uint8_t *password = ctx->password;
457 uint32_t passLen = ctx->passLen;
458 const uint8_t *salt = ctx->salt;
459 uint32_t saltLen = ctx->saltLen;
460 uint32_t n = ctx->n;
461 uint32_t r = ctx->r;
462 uint32_t p = ctx->p;
463
464 if ((ret = SCRYPT_CheckParam(n, r, p, out, len)) != CRYPT_SUCCESS) {
465 BSL_ERR_PUSH_ERROR(ret);
466 return ret;
467 }
468 if ((ret = SCRYPT_CheckPointer(pbkdf2Prf, password, passLen, salt, saltLen)) != CRYPT_SUCCESS) {
469 BSL_ERR_PUSH_ERROR(ret);
470 return ret;
471 }
472
473 blockSize = r << 7;
474 bLen = blockSize * p;
475
476 sumLen = bLen + blockSize * n + blockSize;
477 if (sumLen < bLen) {
478 BSL_ERR_PUSH_ERROR(CRYPT_SCRYPT_DATA_TOO_MAX);
479 return CRYPT_SCRYPT_DATA_TOO_MAX;
480 }
481 b = BSL_SAL_Malloc(sumLen);
482 if (b == NULL) {
483 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
484 return CRYPT_MEM_ALLOC_FAIL;
485 }
486
487 v = b + bLen;
488 y = v + blockSize * ctx->n;
489
490 GOTO_ERR_IF(pbkdf2Prf(macMeth, CRYPT_MAC_HMAC_SHA256, mdMeth, password, passLen, salt, saltLen, 1, b, bLen), ret);
491
492 bi = b;
493 for (uint32_t i = 0; i < p; i++, bi += blockSize) {
494 SCRYPT_ROMix(bi, n, r, v, y);
495 }
496
497 GOTO_ERR_IF(pbkdf2Prf(macMeth, CRYPT_MAC_HMAC_SHA256, mdMeth, password, passLen, b, bLen, 1, out, len), ret);
498
499 ERR:
500 BSL_SAL_FREE(b);
501
502 return ret;
503 }
504
CRYPT_SCRYPT_Deinit(CRYPT_SCRYPT_Ctx * ctx)505 int32_t CRYPT_SCRYPT_Deinit(CRYPT_SCRYPT_Ctx *ctx)
506 {
507 if (ctx == NULL) {
508 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
509 return CRYPT_NULL_INPUT;
510 }
511 BSL_SAL_ClearFree(ctx->password, ctx->passLen);
512 BSL_SAL_FREE(ctx->salt);
513 (void)memset_s(ctx, sizeof(CRYPT_SCRYPT_Ctx), 0, sizeof(CRYPT_SCRYPT_Ctx));
514
515 int32_t ret = CRYPT_SCRYPT_InitCtx(ctx);
516 if (ret != CRYPT_SUCCESS) {
517 BSL_ERR_PUSH_ERROR(ret);
518 }
519 return ret;
520 }
521
CRYPT_SCRYPT_FreeCtx(CRYPT_SCRYPT_Ctx * ctx)522 void CRYPT_SCRYPT_FreeCtx(CRYPT_SCRYPT_Ctx *ctx)
523 {
524 if (ctx == NULL) {
525 return;
526 }
527 BSL_SAL_ClearFree(ctx->password, ctx->passLen);
528 BSL_SAL_FREE(ctx->salt);
529 BSL_SAL_Free(ctx);
530 }
531
532 #endif /* HITLS_CRYPTO_SCRYPT */
533