1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "cf_adapter_extension_openssl.h"
17
18 #include <openssl/asn1.h>
19 #include <openssl/bio.h>
20 #include <openssl/err.h>
21 #include <openssl/evp.h>
22 #include <openssl/pem.h>
23 #include <openssl/x509v3.h>
24
25 #include "securec.h"
26
27 #include "cf_check.h"
28 #include "cf_log.h"
29 #include "cf_magic.h"
30 #include "cf_memory.h"
31 #include "cf_result.h"
32
33 #define KEYUSAGE_SHIFT 8
34 #define CRITICAL_SIZE 1
35
36 typedef struct {
37 char *oid;
38 char *extensionName;
39 } OidToExtensionName;
40
41 static const OidToExtensionName OID_TO_EXT_NAME_MAP[] = {
42 { "2.5.29.9", "SubjectDirectoryAttributes" },
43 { "2.5.29.14", "SubjectKeyIdentifier" },
44 { "2.5.29.15", "KeyUsage" },
45 { "2.5.29.16", "PrivateKeyUsage" },
46 { "2.5.29.17", "SubjectAlternativeName" },
47 { "2.5.29.18", "IssuerAlternativeName" },
48 { "2.5.29.19", "BasicConstraints" },
49 { "2.5.29.20", "CRLNumber" },
50 { "2.5.29.21", "CRLReason" },
51 { "2.5.29.23", "HoldInstructionCode" },
52 { "2.5.29.24", "InvalidityDate" },
53 { "2.5.29.27", "DeltaCRLIndicator" },
54 { "2.5.29.28", "IssuingDistributionPoint" },
55 { "2.5.29.29", "CertificateIssuer" },
56 { "2.5.29.30", "NameConstraints" },
57 { "2.5.29.31", "CRLDistributionPoints" },
58 { "2.5.29.32", "CertificatePolicies" },
59 { "2.5.29.33", "PolicyMappings" },
60 { "2.5.29.35", "AuthorityKeyIdentifier" },
61 { "2.5.29.36", "PolicyConstraints" },
62 { "2.5.29.37", "ExtendedKeyUsage" },
63 { "2.5.29.46", "FreshestCRL" },
64 { "2.5.29.54", "InhibitAnyPolicy" },
65 { "1.3.6.1.5.5.7.1.1", "AuthInfoAccess" },
66 { "1.3.6.1.5.5.7.1.11", "SubjectInfoAccess" },
67 { "1.3.6.1.5.5.7.48.1.5", "OCSPNoCheck" },
68 { "2.16.840.1.113730.1.1", "NETSCAPECert" }
69 };
70
CfOpensslCreateExtension(const CfEncodingBlob * inData,CfBase ** object)71 int32_t CfOpensslCreateExtension(const CfEncodingBlob *inData, CfBase **object)
72 {
73 if ((CfCheckEncodingBlob(inData, MAX_LEN_EXTENSIONS) != CF_SUCCESS) ||
74 (inData->encodingFormat != CF_FORMAT_DER) || (object == NULL)) {
75 CF_LOG_E("invalid input params");
76 return CF_INVALID_PARAMS;
77 }
78
79 CfOpensslExtensionObj *extsObj = CfMalloc(sizeof(CfOpensslExtensionObj), 0);
80 if (extsObj == NULL) {
81 CF_LOG_E("malloc failed");
82 return CF_ERR_MALLOC;
83 }
84 extsObj->base.type = CF_MAGIC(CF_MAGIC_TYPE_ADAPTER_RESOURCE, CF_OBJ_TYPE_EXTENSION);
85
86 uint8_t *end = inData->data; /* data pointer will shift downward in d2i_X509_EXTENSIONS */
87 extsObj->exts = d2i_X509_EXTENSIONS(NULL, (const unsigned char **)&end, inData->len);
88 if (extsObj->exts == NULL) {
89 CF_LOG_E("Failed to get internal extension");
90 CfFree(extsObj);
91 extsObj = NULL;
92 return CF_ERR_CRYPTO_OPERATION;
93 }
94
95 if (end != (inData->data + inData->len)) { /* Tainted extension data: valid part + invalid part */
96 CF_LOG_E("The extension indata is invalid");
97 sk_X509_EXTENSION_pop_free(extsObj->exts, X509_EXTENSION_free);
98 CfFree(extsObj);
99 extsObj = NULL;
100 return CF_ERR_CRYPTO_OPERATION;
101 }
102
103 *object = &extsObj->base;
104 return CF_SUCCESS;
105 }
106
CfOpensslDestoryExtension(CfBase ** object)107 void CfOpensslDestoryExtension(CfBase **object)
108 {
109 if ((object == NULL) || (*object == NULL)) {
110 CF_LOG_E("invalid input params");
111 return;
112 }
113
114 CfOpensslExtensionObj *extsObj = (CfOpensslExtensionObj *)*object;
115 if (extsObj->base.type != CF_MAGIC(CF_MAGIC_TYPE_ADAPTER_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
116 CF_LOG_E("the object is invalid , type = %{public}lu", extsObj->base.type);
117 return;
118 }
119
120 if (extsObj->exts != NULL) {
121 sk_X509_EXTENSION_pop_free(extsObj->exts, X509_EXTENSION_free);
122 }
123 CfFree(extsObj);
124 *object = NULL;
125 return;
126 }
127
CheckObjectAndGetExts(const CfBase * object,X509_EXTENSIONS ** exts)128 static int32_t CheckObjectAndGetExts(const CfBase *object, X509_EXTENSIONS **exts)
129 {
130 CfOpensslExtensionObj *extsObj = (CfOpensslExtensionObj *)object;
131 if (extsObj->base.type != CF_MAGIC(CF_MAGIC_TYPE_ADAPTER_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
132 CF_LOG_E("the object is invalid , type = %{public}lu", extsObj->base.type);
133 return CF_INVALID_PARAMS;
134 }
135
136 if (extsObj->exts == NULL) {
137 CF_LOG_E("extension is null");
138 return CF_INVALID_PARAMS;
139 }
140
141 *exts = extsObj->exts;
142 return CF_SUCCESS;
143 }
144
CopyIndexArray(uint32_t * destArray,uint32_t * destLen,const uint32_t * srcArray,uint32_t srcLen)145 static int32_t CopyIndexArray(uint32_t *destArray, uint32_t *destLen, const uint32_t *srcArray, uint32_t srcLen)
146 {
147 if (memcpy_s(destArray, ((*destLen) * sizeof(uint32_t)), srcArray, (srcLen * sizeof(uint32_t))) != EOK) {
148 CF_LOG_E("Failed to copy index array");
149 return CF_ERR_COPY;
150 }
151 *destLen = srcLen;
152 return CF_SUCCESS;
153 }
154
GetExtensionIndexArray(const X509_EXTENSIONS * exts,CfExtensionOidType type,uint32_t * array,uint32_t * arrayLen)155 static int32_t GetExtensionIndexArray(const X509_EXTENSIONS *exts, CfExtensionOidType type,
156 uint32_t *array, uint32_t *arrayLen)
157 {
158 int32_t extNums = sk_X509_EXTENSION_num(exts);
159 if ((extNums <= 0) || (extNums > MAX_COUNT_OID)) {
160 CF_LOG_E("Failed to get extension numbers");
161 return CF_ERR_CRYPTO_OPERATION;
162 }
163
164 uint32_t allOidArray[MAX_COUNT_OID] = { 0 }; /* type: CF_EXT_TYPE_ALL_OIDS */
165 uint32_t critOidArray[MAX_COUNT_OID] = { 0 }; /* type: CF_EXT_TYPE_CRITICAL_OIDS */
166 uint32_t uncritOidArray[MAX_COUNT_OID] = { 0 }; /* type: CF_EXT_TYPE_UNCRITICAL_OIDS */
167 uint32_t critCnt = 0;
168 uint32_t uncritCnt = 0;
169
170 for (uint32_t i = 0; i < (uint32_t)extNums; ++i) {
171 allOidArray[i] = i;
172
173 X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i);
174 if (ex == NULL) {
175 CF_LOG_E("Failed to get exts [%{public}u] value", i);
176 return CF_ERR_CRYPTO_OPERATION;
177 }
178
179 int crit = X509_EXTENSION_get_critical(ex);
180 if (crit == 1) {
181 critOidArray[critCnt++] = i;
182 } else {
183 uncritOidArray[uncritCnt++] = i;
184 }
185 }
186
187 switch (type) {
188 case CF_EXT_TYPE_ALL_OIDS:
189 return CopyIndexArray(array, arrayLen, allOidArray, (uint32_t)extNums);
190 case CF_EXT_TYPE_CRITICAL_OIDS:
191 return CopyIndexArray(array, arrayLen, critOidArray, critCnt);
192 case CF_EXT_TYPE_UNCRITICAL_OIDS:
193 return CopyIndexArray(array, arrayLen, uncritOidArray, uncritCnt);
194 default:
195 CF_LOG_E("type is invalid");
196 return CF_INVALID_PARAMS;
197 }
198 }
199
DeepCopyDataToOutblob(const char * data,uint32_t len,CfBlob * outBlob)200 static int32_t DeepCopyDataToOutblob(const char *data, uint32_t len, CfBlob *outBlob)
201 {
202 outBlob->data = (uint8_t *)CfMalloc(len, 0);
203 if (outBlob->data == NULL) {
204 CF_LOG_E("Failed to malloc");
205 return CF_ERR_MALLOC;
206 }
207 (void)memcpy_s(outBlob->data, len, data, len);
208 outBlob->size = len;
209 return CF_SUCCESS;
210 }
211
DeepCopyOidsToOut(const X509_EXTENSIONS * exts,const uint32_t * idxArray,uint32_t arrayLen,CfBlobArray * out)212 static int32_t DeepCopyOidsToOut(const X509_EXTENSIONS *exts, const uint32_t *idxArray, uint32_t arrayLen,
213 CfBlobArray *out)
214 {
215 uint32_t memSize = sizeof(CfBlob) * arrayLen;
216 CfBlob *dataArray = (CfBlob *)CfMalloc(memSize, 0);
217 if (dataArray == NULL) {
218 CF_LOG_E("Failed to malloc");
219 return CF_ERR_MALLOC;
220 }
221
222 for (uint32_t i = 0; i < arrayLen; ++i) {
223 uint32_t index = idxArray[i];
224
225 X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, index);
226 if (ex == NULL) {
227 CF_LOG_E("Failed to get exts [%{public}u] value", index);
228 FreeCfBlobArray(dataArray, i);
229 dataArray = NULL;
230 return CF_ERR_CRYPTO_OPERATION;
231 }
232
233 char oid[MAX_LEN_OID] = { 0 };
234 int32_t oidLen = OBJ_obj2txt(oid, MAX_LEN_OID, X509_EXTENSION_get_object(ex), 1);
235 if ((oidLen <= 0) || (oidLen >= MAX_LEN_OID)) {
236 CF_LOG_E("Failed to get oid[%{public}u]", index);
237 FreeCfBlobArray(dataArray, i);
238 dataArray = NULL;
239 return CF_ERR_CRYPTO_OPERATION;
240 }
241
242 int32_t ret = DeepCopyDataToOutblob(oid, strlen(oid), &dataArray[i]);
243 if (ret != CF_SUCCESS) {
244 CF_LOG_E("Failed to copy oid[%{public}u]", index);
245 FreeCfBlobArray(dataArray, i);
246 dataArray = NULL;
247 return ret;
248 }
249 }
250
251 out->data = dataArray;
252 out->count = arrayLen;
253 return CF_SUCCESS;
254 }
255
CfOpensslGetOids(const CfBase * object,CfExtensionOidType type,CfBlobArray * out)256 int32_t CfOpensslGetOids(const CfBase *object, CfExtensionOidType type, CfBlobArray *out)
257 {
258 if ((object == NULL) || (out == NULL)) {
259 CF_LOG_E("invalid input params");
260 return CF_INVALID_PARAMS;
261 }
262
263 X509_EXTENSIONS *exts = NULL;
264 int32_t ret = CheckObjectAndGetExts(object, &exts);
265 if (ret != CF_SUCCESS) {
266 CF_LOG_E("Failed to get extension");
267 return ret;
268 }
269
270 uint32_t idxArray[MAX_COUNT_OID] = { 0 }; /* extension index array for target CfExtensionOidType */
271 uint32_t count = MAX_COUNT_OID;
272 ret = GetExtensionIndexArray(exts, type, idxArray, &count);
273 if (ret != CF_SUCCESS) {
274 CF_LOG_E("Failed to get extension index array");
275 return ret;
276 }
277
278 ret = DeepCopyOidsToOut(exts, idxArray, count, out);
279 if (ret != CF_SUCCESS) {
280 CF_LOG_E("Failed to copy oids to out");
281 return ret;
282 }
283 return CF_SUCCESS;
284 }
285
CfOpensslHasUnsupportedCriticalExtension(const CfBase * object,bool * out)286 int32_t CfOpensslHasUnsupportedCriticalExtension(const CfBase *object, bool *out)
287 {
288 if (object == NULL || out == NULL) {
289 CF_LOG_E("invalid input params");
290 return CF_INVALID_PARAMS;
291 }
292
293 X509_EXTENSIONS *exts = NULL;
294 int32_t ret = CheckObjectAndGetExts(object, &exts);
295 if (ret != CF_SUCCESS) {
296 CF_LOG_E("Failed to get extension");
297 return ret;
298 }
299
300 int32_t extNums = sk_X509_EXTENSION_num(exts);
301 if ((extNums <= 0) || (extNums > MAX_COUNT_OID)) {
302 CF_LOG_E("Failed to get extension numbers, extNums = %{public}d", extNums);
303 return CF_ERR_CRYPTO_OPERATION;
304 }
305
306 for (uint32_t i = 0; i < (uint32_t)extNums; ++i) {
307 X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i);
308 if (ex == NULL) {
309 CF_LOG_E("Failed to get exts [%{public}u] value", i);
310 return CF_ERR_CRYPTO_OPERATION;
311 }
312
313 int crit = X509_EXTENSION_get_critical(ex);
314 if (crit != 1) { /* the extension entry is critical */
315 continue;
316 }
317
318 char oid[MAX_LEN_OID] = { 0 };
319 int32_t oidLen = OBJ_obj2txt(oid, MAX_LEN_OID, X509_EXTENSION_get_object(ex), 1);
320 if ((oidLen <= 0) || (oidLen >= MAX_LEN_OID)) {
321 CF_LOG_E("Failed to get ext oid");
322 return CF_ERR_CRYPTO_OPERATION;
323 }
324 uint32_t oidsCount = sizeof(OID_TO_EXT_NAME_MAP) / sizeof(OidToExtensionName);
325 bool match = false;
326 for (uint32_t oidInd = 0; oidInd < oidsCount; oidInd++) {
327 if (strcmp(OID_TO_EXT_NAME_MAP[oidInd].oid, oid) == 0) {
328 match = true;
329 break;
330 }
331 }
332 if (!match) {
333 CF_LOG_I("extension oid [%{public}s] is not supported.", oid);
334 *out = true;
335 return CF_SUCCESS;
336 }
337 }
338 *out = false;
339 return CF_SUCCESS;
340 }
341
GetTargetNid(const CfBlob * oid,int * nid)342 static int GetTargetNid(const CfBlob *oid, int *nid)
343 {
344 uint32_t length = oid->size + 1; /* add '\0' in the end */
345 uint8_t *oidString = (uint8_t *)CfMalloc(length, 0);
346 if (oidString == NULL) {
347 CF_LOG_E("Failed to malloc oid string");
348 return CF_ERR_MALLOC;
349 }
350
351 if (memcpy_s(oidString, length, oid->data, oid->size) != EOK) {
352 CF_LOG_E("Failed to copy oid string");
353 CfFree(oidString);
354 oidString = NULL;
355 return CF_ERR_COPY;
356 }
357
358 *nid = OBJ_txt2nid((char *)oidString);
359 CfFree(oidString);
360 oidString = NULL;
361 return CF_SUCCESS;
362 }
363
FoundExtMatchedNid(const X509_EXTENSIONS * exts,int targetNid,X509_EXTENSION ** found)364 static int32_t FoundExtMatchedNid(const X509_EXTENSIONS *exts, int targetNid, X509_EXTENSION **found)
365 {
366 int32_t extNums = sk_X509_EXTENSION_num(exts);
367 if ((extNums <= 0) || (extNums > MAX_COUNT_OID)) {
368 CF_LOG_E("Failed to get extension numbers");
369 return CF_ERR_CRYPTO_OPERATION;
370 }
371
372 for (int i = 0; i < extNums; ++i) {
373 X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i);
374 if (ex == NULL) {
375 CF_LOG_E("Failed to get exts [%{public}d] value", i);
376 return CF_ERR_CRYPTO_OPERATION;
377 }
378
379 int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
380 if (nid == NID_undef) {
381 CF_LOG_E("nid undefined");
382 return CF_ERR_CRYPTO_OPERATION;
383 }
384
385 if (targetNid == nid) {
386 *found = ex;
387 return CF_SUCCESS;
388 }
389 }
390 CF_LOG_E("no found target nid.");
391 return CF_NOT_EXIST;
392 }
393
GetEntry(const X509_EXTENSION * found,CfBlob * out)394 static int32_t GetEntry(const X509_EXTENSION *found, CfBlob *out)
395 {
396 unsigned char *entry = NULL;
397 int entryLen = i2d_X509_EXTENSION((X509_EXTENSION *)found, &entry);
398 if (entryLen <= 0) {
399 CF_LOG_E("Failed to get entry");
400 return CF_ERR_CRYPTO_OPERATION;
401 }
402
403 int32_t ret = DeepCopyDataToOutblob((const char *)entry, entryLen, out);
404 OPENSSL_free(entry);
405 return ret;
406 }
407
GetEntryCritical(const X509_EXTENSION * found,CfBlob * out)408 static int32_t GetEntryCritical(const X509_EXTENSION *found, CfBlob *out)
409 {
410 out->data = (uint8_t *)CfMalloc(CRITICAL_SIZE, 0); /* critical value is 0 or 1 */
411 if (out->data == NULL) {
412 CF_LOG_E("Failed to malloc");
413 return CF_ERR_MALLOC;
414 }
415 out->size = CRITICAL_SIZE;
416
417 int crit = X509_EXTENSION_get_critical(found);
418 if (crit == 1) {
419 out->data[0] = 1;
420 } else {
421 out->data[0] = 0;
422 }
423
424 return CF_SUCCESS;
425 }
426
GetEntryValue(const X509_EXTENSION * found,CfBlob * out)427 static int32_t GetEntryValue(const X509_EXTENSION *found, CfBlob *out)
428 {
429 /* return internal value: extension data */
430 ASN1_OCTET_STRING *octetString = X509_EXTENSION_get_data((X509_EXTENSION *)found);
431 if (octetString == NULL) {
432 CF_LOG_E("Failed to get entry value");
433 return CF_ERR_CRYPTO_OPERATION;
434 }
435
436 unsigned char *entryValue = NULL;
437 int entryValueLen = i2d_ASN1_OCTET_STRING(octetString, &entryValue);
438 if (entryValueLen <= 0) {
439 CF_LOG_E("Failed to get entry value len");
440 return CF_ERR_CRYPTO_OPERATION;
441 }
442
443 int32_t ret = DeepCopyDataToOutblob((char *)entryValue, entryValueLen, out);
444 OPENSSL_free(entryValue);
445 return ret;
446 }
447
GetMatchedEntry(const X509_EXTENSION * found,CfExtensionEntryType type,CfBlob * out)448 static int32_t GetMatchedEntry(const X509_EXTENSION *found, CfExtensionEntryType type, CfBlob *out)
449 {
450 switch (type) {
451 case CF_EXT_ENTRY_TYPE_ENTRY:
452 return GetEntry(found, out);
453 case CF_EXT_ENTRY_TYPE_ENTRY_CRITICAL:
454 return GetEntryCritical(found, out);
455 case CF_EXT_ENTRY_TYPE_ENTRY_VALUE:
456 return GetEntryValue(found, out);
457 default:
458 CF_LOG_E("type id invalid");
459 return CF_INVALID_PARAMS;
460 }
461 }
462
CfOpensslGetEntry(const CfBase * object,CfExtensionEntryType type,const CfBlob * oid,CfBlob * out)463 int32_t CfOpensslGetEntry(const CfBase *object, CfExtensionEntryType type, const CfBlob *oid, CfBlob *out)
464 {
465 if ((object == NULL) || (out == NULL) || (CfCheckBlob(oid, MAX_LEN_OID) != CF_SUCCESS)) {
466 CF_LOG_E("invalid input params");
467 return CF_INVALID_PARAMS;
468 }
469
470 X509_EXTENSIONS *exts = NULL;
471 int32_t ret = CheckObjectAndGetExts(object, &exts);
472 if (ret != CF_SUCCESS) {
473 CF_LOG_E("Failed to get extension");
474 return ret;
475 }
476
477 /* get target nid from oid */
478 int targetNid;
479 ret = GetTargetNid(oid, &targetNid);
480 if ((ret != CF_SUCCESS) || (targetNid == NID_undef)) {
481 CF_LOG_E("nid is undefined");
482 ret = (ret == CF_SUCCESS) ? CF_INVALID_PARAMS : ret;
483 return ret;
484 }
485
486 /* found one extension matched target nid in extensions */
487 X509_EXTENSION *found = NULL;
488 ret = FoundExtMatchedNid(exts, targetNid, &found);
489 if (ret != CF_SUCCESS) {
490 CF_LOG_E("call FoundExtMatchedNid failed.");
491 return ret;
492 }
493
494 /* get entry from matched extension for target type */
495 ret = GetMatchedEntry(found, type, out);
496 if (ret != CF_SUCCESS) {
497 CF_LOG_E("Failed to get matched entry");
498 return ret;
499 }
500 return CF_SUCCESS;
501 }
502
CheckKeyUsage(const X509_EXTENSIONS * exts,int32_t * pathLen)503 static int32_t CheckKeyUsage(const X509_EXTENSIONS *exts, int32_t *pathLen)
504 {
505 ASN1_BIT_STRING *usage = (ASN1_BIT_STRING *)X509V3_get_d2i(exts, NID_key_usage, NULL, NULL);
506 if (usage == NULL) {
507 CF_LOG_E("Failed to get usage");
508 return CF_ERR_CRYPTO_OPERATION;
509 }
510
511 uint32_t keyUsage = (uint32_t)usage->data[0];
512 if (usage->length > 1) {
513 keyUsage |= ((uint32_t)usage->data[1] << KEYUSAGE_SHIFT);
514 }
515
516 /* keyUsage of a CA cert: sign */
517 if ((keyUsage & KU_KEY_CERT_SIGN) == 0) {
518 CF_LOG_I("this cert not a CA");
519 *pathLen = BASIC_CONSTRAINTS_NO_CA;
520 }
521
522 ASN1_BIT_STRING_free(usage);
523 return CF_SUCCESS;
524 }
525
CheckBasicConstraints(const X509_EXTENSIONS * exts,int32_t * pathLen)526 static int32_t CheckBasicConstraints(const X509_EXTENSIONS *exts, int32_t *pathLen)
527 {
528 BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509V3_get_d2i(exts, NID_basic_constraints, NULL, NULL);
529 if (bs == NULL) {
530 CF_LOG_E("Failed to get basic constraints");
531 return CF_ERR_CRYPTO_OPERATION;
532 }
533
534 int32_t ret = CF_SUCCESS;
535 do {
536 if (!bs->ca) {
537 CF_LOG_I("this cert not a CA");
538 /* CheckCA operation is success, but cert is not a CA, pathLen set -1 */
539 *pathLen = BASIC_CONSTRAINTS_NO_CA;
540 ret = CF_SUCCESS;
541 break;
542 }
543
544 if ((bs->pathlen == NULL) || (bs->pathlen->type == V_ASN1_NEG_INTEGER)) {
545 CF_LOG_I("this cert pathlen no limit");
546 /* CheckCA operation is success and cert is a CA, but no limit to pathlen, pathLen set -2 */
547 *pathLen = BASIC_CONSTRAINTS_PATHLEN_NO_LIMIT;
548 ret = CF_SUCCESS;
549 break;
550 }
551
552 long len = ASN1_INTEGER_get(bs->pathlen);
553 if ((len < 0) || (len > INT_MAX)) { /* CheckCA operation is exceptional, pathlen is invalid */
554 CF_LOG_E("this cert pathlen is invalid");
555 ret = CF_ERR_CRYPTO_OPERATION;
556 break;
557 }
558 *pathLen = (int32_t)len;
559 } while (0);
560
561 BASIC_CONSTRAINTS_free(bs);
562 return ret;
563 }
564
CfOpensslCheckCA(const CfBase * object,int32_t * pathLen)565 int32_t CfOpensslCheckCA(const CfBase *object, int32_t *pathLen)
566 {
567 if ((object == NULL) || (pathLen == NULL)) {
568 CF_LOG_E("invalid input params");
569 return CF_INVALID_PARAMS;
570 }
571
572 X509_EXTENSIONS *exts = NULL;
573 int32_t ret = CheckObjectAndGetExts(object, &exts);
574 if (ret != CF_SUCCESS) {
575 CF_LOG_E("Failed to get extension");
576 return ret;
577 }
578
579 *pathLen = 0;
580 ret = CheckKeyUsage(exts, pathLen);
581 if (ret != CF_SUCCESS) {
582 CF_LOG_E("Failed to check keyUsage");
583 return ret;
584 }
585 if (*pathLen != 0) { /* checkKeyUsage operation success, but cert has no signing purpose, pathLen set -1. */
586 CF_LOG_I("Return: this cert not a CA");
587 return ret;
588 }
589
590 ret = CheckBasicConstraints(exts, pathLen);
591 if (ret != CF_SUCCESS) {
592 CF_LOG_E("Failed to check basicConstraints");
593 return ret;
594 }
595 return ret;
596 }
597
GetExtensionEncoded(const X509_EXTENSIONS * inExts,CfBlob * out)598 static int32_t GetExtensionEncoded(const X509_EXTENSIONS *inExts, CfBlob *out)
599 {
600 unsigned char *derExts = NULL;
601 int extsLen = i2d_X509_EXTENSIONS((X509_EXTENSIONS *)inExts, &derExts);
602 if (extsLen <= 0) {
603 CF_LOG_E("Failed to convert internal exts to der format");
604 return CF_ERR_CRYPTO_OPERATION;
605 }
606
607 int32_t ret = DeepCopyDataToOutblob((const char *)derExts, extsLen, out);
608 OPENSSL_free(derExts);
609 return ret;
610 }
611
CfOpensslGetExtensionItem(const CfBase * object,CfItemId id,CfBlob * out)612 int32_t CfOpensslGetExtensionItem(const CfBase *object, CfItemId id, CfBlob *out)
613 {
614 if ((out == NULL) || (object == NULL)) {
615 CF_LOG_E("invalid input params");
616 return CF_INVALID_PARAMS;
617 }
618
619 X509_EXTENSIONS *inExts = NULL;
620 int32_t ret = CheckObjectAndGetExts(object, &inExts);
621 if (ret != CF_SUCCESS) {
622 CF_LOG_E("Failed to get extension");
623 return ret;
624 }
625
626 switch (id) {
627 case CF_ITEM_ENCODED:
628 return GetExtensionEncoded(inExts, out);
629 default:
630 CF_LOG_E("id is invalid");
631 return CF_INVALID_PARAMS;
632 }
633 }
634