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 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, 0);
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, 0);
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,int * nid)337 static int GetTargetNid(const CfBlob *oid, int *nid)
338 {
339 uint32_t length = oid->size + 1; /* add '\0' in the end */
340 uint8_t *oidString = (uint8_t *)CfMalloc(length, 0);
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 *nid = OBJ_txt2nid((char *)oidString);
353 CfFree(oidString);
354 return CF_SUCCESS;
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) {
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(CRITICAL_SIZE, 0); /* 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;
471 ret = GetTargetNid(oid, &targetNid);
472 if ((ret != CF_SUCCESS) || (targetNid == NID_undef)) {
473 CF_LOG_E("nid is undefined");
474 ret = (ret == CF_SUCCESS) ? CF_INVALID_PARAMS : ret;
475 return ret;
476 }
477
478 /* found one extension matched target nid in extensions */
479 X509_EXTENSION *found = NULL;
480 ret = FoundExtMatchedNid(exts, targetNid, &found);
481 if (ret != CF_SUCCESS) {
482 CF_LOG_E("no found target nid");
483 return ret;
484 }
485
486 /* get entry from matched extension for target type */
487 ret = GetMatchedEntry(found, type, out);
488 if (ret != CF_SUCCESS) {
489 CF_LOG_E("Failed to get matched entry");
490 return ret;
491 }
492 return CF_SUCCESS;
493 }
494
CheckKeyUsage(const X509_EXTENSIONS * exts,int32_t * pathLen)495 static int32_t CheckKeyUsage(const X509_EXTENSIONS *exts, int32_t *pathLen)
496 {
497 ASN1_BIT_STRING *usage = (ASN1_BIT_STRING *)X509V3_get_d2i(exts, NID_key_usage, NULL, NULL);
498 if (usage == NULL) {
499 CF_LOG_E("Failed to get usage");
500 return CF_ERR_CRYPTO_OPERATION;
501 }
502
503 uint32_t keyUsage = (uint32_t)usage->data[0];
504 if (usage->length > 1) {
505 keyUsage |= ((uint32_t)usage->data[1] << KEYUSAGE_SHIFT);
506 }
507
508 /* keyUsage of a CA cert: sign */
509 if ((keyUsage & KU_KEY_CERT_SIGN) == 0) {
510 CF_LOG_I("this cert not a CA");
511 *pathLen = BASIC_CONSTRAINTS_NO_CA;
512 }
513
514 ASN1_BIT_STRING_free(usage);
515 return CF_SUCCESS;
516 }
517
CheckBasicConstraints(const X509_EXTENSIONS * exts,int32_t * pathLen)518 static int32_t CheckBasicConstraints(const X509_EXTENSIONS *exts, int32_t *pathLen)
519 {
520 BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)X509V3_get_d2i(exts, NID_basic_constraints, NULL, NULL);
521 if (bs == NULL) {
522 CF_LOG_E("Failed to get basic constraints");
523 return CF_ERR_CRYPTO_OPERATION;
524 }
525
526 int32_t ret = CF_SUCCESS;
527 do {
528 if (!bs->ca) {
529 CF_LOG_I("this cert not a CA");
530 /* CheckCA operation is success, but cert is not a CA, pathLen set -1 */
531 *pathLen = BASIC_CONSTRAINTS_NO_CA;
532 ret = CF_SUCCESS;
533 break;
534 }
535
536 if ((bs->pathlen == NULL) || (bs->pathlen->type == V_ASN1_NEG_INTEGER)) {
537 CF_LOG_I("this cert pathlen no limit");
538 /* CheckCA operation is success and cert is a CA, but no limit to pathlen, pathLen set -2 */
539 *pathLen = BASIC_CONSTRAINTS_PATHLEN_NO_LIMIT;
540 ret = CF_SUCCESS;
541 break;
542 }
543
544 long len = ASN1_INTEGER_get(bs->pathlen);
545 if ((len < 0) || (len > INT_MAX)) { /* CheckCA operation is exceptional, pathlen is invalid */
546 CF_LOG_E("this cert pathlen is invalid");
547 ret = CF_ERR_CRYPTO_OPERATION;
548 break;
549 }
550 *pathLen = (int32_t)len;
551 } while (0);
552
553 BASIC_CONSTRAINTS_free(bs);
554 return ret;
555 }
556
CfOpensslCheckCA(const CfBase * object,int32_t * pathLen)557 int32_t CfOpensslCheckCA(const CfBase *object, int32_t *pathLen)
558 {
559 if ((object == NULL) || (pathLen == NULL)) {
560 CF_LOG_E("invalid input params");
561 return CF_INVALID_PARAMS;
562 }
563
564 X509_EXTENSIONS *exts = NULL;
565 int32_t ret = CheckObjectAndGetExts(object, &exts);
566 if (ret != CF_SUCCESS) {
567 CF_LOG_E("Failed to get extension");
568 return ret;
569 }
570
571 *pathLen = 0;
572 ret = CheckKeyUsage(exts, pathLen);
573 if (ret != CF_SUCCESS) {
574 CF_LOG_E("Failed to check keyUsage");
575 return ret;
576 }
577 if (*pathLen != 0) { /* checkKeyUsage operation success, but cert has no signing purpose, pathLen set -1. */
578 CF_LOG_I("Return: this cert not a CA");
579 return ret;
580 }
581
582 ret = CheckBasicConstraints(exts, pathLen);
583 if (ret != CF_SUCCESS) {
584 CF_LOG_E("Failed to check basicConstraints");
585 return ret;
586 }
587 return ret;
588 }
589
GetExtensionEncoded(const X509_EXTENSIONS * inExts,CfBlob * out)590 static int32_t GetExtensionEncoded(const X509_EXTENSIONS *inExts, CfBlob *out)
591 {
592 unsigned char *derExts = NULL;
593 int extsLen = i2d_X509_EXTENSIONS((X509_EXTENSIONS *)inExts, &derExts);
594 if (extsLen <= 0) {
595 CF_LOG_E("Failed to convert internal exts to der format");
596 return CF_ERR_CRYPTO_OPERATION;
597 }
598
599 int32_t ret = DeepCopyDataToOutblob((const char *)derExts, extsLen, out);
600 OPENSSL_free(derExts);
601 return ret;
602 }
603
CfOpensslGetExtensionItem(const CfBase * object,CfItemId id,CfBlob * out)604 int32_t CfOpensslGetExtensionItem(const CfBase *object, CfItemId id, CfBlob *out)
605 {
606 if ((out == NULL) || (object == NULL)) {
607 CF_LOG_E("invalid input params");
608 return CF_INVALID_PARAMS;
609 }
610
611 X509_EXTENSIONS *inExts = NULL;
612 int32_t ret = CheckObjectAndGetExts(object, &inExts);
613 if (ret != CF_SUCCESS) {
614 CF_LOG_E("Failed to get extension");
615 return ret;
616 }
617
618 switch (id) {
619 case CF_ITEM_ENCODED:
620 return GetExtensionEncoded(inExts, out);
621 default:
622 CF_LOG_E("id is invalid");
623 return CF_INVALID_PARAMS;
624 }
625 }
626