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_PBKDF2
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_pbkdf2.h"
27 #include "crypt_algid.h"
28 #include "eal_mac_local.h"
29 #include "crypt_ealinit.h"
30 #include "pbkdf2_local.h"
31 #include "bsl_params.h"
32 #include "crypt_params_key.h"
33
34 #define PBKDF2_MAX_BLOCKSIZE 64
35 #define PBKDF2_MAX_KEYLEN 0xFFFFFFFF
36
37 static const uint32_t PBKDF_ID_LIST[] = {
38 CRYPT_MAC_HMAC_MD5,
39 CRYPT_MAC_HMAC_SHA1,
40 CRYPT_MAC_HMAC_SHA224,
41 CRYPT_MAC_HMAC_SHA256,
42 CRYPT_MAC_HMAC_SHA384,
43 CRYPT_MAC_HMAC_SHA512,
44 CRYPT_MAC_HMAC_SM3,
45 CRYPT_MAC_HMAC_SHA3_224,
46 CRYPT_MAC_HMAC_SHA3_256,
47 CRYPT_MAC_HMAC_SHA3_384,
48 CRYPT_MAC_HMAC_SHA3_512,
49 };
50
51 struct CryptPbkdf2Ctx {
52 CRYPT_MAC_AlgId macId;
53 const EAL_MacMethod *macMeth;
54 const EAL_MdMethod *mdMeth;
55 void *macCtx;
56 uint8_t *password;
57 uint32_t passLen;
58 uint8_t *salt;
59 uint32_t saltLen;
60 uint32_t iterCnt;
61 };
62
CRYPT_PBKDF2_IsValidAlgId(CRYPT_MAC_AlgId id)63 bool CRYPT_PBKDF2_IsValidAlgId(CRYPT_MAC_AlgId id)
64 {
65 return ParamIdIsValid(id, PBKDF_ID_LIST, sizeof(PBKDF_ID_LIST) / sizeof(PBKDF_ID_LIST[0]));
66 }
67
68
CRYPT_PBKDF2_U1(const CRYPT_PBKDF2_Ctx * pCtx,uint32_t blockCount,uint8_t * u,uint32_t * blockSize)69 int32_t CRYPT_PBKDF2_U1(const CRYPT_PBKDF2_Ctx *pCtx, uint32_t blockCount, uint8_t *u, uint32_t *blockSize)
70 {
71 int32_t ret;
72 const EAL_MacMethod *macMeth = pCtx->macMeth;
73 void *macCtx = pCtx->macCtx;
74 (void)macMeth->reinit(macCtx);
75 if ((ret = macMeth->update(macCtx, pCtx->salt, pCtx->saltLen)) != CRYPT_SUCCESS) {
76 BSL_ERR_PUSH_ERROR(ret);
77 return ret;
78 }
79
80 /* processing the big endian */
81 uint32_t blockCnt = CRYPT_HTONL(blockCount);
82 if ((ret = macMeth->update(macCtx, (uint8_t *)&blockCnt, sizeof(blockCnt))) != CRYPT_SUCCESS) {
83 BSL_ERR_PUSH_ERROR(ret);
84 return ret;
85 }
86 if ((ret = macMeth->final(macCtx, u, blockSize)) != CRYPT_SUCCESS) {
87 BSL_ERR_PUSH_ERROR(ret);
88 return ret;
89 }
90 return CRYPT_SUCCESS;
91 }
92
CRYPT_PBKDF2_Un(const CRYPT_PBKDF2_Ctx * pCtx,uint8_t * u,uint32_t * blockSize,uint8_t * t,uint32_t tLen)93 int32_t CRYPT_PBKDF2_Un(const CRYPT_PBKDF2_Ctx *pCtx, uint8_t *u, uint32_t *blockSize, uint8_t *t, uint32_t tLen)
94 {
95 int32_t ret;
96 const EAL_MacMethod *macMeth = pCtx->macMeth;
97 void *macCtx = pCtx->macCtx;
98
99 macMeth->reinit(macCtx);
100 if ((ret = macMeth->update(macCtx, u, *blockSize)) != CRYPT_SUCCESS) {
101 BSL_ERR_PUSH_ERROR(ret);
102 return ret;
103 }
104 if ((ret = macMeth->final(macCtx, u, blockSize)) != CRYPT_SUCCESS) {
105 BSL_ERR_PUSH_ERROR(ret);
106 return ret;
107 }
108 DATA_XOR(t, u, t, tLen);
109 return CRYPT_SUCCESS;
110 }
111
CRYPT_PBKDF2_CalcT(const CRYPT_PBKDF2_Ctx * pCtx,uint32_t blockCount,uint8_t * t,uint32_t * tlen)112 int32_t CRYPT_PBKDF2_CalcT(const CRYPT_PBKDF2_Ctx *pCtx, uint32_t blockCount, uint8_t *t, uint32_t *tlen)
113 {
114 uint8_t u[PBKDF2_MAX_BLOCKSIZE] = {0};
115 uint8_t tmpT[PBKDF2_MAX_BLOCKSIZE] = {0};
116 uint32_t blockSize = PBKDF2_MAX_BLOCKSIZE;
117 int32_t ret;
118 uint32_t iterCnt = pCtx->iterCnt;
119 /* U1 = PRF(Password, Salt + INT_32_BE(i))
120 tmpT = U1 */
121 ret = CRYPT_PBKDF2_U1(pCtx, blockCount, u, &blockSize);
122 if (ret != CRYPT_SUCCESS) {
123 BSL_ERR_PUSH_ERROR(ret);
124 return ret;
125 }
126 (void)memcpy_s(tmpT, PBKDF2_MAX_BLOCKSIZE, u, blockSize);
127 for (uint32_t un = 1; un < iterCnt; un++) {
128 /* t = t ^ Un */
129 ret = CRYPT_PBKDF2_Un(pCtx, u, &blockSize, tmpT, blockSize);
130 if (ret != CRYPT_SUCCESS) {
131 BSL_ERR_PUSH_ERROR(ret);
132 return ret;
133 }
134 }
135 uint32_t len = (*tlen > blockSize) ? blockSize : (*tlen);
136 (void)memcpy_s(t, *tlen, tmpT, len);
137 *tlen = len;
138 BSL_SAL_CleanseData(u, PBKDF2_MAX_BLOCKSIZE);
139 BSL_SAL_CleanseData(tmpT, PBKDF2_MAX_BLOCKSIZE);
140 return CRYPT_SUCCESS;
141 }
142
CRYPT_PBKDF2_GenDk(const CRYPT_PBKDF2_Ctx * pCtx,uint8_t * dk,uint32_t dkLen)143 int32_t CRYPT_PBKDF2_GenDk(const CRYPT_PBKDF2_Ctx *pCtx, uint8_t *dk, uint32_t dkLen)
144 {
145 uint32_t curLen;
146 uint8_t *t = dk;
147 uint32_t tlen;
148 uint32_t i;
149 int32_t ret;
150
151 ret = pCtx->macMeth->init(pCtx->macCtx, pCtx->password, pCtx->passLen, NULL);
152 if (ret != CRYPT_SUCCESS) {
153 BSL_ERR_PUSH_ERROR(ret);
154 return ret;
155 }
156
157 /* DK = T1 + T2 + ⋯ + Tdklen/hlen */
158 for (i = 1, curLen = dkLen; curLen > 0; i++) {
159 tlen = curLen;
160 ret = CRYPT_PBKDF2_CalcT(pCtx, i, t, &tlen);
161 if (ret != CRYPT_SUCCESS) {
162 BSL_ERR_PUSH_ERROR(ret);
163 return ret;
164 }
165 curLen -= tlen;
166 t += tlen;
167 }
168 return CRYPT_SUCCESS;
169 }
170
CRYPT_PBKDF2_HMAC(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 iterCnt,uint8_t * out,uint32_t len)171 int32_t CRYPT_PBKDF2_HMAC(const EAL_MacMethod *macMeth, CRYPT_MAC_AlgId macId, const EAL_MdMethod *mdMeth,
172 const uint8_t *key, uint32_t keyLen,
173 const uint8_t *salt, uint32_t saltLen,
174 uint32_t iterCnt, uint8_t *out, uint32_t len)
175 {
176 int32_t ret;
177 CRYPT_PBKDF2_Ctx pCtx;
178
179 if (macMeth == NULL || mdMeth == NULL || out == NULL) {
180 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
181 return CRYPT_NULL_INPUT;
182 }
183 if (key == NULL && keyLen > 0) {
184 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
185 return CRYPT_NULL_INPUT;
186 }
187 // add keyLen limit based on rfc2898
188 if (mdMeth->mdSize == 0 || (keyLen / mdMeth->mdSize) >= PBKDF2_MAX_KEYLEN) {
189 BSL_ERR_PUSH_ERROR(CRYPT_PBKDF2_PARAM_ERROR);
190 return CRYPT_PBKDF2_PARAM_ERROR;
191 }
192 if (salt == NULL && saltLen > 0) {
193 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
194 return CRYPT_NULL_INPUT;
195 }
196 if ((len == 0) || (iterCnt == 0)) {
197 BSL_ERR_PUSH_ERROR(CRYPT_PBKDF2_PARAM_ERROR);
198 return CRYPT_PBKDF2_PARAM_ERROR;
199 }
200
201 void *macCtx = macMeth->newCtx(macId);
202 if (macCtx == NULL) {
203 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
204 return CRYPT_MEM_ALLOC_FAIL;
205 }
206
207 pCtx.macMeth = macMeth;
208 pCtx.macCtx = macCtx;
209 pCtx.password = (uint8_t *)(uintptr_t)key;
210 pCtx.passLen = keyLen;
211 pCtx.salt = (uint8_t *)(uintptr_t)salt;
212 pCtx.saltLen = saltLen;
213 pCtx.iterCnt = iterCnt;
214 ret = CRYPT_PBKDF2_GenDk(&pCtx, out, len);
215
216 macMeth->deinit(macCtx);
217 macMeth->freeCtx(macCtx);
218 macCtx = NULL;
219 return ret;
220 }
221
CRYPT_PBKDF2_NewCtx(void)222 CRYPT_PBKDF2_Ctx* CRYPT_PBKDF2_NewCtx(void)
223 {
224 CRYPT_PBKDF2_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_PBKDF2_Ctx));
225 if (ctx == NULL) {
226 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
227 return NULL;
228 }
229 return ctx;
230 }
231
CRYPT_PBKDF2_SetMacMethod(CRYPT_PBKDF2_Ctx * ctx,const CRYPT_MAC_AlgId id)232 int32_t CRYPT_PBKDF2_SetMacMethod(CRYPT_PBKDF2_Ctx *ctx, const CRYPT_MAC_AlgId id)
233 {
234 #ifdef HITLS_CRYPTO_ASM_CHECK
235 if (CRYPT_ASMCAP_Mac(id) != CRYPT_SUCCESS) {
236 BSL_ERR_PUSH_ERROR(CRYPT_EAL_ALG_ASM_NOT_SUPPORT);
237 return CRYPT_EAL_ALG_ASM_NOT_SUPPORT;
238 }
239 #endif
240 EAL_MacMethLookup method;
241 if (!CRYPT_PBKDF2_IsValidAlgId(id)) {
242 BSL_ERR_PUSH_ERROR(CRYPT_PBKDF2_PARAM_ERROR);
243 return CRYPT_PBKDF2_PARAM_ERROR;
244 }
245 int32_t ret = EAL_MacFindMethod(id, &method);
246 if (ret != CRYPT_SUCCESS) {
247 BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_METH_NULL_NUMBER);
248 return CRYPT_EAL_ERR_METH_NULL_NUMBER;
249 }
250 ctx->macMeth = method.macMethod;
251 ctx->macId = id;
252 ctx->mdMeth = method.md;
253 return CRYPT_SUCCESS;
254 }
255
CRYPT_PBKDF2_SetPassWord(CRYPT_PBKDF2_Ctx * ctx,const uint8_t * password,uint32_t passLen)256 int32_t CRYPT_PBKDF2_SetPassWord(CRYPT_PBKDF2_Ctx *ctx, const uint8_t *password, uint32_t passLen)
257 {
258 if (password == NULL && passLen > 0) {
259 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
260 return CRYPT_NULL_INPUT;
261 }
262
263 BSL_SAL_ClearFree(ctx->password, ctx->passLen);
264
265 ctx->password = BSL_SAL_Dump(password, passLen);
266 if (ctx->password == NULL && passLen > 0) {
267 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
268 return CRYPT_MEM_ALLOC_FAIL;
269 }
270 ctx->passLen = passLen;
271 return CRYPT_SUCCESS;
272 }
273
CRYPT_PBKDF2_SetSalt(CRYPT_PBKDF2_Ctx * ctx,const uint8_t * salt,uint32_t saltLen)274 int32_t CRYPT_PBKDF2_SetSalt(CRYPT_PBKDF2_Ctx *ctx, const uint8_t *salt, uint32_t saltLen)
275 {
276 if (salt == NULL && saltLen > 0) {
277 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
278 return CRYPT_NULL_INPUT;
279 }
280
281 BSL_SAL_FREE(ctx->salt);
282
283 ctx->salt = BSL_SAL_Dump(salt, saltLen);
284 if (ctx->salt == NULL && saltLen > 0) {
285 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
286 return CRYPT_MEM_ALLOC_FAIL;
287 }
288 ctx->saltLen = saltLen;
289 return CRYPT_SUCCESS;
290 }
291
CRYPT_PBKDF2_SetCnt(CRYPT_PBKDF2_Ctx * ctx,const uint32_t iterCnt)292 int32_t CRYPT_PBKDF2_SetCnt(CRYPT_PBKDF2_Ctx *ctx, const uint32_t iterCnt)
293 {
294 if (iterCnt == 0) {
295 BSL_ERR_PUSH_ERROR(CRYPT_PBKDF2_PARAM_ERROR);
296 return CRYPT_PBKDF2_PARAM_ERROR;
297 }
298 ctx->iterCnt = iterCnt;
299 return CRYPT_SUCCESS;
300 }
301
CRYPT_PBKDF2_SetParam(CRYPT_PBKDF2_Ctx * ctx,const BSL_Param * param)302 int32_t CRYPT_PBKDF2_SetParam(CRYPT_PBKDF2_Ctx *ctx, const BSL_Param *param)
303 {
304 uint32_t val = 0;
305 uint32_t len = 0;
306 const BSL_Param *temp = NULL;
307 int32_t ret = CRYPT_PBKDF2_PARAM_ERROR;
308 if (ctx == NULL || param == NULL) {
309 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
310 return CRYPT_NULL_INPUT;
311 }
312 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_MAC_ID)) != NULL) {
313 len = sizeof(val);
314 GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_MAC_ID,
315 BSL_PARAM_TYPE_UINT32, &val, &len), ret);
316 GOTO_ERR_IF(CRYPT_PBKDF2_SetMacMethod(ctx, val), ret);
317 }
318 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_PASSWORD)) != NULL) {
319 GOTO_ERR_IF(CRYPT_PBKDF2_SetPassWord(ctx, temp->value, temp->valueLen), ret);
320 }
321 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_SALT)) != NULL) {
322 GOTO_ERR_IF(CRYPT_PBKDF2_SetSalt(ctx, temp->value, temp->valueLen), ret);
323 }
324 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_ITER)) != NULL) {
325 len = sizeof(val);
326 GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_ITER,
327 BSL_PARAM_TYPE_UINT32, &val, &len), ret);
328 GOTO_ERR_IF(CRYPT_PBKDF2_SetCnt(ctx, val), ret);
329 }
330 ERR:
331 return ret;
332 }
333
CRYPT_PBKDF2_Derive(CRYPT_PBKDF2_Ctx * ctx,uint8_t * out,uint32_t len)334 int32_t CRYPT_PBKDF2_Derive(CRYPT_PBKDF2_Ctx *ctx, uint8_t *out, uint32_t len)
335 {
336 int32_t ret;
337
338 if (ctx == NULL || ctx->macMeth == NULL || ctx->mdMeth == NULL) {
339 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
340 return CRYPT_NULL_INPUT;
341 }
342 if (out == NULL) {
343 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
344 return CRYPT_NULL_INPUT;
345 }
346 if (ctx->password == NULL && ctx->passLen > 0) {
347 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
348 return CRYPT_NULL_INPUT;
349 }
350 // add keyLen limit based on rfc2898
351 if (ctx->mdMeth->mdSize == 0 || (ctx->passLen / ctx->mdMeth->blockSize) >= PBKDF2_MAX_KEYLEN) {
352 BSL_ERR_PUSH_ERROR(CRYPT_PBKDF2_PARAM_ERROR);
353 return CRYPT_PBKDF2_PARAM_ERROR;
354 }
355 if (ctx->salt == NULL && ctx->saltLen > 0) {
356 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
357 return CRYPT_NULL_INPUT;
358 }
359 if ((len == 0) || (ctx->iterCnt == 0)) {
360 BSL_ERR_PUSH_ERROR(CRYPT_PBKDF2_PARAM_ERROR);
361 return CRYPT_PBKDF2_PARAM_ERROR;
362 }
363
364 void *macCtx = ctx->macMeth->newCtx(ctx->macId);
365 if (macCtx == NULL) {
366 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
367 return CRYPT_MEM_ALLOC_FAIL;
368 }
369 ctx->macCtx = macCtx;
370
371 ret = CRYPT_PBKDF2_GenDk(ctx, out, len);
372
373 ctx->macMeth->deinit(ctx->macCtx);
374 ctx->macMeth->freeCtx(ctx->macCtx);
375 ctx->macCtx = NULL;
376 return ret;
377 }
378
379
CRYPT_PBKDF2_Deinit(CRYPT_PBKDF2_Ctx * ctx)380 int32_t CRYPT_PBKDF2_Deinit(CRYPT_PBKDF2_Ctx *ctx)
381 {
382 if (ctx == NULL) {
383 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
384 return CRYPT_NULL_INPUT;
385 }
386 BSL_SAL_ClearFree((void *)ctx->password, ctx->passLen);
387 BSL_SAL_FREE(ctx->salt);
388 (void)memset_s(ctx, sizeof(CRYPT_PBKDF2_Ctx), 0, sizeof(CRYPT_PBKDF2_Ctx));
389 return CRYPT_SUCCESS;
390 }
391
CRYPT_PBKDF2_FreeCtx(CRYPT_PBKDF2_Ctx * ctx)392 void CRYPT_PBKDF2_FreeCtx(CRYPT_PBKDF2_Ctx *ctx)
393 {
394 if (ctx == NULL) {
395 return;
396 }
397 BSL_SAL_ClearFree((void *)ctx->password, ctx->passLen);
398 BSL_SAL_FREE(ctx->salt);
399 BSL_SAL_Free(ctx);
400 }
401
402 #endif // HITLS_CRYPTO_PBKDF2
403