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