• 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_HKDF
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_hkdf.h"
27 #include "eal_mac_local.h"
28 #include "bsl_params.h"
29 #include "crypt_params_key.h"
30 
31 #define HKDF_MAX_HMACSIZE 64
32 
33 static const uint32_t HKDF_ID_LIST[] = {
34     CRYPT_MAC_HMAC_MD5,
35     CRYPT_MAC_HMAC_SHA1,
36     CRYPT_MAC_HMAC_SHA224,
37     CRYPT_MAC_HMAC_SHA256,
38     CRYPT_MAC_HMAC_SHA384,
39     CRYPT_MAC_HMAC_SHA512,
40 };
41 
CRYPT_HKDF_IsValidAlgId(CRYPT_MAC_AlgId id)42 bool CRYPT_HKDF_IsValidAlgId(CRYPT_MAC_AlgId id)
43 {
44     return ParamIdIsValid(id, HKDF_ID_LIST, sizeof(HKDF_ID_LIST) / sizeof(HKDF_ID_LIST[0]));
45 }
46 
47 struct CryptHkdfCtx {
48     CRYPT_MAC_AlgId macId;
49     const EAL_MacMethod *macMeth;
50     const EAL_MdMethod *mdMeth;
51     CRYPT_HKDF_MODE mode;
52     uint8_t *key;
53     uint32_t keyLen;
54     uint8_t *salt;
55     uint32_t saltLen;
56     uint8_t *prk;
57     uint32_t prkLen;
58     uint8_t *info;
59     uint32_t infoLen;
60     uint32_t *outLen;
61 };
62 
CRYPT_HKDF_Extract(const EAL_MacMethod * macMeth,CRYPT_MAC_AlgId macId,const uint8_t * key,uint32_t keyLen,const uint8_t * salt,uint32_t saltLen,uint8_t * prk,uint32_t * prkLen)63 int32_t CRYPT_HKDF_Extract(const EAL_MacMethod *macMeth, CRYPT_MAC_AlgId macId, const uint8_t *key,
64     uint32_t keyLen, const uint8_t *salt, uint32_t saltLen, uint8_t *prk, uint32_t *prkLen)
65 {
66     int32_t ret;
67     if (macMeth == NULL) {
68         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
69         return CRYPT_NULL_INPUT;
70     }
71     if (key == NULL && keyLen > 0) {
72         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
73         return CRYPT_NULL_INPUT;
74     }
75     if (salt == NULL && saltLen > 0) {
76         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
77         return CRYPT_NULL_INPUT;
78     }
79 
80     void *macCtx = macMeth->newCtx(macId);
81     if (macCtx == NULL) {
82         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
83         return CRYPT_MEM_ALLOC_FAIL;
84     }
85 
86     GOTO_ERR_IF(macMeth->init(macCtx, salt, saltLen, NULL), ret);
87     GOTO_ERR_IF(macMeth->update(macCtx, key, keyLen), ret);
88     GOTO_ERR_IF(macMeth->final(macCtx, prk, prkLen), ret);
89 
90 ERR:
91     macMeth->deinit(macCtx);
92     macMeth->freeCtx(macCtx);
93     macCtx = NULL;
94     return ret;
95 }
96 
HKDF_ExpandParamCheck(const EAL_MacMethod * macMeth,const EAL_MdMethod * mdMeth,const uint8_t * prk,uint32_t prkLen,const uint8_t * info,uint32_t infoLen,const uint8_t * out,uint32_t outLen)97 static int32_t HKDF_ExpandParamCheck(const EAL_MacMethod *macMeth, const EAL_MdMethod *mdMeth, const uint8_t *prk,
98     uint32_t prkLen, const uint8_t *info, uint32_t infoLen, const uint8_t *out, uint32_t outLen)
99 {
100     if (macMeth == NULL || mdMeth == NULL) {
101         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
102         return CRYPT_NULL_INPUT;
103     }
104     if (prk == NULL && prkLen > 0) {
105         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
106         return CRYPT_NULL_INPUT;
107     }
108     if (info == NULL && infoLen > 0) {
109         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
110         return CRYPT_NULL_INPUT;
111     }
112     if ((out == NULL) || (outLen == 0)) {
113         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
114         return CRYPT_NULL_INPUT;
115     }
116     if (mdMeth->mdSize == 0) {
117         BSL_ERR_PUSH_ERROR(CRYPT_HKDF_PARAM_ERROR);
118         return CRYPT_HKDF_PARAM_ERROR;
119     }
120     /* len cannot be larger than 255 * hashLen */
121     if (outLen > (uint32_t)mdMeth->mdSize * 255) {
122         BSL_ERR_PUSH_ERROR(CRYPT_HKDF_DKLEN_OVERFLOW);
123         return CRYPT_HKDF_DKLEN_OVERFLOW;
124     }
125 
126     return CRYPT_SUCCESS;
127 }
128 
CRYPT_HKDF_Expand(const EAL_MacMethod * macMeth,CRYPT_MAC_AlgId macId,const EAL_MdMethod * mdMeth,const uint8_t * prk,uint32_t prkLen,const uint8_t * info,uint32_t infoLen,uint8_t * out,uint32_t outLen)129 int32_t CRYPT_HKDF_Expand(const EAL_MacMethod *macMeth, CRYPT_MAC_AlgId macId, const EAL_MdMethod *mdMeth,
130     const uint8_t *prk, uint32_t prkLen, const uint8_t *info, uint32_t infoLen, uint8_t *out, uint32_t outLen)
131 {
132     int32_t ret = HKDF_ExpandParamCheck(macMeth, mdMeth, prk, prkLen, info, infoLen, out, outLen);
133     if (ret != CRYPT_SUCCESS) {
134         return ret;
135     }
136     uint8_t hash[HKDF_MAX_HMACSIZE];
137     uint32_t hashLen = mdMeth->mdSize;
138     uint8_t counter = 1;
139     uint32_t totalLen = 0;
140     uint32_t n;
141 
142     void *macCtx = macMeth->newCtx(macId);
143     if (macCtx == NULL) {
144         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
145         return CRYPT_MEM_ALLOC_FAIL;
146     }
147 
148     GOTO_ERR_IF(macMeth->init(macCtx, prk, prkLen, NULL), ret);
149 
150     /* ceil(a / b) = (a + b - 1) / b */
151     n = (outLen + hashLen - 1) / hashLen;
152     for (uint32_t i = 1; i <= n; i++, counter++) {
153         if (i > 1) {
154             macMeth->reinit(macCtx);
155             GOTO_ERR_IF(macMeth->update(macCtx, hash, hashLen), ret);
156         }
157         GOTO_ERR_IF(macMeth->update(macCtx, info, infoLen), ret);
158         GOTO_ERR_IF(macMeth->update(macCtx, &counter, 1), ret);
159         GOTO_ERR_IF(macMeth->final(macCtx, hash, &hashLen), ret);
160         hashLen = hashLen > (outLen - totalLen) ? (outLen - totalLen) : hashLen;
161         (void)memcpy_s(out + totalLen, outLen - totalLen, hash, hashLen);
162         totalLen += hashLen;
163     }
164 
165 ERR:
166     macMeth->deinit(macCtx);
167     macMeth->freeCtx(macCtx);
168     macCtx = NULL;
169     return ret;
170 }
171 
CRYPT_HKDF(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,const uint8_t * info,uint32_t infoLen,uint8_t * out,uint32_t len)172 int32_t CRYPT_HKDF(const EAL_MacMethod *macMeth, CRYPT_MAC_AlgId macId, const EAL_MdMethod *mdMeth,
173     const uint8_t *key, uint32_t keyLen, const uint8_t *salt, uint32_t saltLen,
174     const uint8_t *info, uint32_t infoLen, uint8_t *out, uint32_t len)
175 {
176     int ret;
177     uint8_t prk[HKDF_MAX_HMACSIZE];
178     uint32_t prkLen = HKDF_MAX_HMACSIZE;
179     ret = CRYPT_HKDF_Extract(macMeth, macId, key, keyLen, salt, saltLen, prk, &prkLen);
180     if (ret != CRYPT_SUCCESS) {
181         return ret;
182     }
183     return CRYPT_HKDF_Expand(macMeth, macId, mdMeth, prk, prkLen, info, infoLen, out, len);
184 }
185 
CRYPT_HKDF_NewCtx(void)186 CRYPT_HKDF_Ctx* CRYPT_HKDF_NewCtx(void)
187 {
188     CRYPT_HKDF_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_HKDF_Ctx));
189     if (ctx == NULL) {
190         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
191         return NULL;
192     }
193     return ctx;
194 }
195 
CRYPT_HKDF_SetMacMethod(CRYPT_HKDF_Ctx * ctx,const CRYPT_MAC_AlgId id)196 int32_t CRYPT_HKDF_SetMacMethod(CRYPT_HKDF_Ctx *ctx, const CRYPT_MAC_AlgId id)
197 {
198     EAL_MacMethLookup method;
199     if (!CRYPT_HKDF_IsValidAlgId(id)) {
200         BSL_ERR_PUSH_ERROR(CRYPT_HKDF_PARAM_ERROR);
201         return CRYPT_HKDF_PARAM_ERROR;
202     }
203     int32_t ret = EAL_MacFindMethod(id, &method);
204     if (ret != CRYPT_SUCCESS) {
205         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_METH_NULL_NUMBER);
206         return CRYPT_EAL_ERR_METH_NULL_NUMBER;
207     }
208     ctx->macMeth = method.macMethod;
209     ctx->macId = id;
210     ctx->mdMeth = method.md;
211     return CRYPT_SUCCESS;
212 }
213 
CRYPT_HKDF_SetKey(CRYPT_HKDF_Ctx * ctx,const uint8_t * key,uint32_t keyLen)214 int32_t CRYPT_HKDF_SetKey(CRYPT_HKDF_Ctx *ctx, const uint8_t *key, uint32_t keyLen)
215 {
216     if (key == NULL && keyLen > 0) {
217         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
218         return CRYPT_NULL_INPUT;
219     }
220 
221     BSL_SAL_ClearFree((void *)ctx->key, ctx->keyLen);
222 
223     ctx->key = BSL_SAL_Dump(key, keyLen);
224     if (ctx->key == NULL && keyLen > 0) {
225         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
226         return CRYPT_MEM_ALLOC_FAIL;
227     }
228     ctx->keyLen = keyLen;
229     return CRYPT_SUCCESS;
230 }
231 
CRYPT_HKDF_SetSalt(CRYPT_HKDF_Ctx * ctx,const uint8_t * salt,uint32_t saltLen)232 int32_t CRYPT_HKDF_SetSalt(CRYPT_HKDF_Ctx *ctx, const uint8_t *salt, uint32_t saltLen)
233 {
234     if (salt == NULL && saltLen > 0) {
235         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
236         return CRYPT_NULL_INPUT;
237     }
238 
239     BSL_SAL_FREE(ctx->salt);
240 
241     ctx->salt = BSL_SAL_Dump(salt, saltLen);
242     if (ctx->salt == NULL && saltLen > 0) {
243         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
244         return CRYPT_MEM_ALLOC_FAIL;
245     }
246     ctx->saltLen = saltLen;
247     return CRYPT_SUCCESS;
248 }
249 
CRYPT_HKDF_SetPRK(CRYPT_HKDF_Ctx * ctx,const uint8_t * prk,uint32_t prkLen)250 int32_t CRYPT_HKDF_SetPRK(CRYPT_HKDF_Ctx *ctx, const uint8_t *prk, uint32_t prkLen)
251 {
252     if (prk == NULL && prkLen > 0) {
253         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
254         return CRYPT_NULL_INPUT;
255     }
256 
257     BSL_SAL_ClearFree((void *)ctx->prk, ctx->prkLen);
258 
259     ctx->prk = BSL_SAL_Dump(prk, prkLen);
260     if (ctx->prk == NULL && prkLen > 0) {
261         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
262         return CRYPT_MEM_ALLOC_FAIL;
263     }
264     ctx->prkLen = prkLen;
265     return CRYPT_SUCCESS;
266 }
267 
CRYPT_HKDF_SetInfo(CRYPT_HKDF_Ctx * ctx,const uint8_t * info,uint32_t infoLen)268 int32_t CRYPT_HKDF_SetInfo(CRYPT_HKDF_Ctx *ctx, const uint8_t *info, uint32_t infoLen)
269 {
270     if (info == NULL && infoLen > 0) {
271         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
272         return CRYPT_NULL_INPUT;
273     }
274 
275     BSL_SAL_ClearFree((void *)ctx->info, ctx->infoLen);
276 
277     ctx->info = BSL_SAL_Dump(info, infoLen);
278     if (ctx->info == NULL && infoLen > 0) {
279         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
280         return CRYPT_MEM_ALLOC_FAIL;
281     }
282     ctx->infoLen = infoLen;
283     return CRYPT_SUCCESS;
284 }
285 
CRYPT_HKDF_SetOutLen(CRYPT_HKDF_Ctx * ctx,uint32_t * outLen)286 int32_t CRYPT_HKDF_SetOutLen(CRYPT_HKDF_Ctx *ctx, uint32_t *outLen)
287 {
288     if (outLen == NULL) {
289         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
290         return CRYPT_NULL_INPUT;
291     }
292 
293     ctx->outLen = outLen;
294     return CRYPT_SUCCESS;
295 }
296 
297 
CRYPT_HKDF_SetParam(CRYPT_HKDF_Ctx * ctx,const BSL_Param * param)298 int32_t CRYPT_HKDF_SetParam(CRYPT_HKDF_Ctx *ctx, const BSL_Param *param)
299 {
300     uint32_t val = 0;
301     void *ptrVal = NULL;
302     uint32_t len = 0;
303     const BSL_Param *temp = NULL;
304     int32_t ret = CRYPT_HKDF_PARAM_ERROR;
305     if (ctx == NULL || param == NULL) {
306         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
307         return CRYPT_NULL_INPUT;
308     }
309     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_MAC_ID)) != NULL) {
310         len = sizeof(val);
311         GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_MAC_ID,
312             BSL_PARAM_TYPE_UINT32, &val, &len), ret);
313         GOTO_ERR_IF(CRYPT_HKDF_SetMacMethod(ctx, val), ret);
314     }
315     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_MODE)) != NULL) {
316         len = sizeof(val);
317         GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_MODE,
318             BSL_PARAM_TYPE_UINT32, &val, &len), ret);
319         ctx->mode = val;
320     }
321     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_KEY)) != NULL) {
322         GOTO_ERR_IF(CRYPT_HKDF_SetKey(ctx, temp->value, temp->valueLen), ret);
323     }
324     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_SALT)) != NULL) {
325         GOTO_ERR_IF(CRYPT_HKDF_SetSalt(ctx, temp->value, temp->valueLen), ret);
326     }
327     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_PRK)) != NULL) {
328         GOTO_ERR_IF(CRYPT_HKDF_SetPRK(ctx, temp->value, temp->valueLen), ret);
329     }
330     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_INFO)) != NULL) {
331         GOTO_ERR_IF(CRYPT_HKDF_SetInfo(ctx, temp->value, temp->valueLen), ret);
332     }
333     if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_EXLEN)) != NULL) {
334         len = sizeof(val);
335         GOTO_ERR_IF(BSL_PARAM_GetPtrValue(temp, CRYPT_PARAM_KDF_EXLEN, BSL_PARAM_TYPE_UINT32_PTR, &ptrVal, &len), ret);
336         GOTO_ERR_IF(CRYPT_HKDF_SetOutLen(ctx, ptrVal), ret);
337     }
338 ERR:
339     return ret;
340 }
341 
CRYPT_HKDF_Derive(CRYPT_HKDF_Ctx * ctx,uint8_t * out,uint32_t len)342 int32_t CRYPT_HKDF_Derive(CRYPT_HKDF_Ctx *ctx, uint8_t *out, uint32_t len)
343 {
344     if (ctx == NULL) {
345         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
346         return CRYPT_NULL_INPUT;
347     }
348 
349     const EAL_MacMethod *macMeth = ctx->macMeth;
350     CRYPT_MAC_AlgId macId = ctx->macId;
351     const EAL_MdMethod *mdMeth = ctx->mdMeth;
352     const uint8_t *key = ctx->key;
353     uint32_t keyLen = ctx->keyLen;
354     const uint8_t *salt = ctx->salt;
355     uint32_t saltLen = ctx->saltLen;
356     const uint8_t *prk = ctx->prk;
357     uint32_t prkLen = ctx->prkLen;
358     const uint8_t *info = ctx->info;
359     uint32_t infoLen = ctx->infoLen;
360     uint32_t *outLen = ctx->outLen;
361 
362     switch (ctx->mode) {
363         case CRYPT_KDF_HKDF_MODE_FULL:
364             return CRYPT_HKDF(macMeth, macId, mdMeth, key, keyLen, salt, saltLen, info, infoLen, out, len);
365         case CRYPT_KDF_HKDF_MODE_EXTRACT:
366             return CRYPT_HKDF_Extract(macMeth, macId, key, keyLen, salt, saltLen, out, outLen);
367         case CRYPT_KDF_HKDF_MODE_EXPAND:
368             return CRYPT_HKDF_Expand(macMeth, macId, mdMeth, prk, prkLen, info, infoLen, out, len);
369         default:
370             return CRYPT_HKDF_PARAM_ERROR;
371     }
372 }
373 
CRYPT_HKDF_Deinit(CRYPT_HKDF_Ctx * ctx)374 int32_t CRYPT_HKDF_Deinit(CRYPT_HKDF_Ctx *ctx)
375 {
376     if (ctx == NULL) {
377         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
378         return CRYPT_NULL_INPUT;
379     }
380     BSL_SAL_ClearFree((void *)ctx->key, ctx->keyLen);
381     BSL_SAL_FREE(ctx->salt);
382     BSL_SAL_ClearFree((void *)ctx->prk, ctx->prkLen);
383     BSL_SAL_ClearFree((void *)ctx->info, ctx->infoLen);
384     (void)memset_s(ctx, sizeof(CRYPT_HKDF_Ctx), 0, sizeof(CRYPT_HKDF_Ctx));
385     return CRYPT_SUCCESS;
386 }
387 
CRYPT_HKDF_FreeCtx(CRYPT_HKDF_Ctx * ctx)388 void CRYPT_HKDF_FreeCtx(CRYPT_HKDF_Ctx *ctx)
389 {
390     if (ctx == NULL) {
391         return;
392     }
393     BSL_SAL_ClearFree((void *)ctx->key, ctx->keyLen);
394     BSL_SAL_FREE(ctx->salt);
395     BSL_SAL_ClearFree((void *)ctx->prk, ctx->prkLen);
396     BSL_SAL_ClearFree((void *)ctx->info, ctx->infoLen);
397     BSL_SAL_Free(ctx);
398 }
399 #endif // HITLS_CRYPTO_HKDF
400