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_KDFTLS12
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_kdf_tls12.h"
27 #include "eal_mac_local.h"
28 #include "bsl_params.h"
29 #include "crypt_params_key.h"
30
31 #define KDFTLS12_MAX_BLOCKSIZE 64
32
33 static const uint32_t KDFTLS12_ID_LIST[] = {
34 CRYPT_MAC_HMAC_SHA256,
35 CRYPT_MAC_HMAC_SHA384,
36 CRYPT_MAC_HMAC_SHA512,
37 };
38
39 struct CryptKdfTls12Ctx {
40 CRYPT_MAC_AlgId macId;
41 const EAL_MacMethod *macMeth;
42 void *macCtx;
43 uint8_t *key;
44 uint32_t keyLen;
45 uint8_t *label;
46 uint32_t labelLen;
47 uint8_t *seed;
48 uint32_t seedLen;
49 };
50
CRYPT_KDFTLS12_IsValidAlgId(CRYPT_MAC_AlgId id)51 bool CRYPT_KDFTLS12_IsValidAlgId(CRYPT_MAC_AlgId id)
52 {
53 return ParamIdIsValid(id, KDFTLS12_ID_LIST, sizeof(KDFTLS12_ID_LIST) / sizeof(KDFTLS12_ID_LIST[0]));
54 }
55
KDF_Hmac(const EAL_MacMethod * macMeth,void * macCtx,uint8_t * data,uint32_t * len)56 int32_t KDF_Hmac(const EAL_MacMethod *macMeth, void *macCtx, uint8_t *data, uint32_t *len)
57 {
58 macMeth->reinit(macCtx);
59 int32_t ret = macMeth->update(macCtx, data, *len);
60 if (ret != CRYPT_SUCCESS) {
61 return ret;
62 }
63 return macMeth->final(macCtx, data, len);
64 }
65
66 // algorithm implementation see https://datatracker.ietf.org/doc/pdf/rfc5246.pdf, chapter 5, p_hash function
KDF_PHASH(CRYPT_KDFTLS12_Ctx * ctx,uint8_t * out,uint32_t len)67 int32_t KDF_PHASH(CRYPT_KDFTLS12_Ctx *ctx, uint8_t *out, uint32_t len)
68 {
69 int32_t ret = CRYPT_SUCCESS;
70 const EAL_MacMethod *macMeth = ctx->macMeth;
71 uint32_t totalLen = 0;
72 uint8_t nextIn[KDFTLS12_MAX_BLOCKSIZE];
73 uint32_t nextInLen = KDFTLS12_MAX_BLOCKSIZE;
74 uint8_t outTmp[KDFTLS12_MAX_BLOCKSIZE];
75 uint32_t outTmpLen = KDFTLS12_MAX_BLOCKSIZE;
76
77 void *macCtx = macMeth->newCtx(ctx->macId);
78 if (macCtx == NULL) {
79 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
80 return CRYPT_MEM_ALLOC_FAIL;
81 }
82 ctx->macCtx = macCtx;
83
84 while (len > totalLen) {
85 if (totalLen == 0) {
86 GOTO_ERR_IF(macMeth->init(ctx->macCtx, ctx->key, ctx->keyLen, NULL), ret);
87 GOTO_ERR_IF(macMeth->update(ctx->macCtx, ctx->label, ctx->labelLen), ret);
88 GOTO_ERR_IF(macMeth->update(ctx->macCtx, ctx->seed, ctx->seedLen), ret);
89 GOTO_ERR_IF(macMeth->final(ctx->macCtx, nextIn, &nextInLen), ret);
90 } else {
91 GOTO_ERR_IF(KDF_Hmac(macMeth, ctx->macCtx, nextIn, &nextInLen), ret);
92 }
93
94 macMeth->reinit(ctx->macCtx);
95 GOTO_ERR_IF(macMeth->update(ctx->macCtx, nextIn, nextInLen), ret);
96 GOTO_ERR_IF(macMeth->update(ctx->macCtx, ctx->label, ctx->labelLen), ret);
97 GOTO_ERR_IF(macMeth->update(ctx->macCtx, ctx->seed, ctx->seedLen), ret);
98 GOTO_ERR_IF(macMeth->final(ctx->macCtx, outTmp, &outTmpLen), ret);
99
100 uint32_t cpyLen = outTmpLen > (len - totalLen) ? (len - totalLen) : outTmpLen;
101 (void)memcpy_s(out + totalLen, len - totalLen, outTmp, cpyLen);
102 totalLen += cpyLen;
103 }
104
105 ERR:
106 macMeth->deinit(ctx->macCtx);
107 macMeth->freeCtx(ctx->macCtx);
108 ctx->macCtx = NULL;
109 return ret;
110 }
111
CRYPT_KDFTLS12_NewCtx(void)112 CRYPT_KDFTLS12_Ctx* CRYPT_KDFTLS12_NewCtx(void)
113 {
114 CRYPT_KDFTLS12_Ctx *ctx = BSL_SAL_Calloc(1, sizeof(CRYPT_KDFTLS12_Ctx));
115 if (ctx == NULL) {
116 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
117 return NULL;
118 }
119 return ctx;
120 }
121
CRYPT_KDFTLS12_SetMacMethod(CRYPT_KDFTLS12_Ctx * ctx,const CRYPT_MAC_AlgId id)122 int32_t CRYPT_KDFTLS12_SetMacMethod(CRYPT_KDFTLS12_Ctx *ctx, const CRYPT_MAC_AlgId id)
123 {
124 EAL_MacMethLookup method;
125 if (!CRYPT_KDFTLS12_IsValidAlgId(id)) {
126 BSL_ERR_PUSH_ERROR(CRYPT_KDFTLS12_PARAM_ERROR);
127 return CRYPT_KDFTLS12_PARAM_ERROR;
128 }
129 int32_t ret = EAL_MacFindMethod(id, &method);
130 if (ret != CRYPT_SUCCESS) {
131 BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_METH_NULL_NUMBER);
132 return CRYPT_EAL_ERR_METH_NULL_NUMBER;
133 }
134 ctx->macMeth = method.macMethod;
135 ctx->macId = id;
136 return CRYPT_SUCCESS;
137 }
138
CRYPT_KDFTLS12_SetKey(CRYPT_KDFTLS12_Ctx * ctx,const uint8_t * key,uint32_t keyLen)139 int32_t CRYPT_KDFTLS12_SetKey(CRYPT_KDFTLS12_Ctx *ctx, const uint8_t *key, uint32_t keyLen)
140 {
141 if (key == NULL && keyLen > 0) {
142 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
143 return CRYPT_NULL_INPUT;
144 }
145
146 BSL_SAL_ClearFree((void *)ctx->key, ctx->keyLen);
147
148 ctx->key = BSL_SAL_Dump(key, keyLen);
149 if (ctx->key == NULL && keyLen > 0) {
150 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
151 return CRYPT_MEM_ALLOC_FAIL;
152 }
153 ctx->keyLen = keyLen;
154 return CRYPT_SUCCESS;
155 }
156
CRYPT_KDFTLS12_SetLabel(CRYPT_KDFTLS12_Ctx * ctx,const uint8_t * label,uint32_t labelLen)157 int32_t CRYPT_KDFTLS12_SetLabel(CRYPT_KDFTLS12_Ctx *ctx, const uint8_t *label, uint32_t labelLen)
158 {
159 if (label == NULL && labelLen > 0) {
160 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
161 return CRYPT_NULL_INPUT;
162 }
163
164 BSL_SAL_ClearFree((void *)ctx->label, ctx->labelLen);
165
166 ctx->label = BSL_SAL_Dump(label, labelLen);
167 if (ctx->label == NULL && labelLen > 0) {
168 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
169 return CRYPT_MEM_ALLOC_FAIL;
170 }
171 ctx->labelLen = labelLen;
172 return CRYPT_SUCCESS;
173 }
174
CRYPT_KDFTLS12_SetSeed(CRYPT_KDFTLS12_Ctx * ctx,const uint8_t * seed,uint32_t seedLen)175 int32_t CRYPT_KDFTLS12_SetSeed(CRYPT_KDFTLS12_Ctx *ctx, const uint8_t *seed, uint32_t seedLen)
176 {
177 if (seed == NULL && seedLen > 0) {
178 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
179 return CRYPT_NULL_INPUT;
180 }
181
182 BSL_SAL_ClearFree((void *)ctx->seed, ctx->seedLen);
183
184 ctx->seed = BSL_SAL_Dump(seed, seedLen);
185 if (ctx->seed == NULL && seedLen > 0) {
186 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
187 return CRYPT_MEM_ALLOC_FAIL;
188 }
189 ctx->seedLen = seedLen;
190 return CRYPT_SUCCESS;
191 }
192
CRYPT_KDFTLS12_SetParam(CRYPT_KDFTLS12_Ctx * ctx,const BSL_Param * param)193 int32_t CRYPT_KDFTLS12_SetParam(CRYPT_KDFTLS12_Ctx *ctx, const BSL_Param *param)
194 {
195 uint32_t val = 0;
196 uint32_t len = 0;
197 const BSL_Param *temp = NULL;
198 int32_t ret = CRYPT_PBKDF2_PARAM_ERROR;
199 if (ctx == NULL || param == NULL) {
200 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
201 return CRYPT_NULL_INPUT;
202 }
203
204 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_MAC_ID)) != NULL) {
205 len = sizeof(val);
206 GOTO_ERR_IF(BSL_PARAM_GetValue(temp, CRYPT_PARAM_KDF_MAC_ID,
207 BSL_PARAM_TYPE_UINT32, &val, &len), ret);
208 GOTO_ERR_IF(CRYPT_KDFTLS12_SetMacMethod(ctx, val), ret);
209 }
210 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_KEY)) != NULL) {
211 GOTO_ERR_IF(CRYPT_KDFTLS12_SetKey(ctx, temp->value, temp->valueLen), ret);
212 }
213 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_LABEL)) != NULL) {
214 GOTO_ERR_IF(CRYPT_KDFTLS12_SetLabel(ctx, temp->value, temp->valueLen), ret);
215 }
216 if ((temp = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_KDF_SEED)) != NULL) {
217 GOTO_ERR_IF(CRYPT_KDFTLS12_SetSeed(ctx, temp->value, temp->valueLen), ret);
218 }
219 ERR:
220 return ret;
221 }
222
CRYPT_KDFTLS12_Derive(CRYPT_KDFTLS12_Ctx * ctx,uint8_t * out,uint32_t len)223 int32_t CRYPT_KDFTLS12_Derive(CRYPT_KDFTLS12_Ctx *ctx, uint8_t *out, uint32_t len)
224 {
225 if (ctx->macMeth == NULL) {
226 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
227 return CRYPT_NULL_INPUT;
228 }
229 if (ctx->key == NULL && ctx->keyLen > 0) {
230 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
231 return CRYPT_NULL_INPUT;
232 }
233 if (ctx->label == NULL && ctx->labelLen > 0) {
234 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
235 return CRYPT_NULL_INPUT;
236 }
237 if (ctx->seed == NULL && ctx->seedLen > 0) {
238 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
239 return CRYPT_NULL_INPUT;
240 }
241 if ((out == NULL) || (len == 0)) {
242 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
243 return CRYPT_NULL_INPUT;
244 }
245
246 return KDF_PHASH(ctx, out, len);
247 }
248
CRYPT_KDFTLS12_Deinit(CRYPT_KDFTLS12_Ctx * ctx)249 int32_t CRYPT_KDFTLS12_Deinit(CRYPT_KDFTLS12_Ctx *ctx)
250 {
251 if (ctx == NULL) {
252 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
253 return CRYPT_NULL_INPUT;
254 }
255 BSL_SAL_ClearFree((void *)ctx->key, ctx->keyLen);
256 BSL_SAL_ClearFree((void *)ctx->label, ctx->labelLen);
257 BSL_SAL_ClearFree((void *)ctx->seed, ctx->seedLen);
258 (void)memset_s(ctx, sizeof(CRYPT_KDFTLS12_Ctx), 0, sizeof(CRYPT_KDFTLS12_Ctx));
259 return CRYPT_SUCCESS;
260 }
261
CRYPT_KDFTLS12_FreeCtx(CRYPT_KDFTLS12_Ctx * ctx)262 void CRYPT_KDFTLS12_FreeCtx(CRYPT_KDFTLS12_Ctx *ctx)
263 {
264 if (ctx == NULL) {
265 return;
266 }
267 BSL_SAL_ClearFree((void *)ctx->key, ctx->keyLen);
268 BSL_SAL_ClearFree((void *)ctx->label, ctx->labelLen);
269 BSL_SAL_ClearFree((void *)ctx->seed, ctx->seedLen);
270 BSL_SAL_Free(ctx);
271 }
272
273 #endif // HITLS_CRYPTO_KDFTLS12
274