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