• 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), 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