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 #if defined(HITLS_PKI_X509_CSR) || defined(HITLS_PKI_PKCS12)
18 #include <stdint.h>
19 #include "securec.h"
20 #include "hitls_x509_local.h"
21 #include "bsl_obj.h"
22 #include "bsl_sal.h"
23 #include "bsl_obj_internal.h"
24 #include "bsl_err_internal.h"
25 #include "crypt_errno.h"
26 #include "crypt_eal_pkey.h"
27 #include "hitls_pki_errno.h"
28 #include "hitls_pki_utils.h"
29
30 #if defined(HITLS_PKI_X509_CSR_PARSE) || defined(HITLS_PKI_PKCS12_PARSE)
31 /**
32 * RFC 2985: section-5.4.2
33 * extensionRequest ATTRIBUTE ::= {
34 * WITH SYNTAX ExtensionRequest
35 * SINGLE VALUE TRUE
36 * ID pkcs-9-at-extensionRequest
37 * }
38 * ExtensionRequest ::= Extensions
39 */
40 static BSL_ASN1_TemplateItem g_x509AttrTempl[] = {
41 {BSL_ASN1_TAG_OBJECT_ID, 0, 0},
42 {BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SET, BSL_ASN1_FLAG_HEADERONLY, 0},
43 };
44
45 typedef enum {
46 HITLS_X509_ATTR_OID_IDX,
47 HITLS_X509_ATTR_SET_IDX,
48 HITLS_X509_ATTR_INDEX_MAX
49 } HITLS_X509_ATTR_IDX;
50 #endif
51
52 #define HITLS_X509_ATTR_MAX_NUM 20
53 #define HITLS_X509_ATTRS_PARSE_FLAG 0x01
54 #define HITLS_X509_ATTRS_GEN_FLAG 0x02
55
HITLS_X509_AttrsNew(void)56 HITLS_X509_Attrs *HITLS_X509_AttrsNew(void)
57 {
58 HITLS_X509_Attrs *attrs = (HITLS_X509_Attrs *)BSL_SAL_Calloc(1, sizeof(HITLS_X509_Attrs));
59 if (attrs == NULL) {
60 return NULL;
61 }
62 attrs->list = BSL_LIST_New(sizeof(HITLS_X509_AttrEntry *));
63 if (attrs->list == NULL) {
64 BSL_SAL_Free(attrs);
65 return NULL;
66 }
67
68 attrs->flag = HITLS_X509_ATTRS_GEN_FLAG;
69 return attrs;
70 }
71
72 /*
73 * For pkcs12, parsing and encoding operation uses deep copy, and it use callback function to free
74 * For csr, parsing operation uses shallow copy, and encoding operation uses deep copy
75 */
HITLS_X509_AttrsFree(HITLS_X509_Attrs * attrs,HITLS_X509_FreeAttrItemCb freeItem)76 void HITLS_X509_AttrsFree(HITLS_X509_Attrs *attrs, HITLS_X509_FreeAttrItemCb freeItem)
77 {
78 if (attrs == NULL) {
79 return;
80 }
81 if (freeItem != NULL) {
82 BSL_LIST_FREE(attrs->list, (BSL_LIST_PFUNC_FREE)freeItem);
83 BSL_SAL_Free(attrs);
84 return;
85 }
86
87 if ((attrs->flag & HITLS_X509_ATTRS_PARSE_FLAG) != 0) {
88 BSL_LIST_FREE(attrs->list, NULL);
89 } else {
90 BSL_LIST_FREE(attrs->list, (BSL_LIST_PFUNC_FREE)HITLS_X509_AttrEntryFree);
91 }
92 BSL_SAL_Free(attrs);
93 }
94
95 #if defined(HITLS_PKI_X509_CSR_GEN) || defined(HITLS_PKI_PKCS12_GEN)
HITLS_X509_EncodeObjIdentity(BslCid cid,BSL_ASN1_Buffer * asnBuff)96 int32_t HITLS_X509_EncodeObjIdentity(BslCid cid, BSL_ASN1_Buffer *asnBuff)
97 {
98 BslOidString *oidStr = BSL_OBJ_GetOID(cid);
99 if (oidStr == NULL) {
100 BSL_ERR_PUSH_ERROR(CRYPT_ERR_ALGID);
101 return CRYPT_ERR_ALGID;
102 }
103 asnBuff->tag = BSL_ASN1_TAG_OBJECT_ID;
104 asnBuff->buff = (uint8_t *)oidStr->octs;
105 asnBuff->len = oidStr->octetLen;
106
107 return HITLS_PKI_SUCCESS;
108 }
109 #endif
110
111 #ifdef HITLS_PKI_PKCS12_GEN
HITLS_X509_AttrsDup(const HITLS_X509_Attrs * src,HITLS_X509_DupAttrItemCb dupCb,HITLS_X509_FreeAttrItemCb freeCb)112 HITLS_X509_Attrs *HITLS_X509_AttrsDup(const HITLS_X509_Attrs *src, HITLS_X509_DupAttrItemCb dupCb,
113 HITLS_X509_FreeAttrItemCb freeCb)
114 {
115 if (src == NULL || BSL_LIST_COUNT(src->list) <= 0 ||
116 dupCb == NULL || freeCb == NULL) {
117 return NULL;
118 }
119 HITLS_X509_Attrs *dst = HITLS_X509_AttrsNew();
120 if (dst == NULL) {
121 return NULL;
122 }
123 void *node = NULL;
124 for (node = BSL_LIST_GET_FIRST(src->list); node != NULL; node = BSL_LIST_GET_NEXT(src->list)) {
125 void *dstEntry = dupCb(node);
126 if (dstEntry == NULL) {
127 HITLS_X509_AttrsFree(dst, freeCb);
128 return NULL;
129 }
130 int32_t ret = BSL_LIST_AddElement(dst->list, dstEntry, BSL_LIST_POS_END);
131 if (ret != BSL_SUCCESS) {
132 freeCb(dstEntry);
133 HITLS_X509_AttrsFree(dst, freeCb);
134 return NULL;
135 }
136 }
137 dst->flag = src->flag;
138 return dst;
139 }
140 #endif
141
HITLS_X509_AttrEntryFree(HITLS_X509_AttrEntry * attr)142 void HITLS_X509_AttrEntryFree(HITLS_X509_AttrEntry *attr)
143 {
144 if (attr == NULL) {
145 return;
146 }
147 BSL_SAL_Free(attr->attrValue.buff);
148 BSL_SAL_Free(attr);
149 }
150
151 #if defined(HITLS_PKI_X509_CSR_PARSE) || defined(HITLS_PKI_PKCS12_PARSE)
HITLS_X509_ParseAttr(BSL_ASN1_Buffer * attrItem,HITLS_X509_AttrEntry * attrEntry)152 int32_t HITLS_X509_ParseAttr(BSL_ASN1_Buffer *attrItem, HITLS_X509_AttrEntry *attrEntry)
153 {
154 uint8_t *temp = attrItem->buff;
155 uint32_t tempLen = attrItem->len;
156 BSL_ASN1_Buffer asnArr[HITLS_X509_ATTR_INDEX_MAX] = {0};
157 BSL_ASN1_Template templ = {g_x509AttrTempl, sizeof(g_x509AttrTempl) / sizeof(g_x509AttrTempl[0])};
158 int32_t ret = BSL_ASN1_DecodeTemplate(&templ, NULL, &temp, &tempLen, asnArr, HITLS_X509_ATTR_INDEX_MAX);
159 if (tempLen != 0) {
160 ret = HITLS_X509_ERR_PARSE_ATTR_BUF;
161 }
162 if (ret != BSL_SUCCESS) {
163 BSL_ERR_PUSH_ERROR(ret);
164 return ret;
165 }
166 /* parse attribute id */
167 BslOidString oid = {asnArr[HITLS_X509_ATTR_OID_IDX].len, (char *)asnArr[HITLS_X509_ATTR_OID_IDX].buff, 0};
168 attrEntry->cid = BSL_OBJ_GetCID(&oid);
169 if (attrEntry->cid == BSL_CID_UNKNOWN) {
170 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_PARSE_OBJ_ID);
171 return HITLS_X509_ERR_PARSE_OBJ_ID;
172 }
173 /* set id and value asn1 buffer */
174 attrEntry->attrId = asnArr[HITLS_X509_ATTR_OID_IDX];
175 attrEntry->attrValue = asnArr[HITLS_X509_ATTR_SET_IDX];
176 return ret;
177 }
178
HITLS_X509_ParseAttrsListAsnItem(uint32_t layer,BSL_ASN1_Buffer * asn,void * cbParam,BSL_ASN1_List * list)179 int32_t HITLS_X509_ParseAttrsListAsnItem(uint32_t layer, BSL_ASN1_Buffer *asn, void *cbParam, BSL_ASN1_List *list)
180 {
181 (void)layer;
182 HITLS_X509_ParseAttrItemCb parseCb = cbParam;
183 HITLS_X509_AttrEntry *node = BSL_SAL_Calloc(1, sizeof(HITLS_X509_AttrEntry));
184 if (node == NULL) {
185 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
186 return BSL_MALLOC_FAIL;
187 }
188
189 /* parse attribute entry */
190 int32_t ret = HITLS_X509_ParseAttr(asn, node);
191 if (ret != BSL_SUCCESS) {
192 BSL_ERR_PUSH_ERROR(ret);
193 goto ERR;
194 }
195 if (parseCb != NULL) {
196 ret = parseCb(list, node);
197 if (ret != BSL_SUCCESS) {
198 BSL_ERR_PUSH_ERROR(ret);
199 }
200 goto ERR;
201 }
202
203 ret = BSL_LIST_AddElement(list, node, BSL_LIST_POS_AFTER);
204 if (ret != BSL_SUCCESS) {
205 BSL_ERR_PUSH_ERROR(ret);
206 goto ERR;
207 }
208
209 return ret;
210 ERR:
211 BSL_SAL_FREE(node);
212 return ret;
213 }
214
HITLS_X509_ParseAttrList(BSL_ASN1_Buffer * attrBuff,HITLS_X509_Attrs * attrs,HITLS_X509_ParseAttrItemCb parseCb,HITLS_X509_FreeAttrItemCb freeItem)215 int32_t HITLS_X509_ParseAttrList(BSL_ASN1_Buffer *attrBuff, HITLS_X509_Attrs *attrs, HITLS_X509_ParseAttrItemCb parseCb,
216 HITLS_X509_FreeAttrItemCb freeItem)
217 {
218 if (attrBuff->tag == 0 || attrBuff->buff == NULL || attrBuff->len == 0) {
219 return HITLS_PKI_SUCCESS;
220 }
221
222 uint8_t expTag[] = {BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SEQUENCE};
223 BSL_ASN1_DecodeListParam listParam = {1, expTag};
224 int32_t ret = BSL_ASN1_DecodeListItem(&listParam, attrBuff, &HITLS_X509_ParseAttrsListAsnItem, parseCb,
225 attrs->list);
226 if (ret != BSL_SUCCESS) {
227 BSL_LIST_DeleteAll(attrs->list, freeItem);
228 return ret;
229 }
230 attrs->flag = HITLS_X509_ATTRS_PARSE_FLAG;
231 return ret;
232 }
233 #endif
234
CmpAttrEntryByCid(const void * attrEntry,const void * cid)235 static int32_t CmpAttrEntryByCid(const void *attrEntry, const void *cid)
236 {
237 const HITLS_X509_AttrEntry *node = attrEntry;
238 return node->cid == *(const BslCid *)cid ? 0 : 1;
239 }
240
241 typedef int32_t (*DecodeAttrCb)(HITLS_X509_Attrs *attributes, HITLS_X509_AttrEntry *attrEntry, void *val,
242 uint32_t valLen);
243
244 #if defined(HITLS_PKI_X509_CSR_GEN) || defined(HITLS_PKI_PKCS12_GEN)
245
246 typedef int32_t (*EncodeAttrCb)(HITLS_X509_Attrs *attributes, void *val, uint32_t valLen, BSL_ASN1_Buffer *attrValue);
247
EncodeReqExtAttr(HITLS_X509_Attrs * attributes,void * val,uint32_t valLen,BSL_ASN1_Buffer * attrValue)248 static int32_t EncodeReqExtAttr(HITLS_X509_Attrs *attributes, void *val, uint32_t valLen, BSL_ASN1_Buffer *attrValue)
249 {
250 (void)valLen;
251 (void)attributes;
252 HITLS_X509_Ext *ext = (HITLS_X509_Ext *)val;
253 return HITLS_X509_EncodeExt(BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SET, ext->extList, attrValue);
254 }
255
SetAttr(HITLS_X509_Attrs * attributes,BslCid cid,void * val,uint32_t valLen,EncodeAttrCb encodeAttrCb)256 static int32_t SetAttr(HITLS_X509_Attrs *attributes, BslCid cid, void *val, uint32_t valLen, EncodeAttrCb encodeAttrCb)
257 {
258 if (val == NULL) {
259 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_INVALID_PARAM);
260 return HITLS_X509_ERR_INVALID_PARAM;
261 }
262
263 /* Check if the attribute already exists. */
264 if (BSL_LIST_Search(attributes->list, &cid, CmpAttrEntryByCid, NULL) != NULL) {
265 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_SET_ATTR_REPEAT);
266 return HITLS_X509_ERR_SET_ATTR_REPEAT;
267 }
268
269 HITLS_X509_AttrEntry *attrEntry = BSL_SAL_Calloc(1, sizeof(HITLS_X509_AttrEntry));
270 if (attrEntry == NULL) {
271 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
272 return BSL_MALLOC_FAIL;
273 }
274 int32_t ret = HITLS_X509_EncodeObjIdentity(cid, &attrEntry->attrId);
275 if (ret != HITLS_PKI_SUCCESS) {
276 BSL_ERR_PUSH_ERROR(ret);
277 goto ERR;
278 }
279
280 ret = encodeAttrCb(attributes, val, valLen, &attrEntry->attrValue);
281 if (ret != HITLS_PKI_SUCCESS) {
282 BSL_ERR_PUSH_ERROR(ret);
283 goto ERR;
284 }
285 attrEntry->cid = cid;
286 ret = BSL_LIST_AddElement(attributes->list, attrEntry, BSL_LIST_POS_END);
287 if (ret != BSL_SUCCESS) {
288 BSL_ERR_PUSH_ERROR(ret);
289 goto ERR;
290 }
291
292 return ret;
293
294 ERR:
295 HITLS_X509_AttrEntryFree(attrEntry);
296 return ret;
297 }
298 #endif // HITLS_PKI_X509_CSR_GEN || HITLS_PKI_PKCS12_GEN
299
DecodeReqExtAttr(HITLS_X509_Attrs * attributes,HITLS_X509_AttrEntry * attrEntry,void * val,uint32_t valLen)300 static int32_t DecodeReqExtAttr(HITLS_X509_Attrs *attributes, HITLS_X509_AttrEntry *attrEntry, void *val,
301 uint32_t valLen)
302 {
303 (void)attributes;
304 if (valLen != sizeof(HITLS_X509_Ext *)) {
305 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_INVALID_PARAM);
306 return HITLS_X509_ERR_INVALID_PARAM;
307 }
308 HITLS_X509_Ext *ext = HITLS_X509_ExtNew(HITLS_X509_EXT_TYPE_CSR);
309 if (ext == NULL) {
310 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
311 return BSL_MALLOC_FAIL;
312 }
313 int32_t ret = HITLS_X509_ParseExt(&attrEntry->attrValue, ext);
314 if (ret != BSL_SUCCESS) {
315 HITLS_X509_ExtFree(ext);
316 BSL_ERR_PUSH_ERROR(ret);
317 return ret;
318 }
319 *(HITLS_X509_Ext **)val = ext;
320 return HITLS_PKI_SUCCESS;
321 }
322
GetAttr(HITLS_X509_Attrs * attributes,BslCid cid,void * val,uint32_t valLen,DecodeAttrCb decodeAttrCb)323 static int32_t GetAttr(HITLS_X509_Attrs *attributes, BslCid cid, void *val, uint32_t valLen, DecodeAttrCb decodeAttrCb)
324 {
325 if (val == NULL) {
326 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_INVALID_PARAM);
327 return HITLS_X509_ERR_INVALID_PARAM;
328 }
329
330 HITLS_X509_AttrEntry *attrEntry = BSL_LIST_Search(attributes->list, &cid, CmpAttrEntryByCid, NULL);
331 if (attrEntry == NULL) {
332 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_ATTR_NOT_FOUND);
333 return HITLS_X509_ERR_ATTR_NOT_FOUND;
334 }
335
336 return decodeAttrCb(attributes, attrEntry, val, valLen);
337 }
338
HITLS_X509_AttrCtrl(HITLS_X509_Attrs * attributes,HITLS_X509_AttrCmd cmd,void * val,uint32_t valLen)339 int32_t HITLS_X509_AttrCtrl(HITLS_X509_Attrs *attributes, HITLS_X509_AttrCmd cmd, void *val, uint32_t valLen)
340 {
341 if (attributes == NULL || val == NULL) {
342 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_INVALID_PARAM);
343 return HITLS_X509_ERR_INVALID_PARAM;
344 }
345 switch (cmd) {
346 #if defined(HITLS_PKI_X509_CSR_GEN) || defined(HITLS_PKI_PKCS12_GEN)
347 case HITLS_X509_ATTR_SET_REQUESTED_EXTENSIONS:
348 return SetAttr(attributes, BSL_CID_EXTENSIONREQUEST, val, valLen, EncodeReqExtAttr);
349 #endif
350 case HITLS_X509_ATTR_GET_REQUESTED_EXTENSIONS:
351 return GetAttr(attributes, BSL_CID_EXTENSIONREQUEST, val, valLen, DecodeReqExtAttr);
352 default:
353 BSL_ERR_PUSH_ERROR(HITLS_X509_ERR_INVALID_PARAM);
354 return HITLS_X509_ERR_INVALID_PARAM;
355 }
356 }
357
358 #if defined(HITLS_PKI_X509_CSR_GEN) || defined(HITLS_PKI_PKCS12_GEN)
359
360 #define X509_CSR_ATTR_ELEM_NUMBER 2
361 static BSL_ASN1_TemplateItem g_x509AttrEntryTempl[] = {
362 {BSL_ASN1_TAG_OBJECT_ID, 0, 0},
363 {BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SET, 0, 0},
364 };
365
HITLS_X509_EncodeAttrEntry(HITLS_X509_AttrEntry * node,BSL_ASN1_Buffer * attrBuff)366 int32_t HITLS_X509_EncodeAttrEntry(HITLS_X509_AttrEntry *node, BSL_ASN1_Buffer *attrBuff)
367 {
368 BSL_ASN1_Buffer asnBuf[X509_CSR_ATTR_ELEM_NUMBER] = {0};
369 asnBuf[0] = node->attrId;
370 asnBuf[1] = node->attrValue;
371 BSL_ASN1_Template templ = {g_x509AttrEntryTempl, sizeof(g_x509AttrEntryTempl) / sizeof(g_x509AttrEntryTempl[0])};
372 int32_t ret = BSL_ASN1_EncodeTemplate(&templ, asnBuf, X509_CSR_ATTR_ELEM_NUMBER, &attrBuff->buff, &attrBuff->len);
373 if (ret != HITLS_PKI_SUCCESS) {
374 BSL_ERR_PUSH_ERROR(ret);
375 return ret;
376 }
377 attrBuff->tag = BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SEQUENCE;
378 return ret;
379 }
380
FreeAsnAttrsBuff(BSL_ASN1_Buffer * asnBuf,uint32_t count)381 void FreeAsnAttrsBuff(BSL_ASN1_Buffer *asnBuf, uint32_t count)
382 {
383 for (uint32_t i = 0; i < count; i++) {
384 BSL_SAL_FREE(asnBuf[i].buff);
385 }
386 BSL_SAL_FREE(asnBuf);
387 }
388
HITLS_X509_EncodeAttrList(uint8_t tag,HITLS_X509_Attrs * attrs,HITLS_X509_EncodeAttrItemCb encodeCb,BSL_ASN1_Buffer * attrAsn1)389 int32_t HITLS_X509_EncodeAttrList(uint8_t tag, HITLS_X509_Attrs *attrs, HITLS_X509_EncodeAttrItemCb encodeCb,
390 BSL_ASN1_Buffer *attrAsn1)
391 {
392 if (attrs == NULL || attrs->list == NULL || BSL_LIST_COUNT(attrs->list) <= 0) {
393 attrAsn1->tag = tag;
394 attrAsn1->buff = NULL;
395 attrAsn1->len = 0;
396 return HITLS_PKI_SUCCESS;
397 }
398 uint32_t count = (uint32_t)BSL_LIST_COUNT(attrs->list);
399 /* no attribute */
400 BSL_ASN1_Buffer *asnBuf = BSL_SAL_Calloc(count, sizeof(BSL_ASN1_Buffer));
401 if (asnBuf == NULL) {
402 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
403 return BSL_MALLOC_FAIL;
404 }
405 uint32_t iter = 0;
406 int32_t ret;
407 void *node = NULL;
408 for (node = BSL_LIST_GET_FIRST(attrs->list); node != NULL; node = BSL_LIST_GET_NEXT(attrs->list), iter++) {
409 HITLS_X509_AttrEntry attrEntry = {};
410 if (encodeCb != NULL) {
411 ret = encodeCb(node, &attrEntry);
412 if (ret != HITLS_PKI_SUCCESS) {
413 FreeAsnAttrsBuff(asnBuf, count);
414 return ret;
415 }
416 } else {
417 attrEntry = *(HITLS_X509_AttrEntry *)node;
418 }
419 ret = HITLS_X509_EncodeAttrEntry(&attrEntry, &asnBuf[iter]);
420 if (encodeCb != NULL) {
421 BSL_SAL_FREE(attrEntry.attrValue.buff);
422 }
423 if (ret != HITLS_PKI_SUCCESS) {
424 FreeAsnAttrsBuff(asnBuf, count);
425 return ret;
426 }
427 }
428 static BSL_ASN1_TemplateItem attrSeqTempl = {BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SEQUENCE, 0, 0 };
429 BSL_ASN1_Template templ = {&attrSeqTempl, 1};
430 ret = BSL_ASN1_EncodeListItem(BSL_ASN1_TAG_SEQUENCE, count, &templ, asnBuf, iter, attrAsn1);
431 FreeAsnAttrsBuff(asnBuf, count);
432 if (ret != HITLS_PKI_SUCCESS) {
433 BSL_ERR_PUSH_ERROR(ret);
434 return ret;
435 }
436
437 attrAsn1->tag = tag;
438 return ret;
439 }
440 #endif // HITLS_PKI_X509_CSR_GEN || HITLS_PKI_PKCS12_GEN
441
442 #endif // HITLS_PKI_X509_CSR || HITLS_PKI_PKCS12
443