• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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));
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         return CF_ERR_CRYPTO_OPERATION;
92     }
93 
94     if (end != (inData->data + inData->len)) { /* Tainted extension data: valid part + invalid part */
95         CF_LOG_E("The extension indata is invalid");
96         sk_X509_EXTENSION_pop_free(extsObj->exts, X509_EXTENSION_free);
97         CfFree(extsObj);
98         return CF_ERR_CRYPTO_OPERATION;
99     }
100 
101     *object = &extsObj->base;
102     return CF_SUCCESS;
103 }
104 
CfOpensslDestoryExtension(CfBase ** object)105 void CfOpensslDestoryExtension(CfBase **object)
106 {
107     if ((object == NULL) || (*object == NULL)) {
108         CF_LOG_E("invalid input params");
109         return;
110     }
111 
112     CfOpensslExtensionObj *extsObj = (CfOpensslExtensionObj *)*object;
113     if (extsObj->base.type != CF_MAGIC(CF_MAGIC_TYPE_ADAPTER_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
114         CF_LOG_E("the object is invalid , type = %lu", extsObj->base.type);
115         return;
116     }
117 
118     if (extsObj->exts != NULL) {
119         sk_X509_EXTENSION_pop_free(extsObj->exts, X509_EXTENSION_free);
120     }
121     CfFree(extsObj);
122     *object = NULL;
123     return;
124 }
125 
CheckObjectAndGetExts(const CfBase * object,X509_EXTENSIONS ** exts)126 static int32_t CheckObjectAndGetExts(const CfBase *object, X509_EXTENSIONS **exts)
127 {
128     CfOpensslExtensionObj *extsObj = (CfOpensslExtensionObj *)object;
129     if (extsObj->base.type != CF_MAGIC(CF_MAGIC_TYPE_ADAPTER_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
130         CF_LOG_E("the object is invalid , type = %lu", extsObj->base.type);
131         return CF_INVALID_PARAMS;
132     }
133 
134     if (extsObj->exts == NULL) {
135         CF_LOG_E("extension is null");
136         return CF_INVALID_PARAMS;
137     }
138 
139     *exts = extsObj->exts;
140     return CF_SUCCESS;
141 }
142 
CopyIndexArray(uint32_t * destArray,uint32_t * destLen,const uint32_t * srcArray,uint32_t srcLen)143 static int32_t CopyIndexArray(uint32_t *destArray, uint32_t *destLen, const uint32_t *srcArray, uint32_t srcLen)
144 {
145     if (memcpy_s(destArray, ((*destLen) * sizeof(uint32_t)), srcArray, (srcLen * sizeof(uint32_t))) != EOK) {
146         CF_LOG_E("Failed to copy index array");
147         return CF_ERR_COPY;
148     }
149     *destLen = srcLen;
150     return CF_SUCCESS;
151 }
152 
GetExtensionIndexArray(const X509_EXTENSIONS * exts,CfExtensionOidType type,uint32_t * array,uint32_t * arrayLen)153 static int32_t GetExtensionIndexArray(const X509_EXTENSIONS *exts, CfExtensionOidType type,
154     uint32_t *array, uint32_t *arrayLen)
155 {
156     int32_t extNums = sk_X509_EXTENSION_num(exts);
157     if ((extNums <= 0) || (extNums > MAX_COUNT_OID)) {
158         CF_LOG_E("Failed to get extension numbers");
159         return CF_ERR_CRYPTO_OPERATION;
160     }
161 
162     uint32_t allOidArray[MAX_COUNT_OID] = { 0 }; /* type: CF_EXT_TYPE_ALL_OIDS */
163     uint32_t critOidArray[MAX_COUNT_OID] = { 0 }; /* type: CF_EXT_TYPE_CRITICAL_OIDS */
164     uint32_t uncritOidArray[MAX_COUNT_OID] = { 0 }; /* type: CF_EXT_TYPE_UNCRITICAL_OIDS */
165     uint32_t critCnt = 0;
166     uint32_t uncritCnt = 0;
167 
168     for (uint32_t i = 0; i < (uint32_t)extNums; ++i) {
169         allOidArray[i] = i;
170 
171         X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i);
172         if (ex == NULL) {
173             CF_LOG_E("Failed to get exts [%u] value", i);
174             return CF_ERR_CRYPTO_OPERATION;
175         }
176 
177         int crit = X509_EXTENSION_get_critical(ex);
178         if (crit == 1) {
179             critOidArray[critCnt++] = i;
180         } else {
181             uncritOidArray[uncritCnt++] = i;
182         }
183     }
184 
185     switch (type) {
186         case CF_EXT_TYPE_ALL_OIDS:
187             return CopyIndexArray(array, arrayLen, allOidArray, (uint32_t)extNums);
188         case CF_EXT_TYPE_CRITICAL_OIDS:
189             return CopyIndexArray(array, arrayLen, critOidArray, critCnt);
190         case CF_EXT_TYPE_UNCRITICAL_OIDS:
191             return CopyIndexArray(array, arrayLen, uncritOidArray, uncritCnt);
192         default:
193             CF_LOG_E("type is invalid");
194             return CF_INVALID_PARAMS;
195     }
196 }
197 
DeepCopyDataToOutblob(const char * data,uint32_t len,CfBlob * outBlob)198 static int32_t DeepCopyDataToOutblob(const char *data, uint32_t len, CfBlob *outBlob)
199 {
200     outBlob->data = (uint8_t *)CfMalloc(len);
201     if (outBlob->data == NULL) {
202         CF_LOG_E("Failed to malloc");
203         return CF_ERR_MALLOC;
204     }
205     (void)memcpy_s(outBlob->data, len, data, len);
206     outBlob->size = len;
207     return CF_SUCCESS;
208 }
209 
DeepCopyOidsToOut(const X509_EXTENSIONS * exts,const uint32_t * idxArray,uint32_t arrayLen,CfBlobArray * out)210 static int32_t DeepCopyOidsToOut(const X509_EXTENSIONS *exts, const uint32_t *idxArray, uint32_t arrayLen,
211     CfBlobArray *out)
212 {
213     uint32_t memSize = sizeof(CfBlob) * arrayLen;
214     CfBlob *dataArray = (CfBlob *)CfMalloc(memSize);
215     if (dataArray == NULL) {
216         CF_LOG_E("Failed to malloc");
217         return CF_ERR_MALLOC;
218     }
219 
220     for (uint32_t i = 0; i < arrayLen; ++i) {
221         uint32_t index = idxArray[i];
222 
223         X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, index);
224         if (ex == NULL) {
225             CF_LOG_E("Failed to get exts [%u] value", index);
226             FreeCfBlobArray(dataArray, i);
227             return CF_ERR_CRYPTO_OPERATION;
228         }
229 
230         char oid[MAX_LEN_OID] = { 0 };
231         int32_t oidLen = OBJ_obj2txt(oid, MAX_LEN_OID, X509_EXTENSION_get_object(ex), 1);
232         if ((oidLen <= 0) || (oidLen >= MAX_LEN_OID)) {
233             CF_LOG_E("Failed to get oid[%u]", index);
234             FreeCfBlobArray(dataArray, i);
235             return CF_ERR_CRYPTO_OPERATION;
236         }
237 
238         int32_t ret = DeepCopyDataToOutblob(oid, strlen(oid), &dataArray[i]);
239         if (ret != CF_SUCCESS) {
240             CF_LOG_E("Failed to copy oid[%u]", index);
241             FreeCfBlobArray(dataArray, i);
242             return ret;
243         }
244     }
245 
246     out->data = dataArray;
247     out->count = arrayLen;
248     return CF_SUCCESS;
249 }
250 
CfOpensslGetOids(const CfBase * object,CfExtensionOidType type,CfBlobArray * out)251 int32_t CfOpensslGetOids(const CfBase *object, CfExtensionOidType type, CfBlobArray *out)
252 {
253     if ((object == NULL) || (out == NULL)) {
254         CF_LOG_E("invalid input params");
255         return CF_INVALID_PARAMS;
256     }
257 
258     X509_EXTENSIONS *exts = NULL;
259     int32_t ret = CheckObjectAndGetExts(object, &exts);
260     if (ret != CF_SUCCESS) {
261         CF_LOG_E("Failed to get extension");
262         return ret;
263     }
264 
265     uint32_t idxArray[MAX_COUNT_OID] = { 0 }; /* extension index array for target CfExtensionOidType */
266     uint32_t count = MAX_COUNT_OID;
267     ret = GetExtensionIndexArray(exts, type, idxArray, &count);
268     if (ret != CF_SUCCESS) {
269         CF_LOG_E("Failed to get extension index array");
270         return ret;
271     }
272 
273     ret = DeepCopyOidsToOut(exts, idxArray, count, out);
274     if (ret != CF_SUCCESS) {
275         CF_LOG_E("Failed to copy oids to out");
276         return ret;
277     }
278     return CF_SUCCESS;
279 }
280 
CfOpensslHasUnsupportedCriticalExtension(const CfBase * object,bool * out)281 int32_t CfOpensslHasUnsupportedCriticalExtension(const CfBase *object, bool *out)
282 {
283     if (object == NULL || out == NULL) {
284         CF_LOG_E("invalid input params");
285         return CF_INVALID_PARAMS;
286     }
287 
288     X509_EXTENSIONS *exts = NULL;
289     int32_t ret = CheckObjectAndGetExts(object, &exts);
290     if (ret != CF_SUCCESS) {
291         CF_LOG_E("Failed to get extension");
292         return ret;
293     }
294 
295     int32_t extNums = sk_X509_EXTENSION_num(exts);
296     if ((extNums <= 0) || (extNums > MAX_COUNT_OID)) {
297         CF_LOG_E("Failed to get extension numbers, extNums = %d", extNums);
298         return CF_ERR_CRYPTO_OPERATION;
299     }
300 
301     for (uint32_t i = 0; i < (uint32_t)extNums; ++i) {
302         X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i);
303         if (ex == NULL) {
304             CF_LOG_E("Failed to get exts [%u] value", i);
305             return CF_ERR_CRYPTO_OPERATION;
306         }
307 
308         int crit = X509_EXTENSION_get_critical(ex);
309         if (crit != 1) { /* the extension entry is critical */
310             continue;
311         }
312 
313         char oid[MAX_LEN_OID] = { 0 };
314         int32_t oidLen = OBJ_obj2txt(oid, MAX_LEN_OID, X509_EXTENSION_get_object(ex), 1);
315         if ((oidLen <= 0) || (oidLen >= MAX_LEN_OID)) {
316             CF_LOG_E("Failed to get ext oid");
317             return CF_ERR_CRYPTO_OPERATION;
318         }
319         uint32_t oidsCount = sizeof(OID_TO_EXT_NAME_MAP) / sizeof(OidToExtensionName);
320         bool match = false;
321         for (uint32_t oidInd = 0; oidInd < oidsCount; oidInd++) {
322             if (strcmp(OID_TO_EXT_NAME_MAP[oidInd].oid, oid) == 0) {
323                 match = true;
324                 break;
325             }
326         }
327         if (!match) {
328             CF_LOG_I("extension oid [%s] is not supported.", oid);
329             *out = true;
330             return CF_SUCCESS;
331         }
332     }
333     *out = false;
334     return CF_SUCCESS;
335 }
336 
GetTargetNid(const CfBlob * oid)337 static int GetTargetNid(const CfBlob *oid)
338 {
339     uint32_t length = oid->size + 1; /* add '\0' in the end */
340     uint8_t *oidString = (uint8_t *)CfMalloc(length);
341     if (oidString == NULL) {
342         CF_LOG_E("Failed to malloc oid string");
343         return CF_ERR_MALLOC;
344     }
345 
346     if (memcpy_s(oidString, length, oid->data, oid->size) != EOK) {
347         CF_LOG_E("Failed to copy oid string");
348         CfFree(oidString);
349         return CF_ERR_COPY;
350     }
351 
352     int nid = OBJ_txt2nid((char *)oidString);
353     CfFree(oidString);
354     return nid;
355 }
356 
FoundExtMatchedNid(const X509_EXTENSIONS * exts,int targetNid,X509_EXTENSION ** found)357 static int32_t FoundExtMatchedNid(const X509_EXTENSIONS *exts, int targetNid, X509_EXTENSION **found)
358 {
359     int32_t extNums = sk_X509_EXTENSION_num(exts);
360     if ((extNums <= 0) || (extNums > MAX_COUNT_OID)) {
361         CF_LOG_E("Failed to get extension numbers");
362         return CF_ERR_CRYPTO_OPERATION;
363     }
364 
365     for (int i = 0; i < extNums; ++i) {
366         X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i);
367         if (ex == NULL) {
368             CF_LOG_E("Failed to get exts [%d] value", i);
369             return CF_ERR_CRYPTO_OPERATION;
370         }
371 
372         int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
373         if ((nid == NID_undef) || (nid > MAX_COUNT_NID)) {
374             CF_LOG_E("nid undefined");
375             return CF_ERR_CRYPTO_OPERATION;
376         }
377 
378         if (targetNid == nid) {
379             *found = ex;
380             return CF_SUCCESS;
381         }
382     }
383     return CF_NOT_EXIST;
384 }
385 
GetEntry(const X509_EXTENSION * found,CfBlob * out)386 static int32_t GetEntry(const X509_EXTENSION *found, CfBlob *out)
387 {
388     unsigned char *entry = NULL;
389     int entryLen = i2d_X509_EXTENSION((X509_EXTENSION *)found, &entry);
390     if (entryLen <= 0) {
391         CF_LOG_E("Failed to get entry");
392         return CF_ERR_CRYPTO_OPERATION;
393     }
394 
395     int32_t ret = DeepCopyDataToOutblob((const char *)entry, entryLen, out);
396     OPENSSL_free(entry);
397     return ret;
398 }
399 
GetEntryCritical(const X509_EXTENSION * found,CfBlob * out)400 static int32_t GetEntryCritical(const X509_EXTENSION *found, CfBlob *out)
401 {
402     out->data = (uint8_t *)CfMalloc(1); /* critical value is 0 or 1 */
403     if (out->data == NULL) {
404         CF_LOG_E("Failed to malloc");
405         return CF_ERR_MALLOC;
406     }
407     out->size = CRITICAL_SIZE;
408 
409     int crit = X509_EXTENSION_get_critical(found);
410     if (crit == 1) {
411         out->data[0] = 1;
412     } else {
413         out->data[0] = 0;
414     }
415 
416     return CF_SUCCESS;
417 }
418 
GetEntryValue(const X509_EXTENSION * found,CfBlob * out)419 static int32_t GetEntryValue(const X509_EXTENSION *found, CfBlob *out)
420 {
421     /* return internal value: extension data */
422     ASN1_OCTET_STRING *octetString = X509_EXTENSION_get_data((X509_EXTENSION *)found);
423     if (octetString == NULL) {
424         CF_LOG_E("Failed to get entry value");
425         return CF_ERR_CRYPTO_OPERATION;
426     }
427 
428     unsigned char *entryValue = NULL;
429     int entryValueLen = i2d_ASN1_OCTET_STRING(octetString, &entryValue);
430     if (entryValueLen <= 0) {
431         CF_LOG_E("Failed to get entry value len");
432         return CF_ERR_CRYPTO_OPERATION;
433     }
434 
435     int32_t ret = DeepCopyDataToOutblob((char *)entryValue, entryValueLen, out);
436     OPENSSL_free(entryValue);
437     return ret;
438 }
439 
GetMatchedEntry(const X509_EXTENSION * found,CfExtensionEntryType type,CfBlob * out)440 static int32_t GetMatchedEntry(const X509_EXTENSION *found, CfExtensionEntryType type, CfBlob *out)
441 {
442     switch (type) {
443         case CF_EXT_ENTRY_TYPE_ENTRY:
444             return GetEntry(found, out);
445         case CF_EXT_ENTRY_TYPE_ENTRY_CRITICAL:
446             return GetEntryCritical(found, out);
447         case CF_EXT_ENTRY_TYPE_ENTRY_VALUE:
448             return GetEntryValue(found, out);
449         default:
450             CF_LOG_E("type id invalid");
451             return CF_INVALID_PARAMS;
452     }
453 }
454 
CfOpensslGetEntry(const CfBase * object,CfExtensionEntryType type,const CfBlob * oid,CfBlob * out)455 int32_t CfOpensslGetEntry(const CfBase *object, CfExtensionEntryType type, const CfBlob *oid, CfBlob *out)
456 {
457     if ((object == NULL) || (out == NULL) || (CfCheckBlob(oid, MAX_LEN_OID) != CF_SUCCESS)) {
458         CF_LOG_E("invalid input params");
459         return CF_INVALID_PARAMS;
460     }
461 
462     X509_EXTENSIONS *exts = NULL;
463     int32_t ret = CheckObjectAndGetExts(object, &exts);
464     if (ret != CF_SUCCESS) {
465         CF_LOG_E("Failed to get extension");
466         return ret;
467     }
468 
469     /* get target nid from oid */
470     int targetNid = GetTargetNid(oid);
471     if ((targetNid == NID_undef) || (targetNid > MAX_COUNT_NID)) {
472         CF_LOG_E("nid is undefined");
473         return CF_INVALID_PARAMS;
474     }
475 
476     /* found one extension matched target nid in extensions */
477     X509_EXTENSION *found = NULL;
478     ret = FoundExtMatchedNid(exts, targetNid, &found);
479     if (ret != CF_SUCCESS) {
480         CF_LOG_E("no found target nid");
481         return ret;
482     }
483 
484     /* get entry from matched extension for target type */
485     ret = GetMatchedEntry(found, type, out);
486     if (ret != CF_SUCCESS) {
487         CF_LOG_E("Failed to get matched entry");
488         return ret;
489     }
490     return CF_SUCCESS;
491 }
492 
CheckKeyUsage(const X509_EXTENSIONS * exts,int32_t * pathLen)493 static int32_t CheckKeyUsage(const X509_EXTENSIONS *exts, int32_t *pathLen)
494 {
495     ASN1_BIT_STRING *usage = (ASN1_BIT_STRING *)X509V3_get_d2i(exts, NID_key_usage, NULL, NULL);
496     if (usage == NULL) {
497         CF_LOG_E("Failed to get usage");
498         return CF_ERR_CRYPTO_OPERATION;
499     }
500 
501     uint32_t keyUsage = (uint32_t)usage->data[0];
502     if (usage->length > 1) {
503         keyUsage |= ((uint32_t)usage->data[1] << KEYUSAGE_SHIFT);
504     }
505 
506     /* keyUsage of a CA cert: sign */
507     if ((keyUsage & KU_KEY_CERT_SIGN) == 0) {
508         CF_LOG_I("this cert not a CA");
509         *pathLen = BASIC_CONSTRAINTS_NO_CA;
510     }
511 
512     ASN1_BIT_STRING_free(usage);
513     return CF_SUCCESS;
514 }
515 
CheckBasicConstraints(const X509_EXTENSIONS * exts,int32_t * pathLen)516 static int32_t CheckBasicConstraints(const X509_EXTENSIONS *exts, int32_t *pathLen)
517 {
518     BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509V3_get_d2i(exts, NID_basic_constraints, NULL, NULL);
519     if (bs == NULL) {
520         CF_LOG_E("Failed to get basic constraints");
521         return CF_ERR_CRYPTO_OPERATION;
522     }
523 
524     int32_t ret = CF_SUCCESS;
525     do {
526         if (!bs->ca) {
527             CF_LOG_I("this cert not a CA");
528             /* CheckCA operation is success, but cert is not a CA, pathLen set -1 */
529             *pathLen = BASIC_CONSTRAINTS_NO_CA;
530             ret = CF_SUCCESS;
531             break;
532         }
533 
534         if ((bs->pathlen == NULL) || (bs->pathlen->type == V_ASN1_NEG_INTEGER)) {
535             CF_LOG_I("this cert pathlen no limit");
536             /* CheckCA operation is success and cert is a CA, but no limit to pathlen, pathLen set -2 */
537             *pathLen = BASIC_CONSTRAINTS_PATHLEN_NO_LIMIT;
538             ret = CF_SUCCESS;
539             break;
540         }
541 
542         long len = ASN1_INTEGER_get(bs->pathlen);
543         if ((len < 0) || (len > INT_MAX)) { /* CheckCA operation is exceptional, pathlen is invalid */
544             CF_LOG_E("this cert pathlen is invalid");
545             ret = CF_ERR_CRYPTO_OPERATION;
546             break;
547         }
548         *pathLen = (int32_t)len;
549     } while (0);
550 
551     BASIC_CONSTRAINTS_free(bs);
552     return ret;
553 }
554 
CfOpensslCheckCA(const CfBase * object,int32_t * pathLen)555 int32_t CfOpensslCheckCA(const CfBase *object, int32_t *pathLen)
556 {
557     if ((object == NULL) || (pathLen == NULL)) {
558         CF_LOG_E("invalid input params");
559         return CF_INVALID_PARAMS;
560     }
561 
562     X509_EXTENSIONS *exts = NULL;
563     int32_t ret = CheckObjectAndGetExts(object, &exts);
564     if (ret != CF_SUCCESS) {
565         CF_LOG_E("Failed to get extension");
566         return ret;
567     }
568 
569     *pathLen = 0;
570     ret = CheckKeyUsage(exts, pathLen);
571     if (ret != CF_SUCCESS) {
572         CF_LOG_E("Failed to check keyUsage");
573         return ret;
574     }
575     if (*pathLen != 0) { /* checkKeyUsage operation success, but cert has no signing purpose, pathLen set -1. */
576         CF_LOG_I("Return: this cert not a CA");
577         return ret;
578     }
579 
580     ret = CheckBasicConstraints(exts, pathLen);
581     if (ret != CF_SUCCESS) {
582         CF_LOG_E("Failed to check basicConstraints");
583         return ret;
584     }
585     return ret;
586 }
587 
GetExtensionEncoded(const X509_EXTENSIONS * inExts,CfBlob * out)588 static int32_t GetExtensionEncoded(const X509_EXTENSIONS *inExts, CfBlob *out)
589 {
590     unsigned char *derExts = NULL;
591     int extsLen = i2d_X509_EXTENSIONS((X509_EXTENSIONS *)inExts, &derExts);
592     if (extsLen <= 0) {
593         CF_LOG_E("Failed to convert internal exts to der format");
594         return CF_ERR_CRYPTO_OPERATION;
595     }
596 
597     int32_t ret = DeepCopyDataToOutblob((const char *)derExts, extsLen, out);
598     OPENSSL_free(derExts);
599     return ret;
600 }
601 
CfOpensslGetExtensionItem(const CfBase * object,CfItemId id,CfBlob * out)602 int32_t CfOpensslGetExtensionItem(const CfBase *object, CfItemId id, CfBlob *out)
603 {
604     if ((out == NULL) || (object == NULL)) {
605         CF_LOG_E("invalid input params");
606         return CF_INVALID_PARAMS;
607     }
608 
609     X509_EXTENSIONS *inExts = NULL;
610     int32_t ret = CheckObjectAndGetExts(object, &inExts);
611     if (ret != CF_SUCCESS) {
612         CF_LOG_E("Failed to get extension");
613         return ret;
614     }
615 
616     switch (id) {
617         case CF_ITEM_ENCODED:
618             return GetExtensionEncoded(inExts, out);
619         default:
620             CF_LOG_E("id is invalid");
621             return CF_INVALID_PARAMS;
622     }
623     return CF_SUCCESS;
624 }
625