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 <stdlib.h>
17 #include <stdint.h>
18 #include "hitls_build.h"
19 #ifdef HITLS_TLS_FEATURE_CUSTOM_EXTENSION
20 #include "tls_binlog_id.h"
21 #include "bsl_log_internal.h"
22 #include "bsl_log.h"
23 #include "bsl_err_internal.h"
24 #include "bsl_bytes.h"
25 #include "hitls_error.h"
26 #include "hitls_config.h"
27 #include "tls.h"
28 #include "hs_msg.h"
29 #include "hs_ctx.h"
30 #include "hs.h"
31 #include "securec.h"
32 #include "bsl_errno.h"
33 #include "bsl_sal.h"
34 #include "custom_extensions.h"
35 #include "alert.h"
36
IsPackNeedCustomExtensions(CustomExt_Methods * exts,uint32_t context)37 bool IsPackNeedCustomExtensions(CustomExt_Methods *exts, uint32_t context)
38 {
39 uint32_t i = 0;
40
41 if (exts == NULL) {
42 return false;
43 }
44 CustomExt_Method *meth = exts->meths;
45 if (meth == NULL) {
46 return false;
47 }
48 for (i = 0; i < exts->methsCount; i++, meth++) {
49 if ((context & meth->context) != 0) {
50 return true;
51 }
52 }
53
54 return false;
55 }
56
IsParseNeedCustomExtensions(CustomExt_Methods * exts,uint16_t extType,uint32_t context)57 bool IsParseNeedCustomExtensions(CustomExt_Methods *exts, uint16_t extType, uint32_t context)
58 {
59 uint32_t i = 0;
60
61 if (exts == NULL) {
62 return false;
63 }
64
65 CustomExt_Method *meth = exts->meths;
66
67 if (meth == NULL) {
68 return false;
69 }
70
71 for (i = 0; i < exts->methsCount; i++, meth++) {
72 if (extType == meth->extType && (context & meth->context) != 0) {
73 return true;
74 }
75 }
76 return false;
77 }
78
IsCustomExtensionTypeAdded(CustomExt_Methods * exts,uint16_t extType)79 bool IsCustomExtensionTypeAdded(CustomExt_Methods *exts, uint16_t extType)
80 {
81 uint32_t i = 0;
82
83 if (exts == NULL) {
84 return false;
85 }
86 CustomExt_Method *meth = exts->meths;
87 if (meth == NULL) {
88 return false;
89 }
90 for (i = 0; i < exts->methsCount; i++, meth++) {
91 if (extType == meth->extType) {
92 return true;
93 }
94 }
95 return false;
96 }
97
FindCustomExtensions(CustomExt_Methods * exts,uint16_t extType,uint32_t context)98 CustomExt_Method *FindCustomExtensions(CustomExt_Methods *exts, uint16_t extType, uint32_t context)
99 {
100 uint32_t i = 0;
101
102 if (exts == NULL) {
103 return NULL;
104 }
105
106 CustomExt_Method *meth = exts->meths;
107
108 if (meth == NULL) {
109 return NULL;
110 }
111
112 for (i = 0; i < exts->methsCount; i++, meth++) {
113 if (extType == meth->extType && (context & meth->context) != 0) {
114 return meth;
115 }
116 }
117 return NULL;
118 }
119
HITLS_CFG_AddCustomExtension(HITLS_Config * config,const HITLS_CustomExtParams * params)120 uint32_t HITLS_CFG_AddCustomExtension(HITLS_Config *config, const HITLS_CustomExtParams *params)
121 {
122 CustomExt_Method *meth = NULL;
123 CustomExt_Method *tmp = NULL;
124
125 if (config == NULL || params == NULL) {
126 return HITLS_NULL_INPUT;
127 }
128
129 if (params->addCb == NULL && params->freeCb != NULL) {
130 return HITLS_INVALID_INPUT;
131 }
132
133 CustomExt_Methods *exts = config->customExts;
134
135 if (IsCustomExtensionTypeAdded(exts, params->extType) ||
136 FindCustomExtensions(exts, params->extType, params->context) != NULL) {
137 return HITLS_CONFIG_DUP_CUSTOM_EXT;
138 }
139
140 if (exts == NULL) {
141 exts = (CustomExt_Methods *)BSL_SAL_Malloc(sizeof(CustomExt_Methods));
142 if (exts == NULL) {
143 return HITLS_MEMALLOC_FAIL;
144 }
145 exts->meths = NULL;
146 exts->methsCount = 0;
147 config->customExts = exts;
148 }
149
150 tmp = BSL_SAL_Realloc(exts->meths, (exts->methsCount + 1) * sizeof(CustomExt_Method),
151 exts->methsCount * sizeof(CustomExt_Method));
152 if (tmp == NULL) {
153 return HITLS_MEMALLOC_FAIL;
154 }
155
156 exts->meths = tmp;
157 meth = exts->meths + exts->methsCount;
158
159 memset_s(meth, sizeof(*meth), 0, sizeof(*meth));
160 meth->extType = params->extType;
161 meth->context = params->context;
162 meth->addCb = params->addCb;
163 meth->freeCb = params->freeCb;
164 meth->addArg = params->addArg;
165 meth->parseCb = params->parseCb;
166 meth->parseArg = params->parseArg;
167 exts->methsCount++;
168
169 return HITLS_SUCCESS;
170 }
171
HITLS_AddCustomExtension(HITLS_Ctx * ctx,const HITLS_CustomExtParams * params)172 uint32_t HITLS_AddCustomExtension(HITLS_Ctx *ctx, const HITLS_CustomExtParams *params)
173 {
174 if (ctx == NULL || params == NULL) {
175 return HITLS_NULL_INPUT;
176 }
177
178 return HITLS_CFG_AddCustomExtension(&(ctx->config.tlsConfig), params);
179 }
180
181
PackCustomExtensions(const struct TlsCtx * ctx,uint8_t * buf,uint32_t bufLen,uint32_t * len,uint32_t context,HITLS_X509_Cert * cert,uint32_t certIndex)182 int32_t PackCustomExtensions(const struct TlsCtx *ctx, uint8_t *buf, uint32_t bufLen, uint32_t *len, uint32_t context, HITLS_X509_Cert *cert, uint32_t certIndex)
183 {
184 uint32_t offset = 0u;
185 uint32_t alert = 0u;
186
187 if (ctx == NULL || buf == NULL || len == NULL) {
188 return HITLS_NULL_INPUT;
189 }
190
191 CustomExt_Methods *exts = CUSTOM_EXT_FROM_CTX(ctx);
192 CustomExt_Method *meth = NULL;
193 uint32_t ret = 0;
194 if (exts == NULL) {
195 *len = 0;
196 return HITLS_SUCCESS;
197 }
198
199 for (uint32_t i = 0; i < exts->methsCount; i++) {
200 uint8_t *out = NULL;
201 uint32_t outLen = 0;
202
203 meth = exts->meths + i;
204
205 if ((meth->context & context) == 0) {
206 continue;
207 }
208
209 if (meth->addCb != NULL) {
210 ret = meth->addCb(ctx, meth->extType, context, &out, &outLen, cert, certIndex, &alert, meth->addArg);
211 if (ret != HITLS_ADD_CUSTOM_EXTENSION_RET_PACK && ret != HITLS_ADD_CUSTOM_EXTENSION_RET_PASS) {
212 ALERT_Send(ctx, ALERT_LEVEL_FATAL, alert);
213 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17350, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
214 "pack custom extension content fail.", 0, 0, 0, 0);
215 return ret;
216 }
217 }
218
219 if (ret == HITLS_ADD_CUSTOM_EXTENSION_RET_PACK) {
220 if (bufLen - offset >= outLen + sizeof(uint16_t) + sizeof(uint16_t)) {
221 BSL_Uint16ToByte(meth->extType, &buf[offset]);
222 offset += sizeof(uint16_t);
223
224 BSL_Uint16ToByte(outLen, &buf[offset]);
225 offset += sizeof(uint16_t);
226
227 (void)memcpy_s(&buf[offset], bufLen - offset, out, outLen);
228 offset += outLen;
229 } else {
230 return HITLS_PACK_NOT_ENOUGH_BUF_LENGTH;
231 }
232 }
233
234 if (meth->freeCb != NULL && out != NULL) {
235 meth->freeCb(ctx, meth->extType, context, out, meth->addArg);
236 }
237 }
238
239 *len = offset;
240 return HITLS_SUCCESS;
241 }
242
ParseCustomExtensions(const struct TlsCtx * ctx,const uint8_t * buf,uint16_t extType,uint32_t extLen,uint32_t context,HITLS_X509_Cert * cert,uint32_t certIndex)243 int32_t ParseCustomExtensions(const struct TlsCtx *ctx, const uint8_t *buf, uint16_t extType, uint32_t extLen,
244 uint32_t context, HITLS_X509_Cert *cert, uint32_t certIndex)
245 {
246 uint32_t alert = 0u;
247
248 CustomExt_Methods *exts = CUSTOM_EXT_FROM_CTX(ctx);
249 CustomExt_Method *meth;
250
251 meth = FindCustomExtensions(exts, extType, context);
252 if (meth == NULL) {
253 return HITLS_SUCCESS;
254 }
255
256 // Create a local pointer starting from the position after the type byte
257 if (meth->parseCb != NULL) {
258 uint32_t ret = meth->parseCb(ctx, meth->extType, context, &buf, &extLen, cert, certIndex, &alert, meth->parseArg);
259 if (ret != HITLS_SUCCESS) {
260 ALERT_Send(ctx, ALERT_LEVEL_FATAL, alert);
261 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17351, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
262 "parse custom extension content fail.", 0, 0, 0, 0);
263 return ret;
264 }
265 }
266
267 return HITLS_SUCCESS;
268 }
269
FreeCustomExtensions(CustomExt_Methods * exts)270 void FreeCustomExtensions(CustomExt_Methods *exts)
271 {
272 if (exts == NULL) {
273 return;
274 }
275 if (exts->meths == NULL) {
276 BSL_SAL_Free(exts);
277 return;
278 }
279 BSL_SAL_Free(exts->meths);
280 BSL_SAL_Free(exts);
281 }
282
DupCustomExtensions(CustomExt_Methods * exts)283 CustomExt_Methods *DupCustomExtensions(CustomExt_Methods *exts)
284 {
285 if (exts == NULL) {
286 return NULL;
287 }
288 CustomExt_Methods *newExts = (CustomExt_Methods *)BSL_SAL_Malloc(sizeof(CustomExt_Methods));
289 if (newExts == NULL) {
290 return NULL;
291 }
292 newExts->meths = (CustomExt_Method *)BSL_SAL_Dump(exts->meths, exts->methsCount * sizeof(CustomExt_Method));
293 if (newExts->meths == NULL) {
294 BSL_SAL_Free(newExts);
295 return NULL;
296 }
297 newExts->methsCount = exts->methsCount;
298 return newExts;
299 }
300 #endif /* HITLS_TLS_FEATURE_CUSTOM_EXTENSION */
301