• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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