• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "x509_cert_chain_openssl_ex.h"
17 
18 #include "certificate_openssl_class.h"
19 #include "certificate_openssl_common.h"
20 #include "cf_blob.h"
21 #include "cf_log.h"
22 #include "cf_memory.h"
23 #include "cf_result.h"
24 #include "utils.h"
25 #include <securec.h>
26 #include "x509_cert_chain_spi.h"
27 #include "x509_certificate_create.h"
28 #include <openssl/pem.h>
29 #include <openssl/pkcs12.h>
30 
31 #define X509_CERT_CHAIN_OPENSSL_CLASS "X509CertChainOpensslClass"
32 
GetX509CertChainClass(void)33 const char *GetX509CertChainClass(void)
34 {
35     return X509_CERT_CHAIN_OPENSSL_CLASS;
36 }
37 
CfToString(HcfX509CertChainSpi * self,CfBlob * out)38 CfResult CfToString(HcfX509CertChainSpi *self, CfBlob *out)
39 {
40     if ((self == NULL) || (out == NULL)) {
41         LOGE("The input data is null!");
42         return CF_INVALID_PARAMS;
43     }
44     if (!CfIsClassMatch((CfObjectBase *)self, GetX509CertChainClass())) {
45         LOGE("Input wrong class type!");
46         return CF_INVALID_PARAMS;
47     }
48 
49     HcfX509CertChainOpensslImpl *certChain = (HcfX509CertChainOpensslImpl *)self;
50     STACK_OF(X509) *x509CertChain = certChain->x509CertChain;
51 
52     int32_t certsNum = sk_X509_num(x509CertChain);
53     BIO *bio = BIO_new(BIO_s_mem());
54     if (bio == NULL) {
55         LOGE("BIO_new error");
56         return CF_ERR_MALLOC;
57     }
58     for (int32_t i = 0; i < certsNum; ++i) {
59         X509 *cert = sk_X509_value(x509CertChain, i);
60         int len = X509_print(bio, cert);
61         if (len <= 0) {
62             LOGE("X509_print error");
63             BIO_free(bio);
64             return CF_ERR_CRYPTO_OPERATION;
65         }
66     }
67     BUF_MEM *bufMem = NULL;
68     if (BIO_get_mem_ptr(bio, &bufMem) > 0 && bufMem != NULL) {
69         CfResult res = DeepCopyDataToOut(bufMem->data, bufMem->length, out);
70         BIO_free(bio);
71         return res;
72     }
73 
74     BIO_free(bio);
75     LOGE("BIO_get_mem_ptr error");
76     return CF_ERR_CRYPTO_OPERATION;
77 }
78 
CfHashCode(HcfX509CertChainSpi * self,CfBlob * out)79 CfResult CfHashCode(HcfX509CertChainSpi *self, CfBlob *out)
80 {
81     if ((self == NULL) || (out == NULL)) {
82         LOGE("The input data is null!");
83         return CF_INVALID_PARAMS;
84     }
85     if (!CfIsClassMatch((CfObjectBase *)self, GetX509CertChainClass())) {
86         LOGE("Input wrong class type!");
87         return CF_INVALID_PARAMS;
88     }
89 
90     HcfX509CertChainOpensslImpl *certChain = (HcfX509CertChainOpensslImpl *)self;
91     STACK_OF(X509) *x509CertChain = certChain->x509CertChain;
92     int32_t certsNum = sk_X509_num(x509CertChain);
93     BIO *bio = BIO_new(BIO_s_mem());
94     if (bio == NULL) {
95         LOGE("BIO_new error");
96         return CF_ERR_MALLOC;
97     }
98     for (int32_t i = 0; i < certsNum; ++i) {
99         X509 *cert = sk_X509_value(x509CertChain, i);
100         int len = i2d_X509_bio(bio, cert);
101         if (len < 0) {
102             LOGE("i2d_X509_bio error");
103             BIO_free(bio);
104             return CF_ERR_CRYPTO_OPERATION;
105         }
106     }
107 
108     out->data = (uint8_t *)CfMalloc(SHA256_DIGEST_LENGTH, 0);
109     if (out->data == NULL) {
110         LOGE("CfMalloc error");
111         BIO_free(bio);
112         return CF_ERR_MALLOC;
113     }
114     BUF_MEM *bufMem = NULL;
115     if (BIO_get_mem_ptr(bio, &bufMem) > 0 && bufMem != NULL) {
116         SHA256((unsigned char *)bufMem->data, bufMem->length, out->data);
117         out->size = SHA256_DIGEST_LENGTH;
118         BIO_free(bio);
119         return CF_SUCCESS;
120     }
121 
122     BIO_free(bio);
123     CfBlobDataFree(out);
124     LOGE("BIO_get_mem_ptr error");
125     return CF_ERR_CRYPTO_OPERATION;
126 }
127 
GetX509FromHcfX509Certificate(const HcfCertificate * cert)128 X509 *GetX509FromHcfX509Certificate(const HcfCertificate *cert)
129 {
130     if (!CfIsClassMatch((CfObjectBase *)cert, HCF_X509_CERTIFICATE_CLASS)) {
131         LOGE("Input wrong openssl class type!");
132         return NULL;
133     }
134     HcfX509CertificateImpl *impl = (HcfX509CertificateImpl *)cert;
135     if (!CfIsClassMatch((CfObjectBase *)(impl->spiObj), X509_CERT_OPENSSL_CLASS)) {
136         LOGE("Input wrong openssl class type!");
137         return NULL;
138     }
139     HcfOpensslX509Cert *realCert = (HcfOpensslX509Cert *)(impl->spiObj);
140 
141     return realCert->x509;
142 }
143 
FreeCertificateArray(HcfX509CertificateArray * certs)144 void FreeCertificateArray(HcfX509CertificateArray *certs)
145 {
146     if (certs == NULL || certs->data == NULL) {
147         return;
148     }
149     for (uint32_t i = 0; i < certs->count; ++i) {
150         CfObjDestroy(certs->data[i]);
151     }
152     CF_FREE_PTR(certs->data);
153     certs->count = 0;
154 }
155 
GetCertChainFromCollection(const HcfX509CertChainBuildParameters * inParams,STACK_OF (X509)* certStack)156 static CfResult GetCertChainFromCollection(const HcfX509CertChainBuildParameters *inParams, STACK_OF(X509) *certStack)
157 {
158     if (inParams->validateParameters.certCRLCollections == NULL) {
159         LOGE("The input is NULL!");
160         return CF_INVALID_PARAMS;
161     }
162 
163     for (uint32_t i = 0; i < inParams->validateParameters.certCRLCollections->count; ++i) {
164         HcfX509CertificateArray retCerts = { NULL, 0 };
165         HcfCertCrlCollection *collection = inParams->validateParameters.certCRLCollections->data[i];
166         CfResult res = collection->selectCerts(collection, &(inParams->certMatchParameters), &retCerts);
167         if (res != CF_SUCCESS) {
168             LOGE("Get mached certs failed!");
169             return res;
170         }
171         for (uint32_t j = 0; j < retCerts.count; ++j) {
172             X509 *cert = GetX509FromHcfX509Certificate((HcfCertificate *)retCerts.data[j]);
173             if (cert == NULL) {
174                 LOGE("GetX509Cert from inParams failed!");
175                 FreeCertificateArray(&retCerts);
176                 return CF_INVALID_PARAMS;
177             }
178 
179             X509 *certDup = X509_dup(cert);
180             if (certDup == NULL) {
181                 LOGE("Memory allocation failure!");
182                 FreeCertificateArray(&retCerts);
183                 return CF_ERR_MALLOC;
184             }
185             if (sk_X509_push(certStack, certDup) <= 0) {
186                 LOGE("Push cert to SK failed!");
187                 X509_free(certDup);
188                 FreeCertificateArray(&retCerts);
189                 return CF_ERR_CRYPTO_OPERATION;
190             }
191         }
192         FreeCertificateArray(&retCerts);
193     }
194     return CF_SUCCESS;
195 }
196 
GetLeafCertsFromCertStack(const HcfX509CertChainBuildParameters * inParams,STACK_OF (X509)* allCerts,STACK_OF (X509)* leafCerts)197 CfResult GetLeafCertsFromCertStack(
198     const HcfX509CertChainBuildParameters *inParams, STACK_OF(X509) *allCerts, STACK_OF(X509) *leafCerts)
199 {
200     CfResult res = GetCertChainFromCollection(inParams, allCerts);
201     if (res != CF_SUCCESS) {
202         LOGE("Error geting certificates from collection.");
203         return res;
204     }
205 
206     int allCertsLen = sk_X509_num(allCerts);
207     if (allCertsLen == 0) {
208         LOGE("The num of all certificate from collection is 0.");
209         return CF_INVALID_PARAMS;
210     }
211     for (int i = 0; i < allCertsLen; ++i) {
212         X509 *x509 = sk_X509_value(allCerts, i);
213         if (!CheckIsLeafCert(x509)) {
214             continue;
215         }
216 
217         X509 *x = X509_dup(x509);
218         if (x == NULL) {
219             LOGE("Dup the cert failed.");
220             return CF_ERR_CRYPTO_OPERATION;
221         }
222         if (!sk_X509_push(leafCerts, x)) {
223             X509_free(x);
224             LOGE("Push the cert into stack failed.");
225             return CF_ERR_CRYPTO_OPERATION;
226         }
227     }
228 
229     if (sk_X509_num(leafCerts) <= 0) {
230         LOGE("The num of leaf certificate is 0.");
231         return CF_INVALID_PARAMS;
232     }
233     return CF_SUCCESS;
234 }
235 
X509ToHcfX509Certificate(X509 * cert,HcfX509Certificate ** returnObj)236 CfResult X509ToHcfX509Certificate(X509 *cert, HcfX509Certificate **returnObj)
237 {
238     if (cert == NULL) {
239         LOGE("The input params invalid.");
240         return CF_INVALID_PARAMS;
241     }
242 
243     HcfX509CertCreateFunc func = GetHcfX509CertCreateFunc();
244     if (func == NULL) {
245         LOGE("HcfX509CertificateCreate is null.");
246         return CF_NULL_POINTER;
247     }
248 
249     int dataLength = 0;
250     uint8_t *certData = GetX509EncodedDataStream(cert, &dataLength);
251     if (certData == NULL) {
252         LOGE("Falied to get certificate data!");
253         return CF_ERR_CRYPTO_OPERATION;
254     }
255 
256     HcfX509Certificate *x509cert = NULL;
257     CfEncodingBlob encodingBlob = { certData, dataLength, CF_FORMAT_DER };
258     CfResult res = func(&encodingBlob, &x509cert);
259     CfFree(certData);
260     if (res != CF_SUCCESS) {
261         LOGE("HcfX509CertificateCreate fail, res : %d!", res);
262         return CF_ERR_MALLOC;
263     }
264 
265     *returnObj = x509cert;
266     return res;
267 }
268 
FreeResources(X509 * cert,EVP_PKEY * pkey,STACK_OF (X509)* caStack)269 void FreeResources(X509 *cert, EVP_PKEY *pkey, STACK_OF(X509) *caStack)
270 {
271     if (cert != NULL) {
272         X509_free(cert);
273     }
274     if (pkey != NULL) {
275         EVP_PKEY_free(pkey);
276     }
277     if (caStack != NULL) {
278         sk_X509_pop_free(caStack, X509_free);
279     }
280 }
281 
FreeHcfX509P12Collection(HcfX509P12Collection * p12Collection)282 void FreeHcfX509P12Collection(HcfX509P12Collection *p12Collection)
283 {
284     if (p12Collection == NULL) {
285         return;
286     }
287     if (p12Collection->cert != NULL) {
288         CfFree(p12Collection->cert);
289     }
290     if (p12Collection->prikey != NULL && p12Collection->prikey->data != NULL) {
291         CfFree(p12Collection->prikey->data);
292         CfFree(p12Collection->prikey);
293     }
294     if (p12Collection->otherCerts != NULL && p12Collection->otherCertsCount != 0) {
295         for (uint32_t i = 0; i < p12Collection->otherCertsCount; i++) {
296             if (p12Collection->otherCerts[i] != NULL) {
297                 CfFree(p12Collection->otherCerts[i]);
298             }
299         }
300         CfFree(p12Collection->otherCerts);
301     }
302     CfFree(p12Collection);
303 }
304 
AllocateAndConvertCert(X509 * cert,HcfX509P12Collection * collection,bool isGet)305 CfResult AllocateAndConvertCert(X509 *cert, HcfX509P12Collection *collection, bool isGet)
306 {
307     if (!isGet) {
308         LOGI("The certificate for P12 does not need to be parsed!");
309         return CF_SUCCESS;
310     }
311     if (cert == NULL) {
312         LOGI("P12 dose not have a cert!");
313         return CF_SUCCESS;
314     }
315     CfResult ret = X509ToHcfX509Certificate(cert, &collection->cert);
316     if (ret != CF_SUCCESS) {
317         CfFree(collection->cert);
318         LOGE("Failed to convert X509 to HcfX509Certificate!");
319         return ret;
320     }
321     return CF_SUCCESS;
322 }
323 
AllocateAndConvertPkey(EVP_PKEY * pkey,HcfX509P12Collection * collection,bool isGet)324 CfResult AllocateAndConvertPkey(EVP_PKEY *pkey, HcfX509P12Collection *collection, bool isGet)
325 {
326     if ((!isGet) || (pkey == NULL)) {
327         LOGI("The prikey for P12 does not need to be parsed!");
328         return CF_SUCCESS;
329     }
330     collection->prikey = (CfBlob *)CfMalloc(sizeof(CfBlob), 0);
331     if (collection->prikey == NULL) {
332         LOGE("Failed to malloc pri key!");
333         return CF_ERR_MALLOC;
334     }
335     BIO *memBio = BIO_new(BIO_s_mem());
336     if (collection->isPem) {
337         if (!PEM_write_bio_PrivateKey(memBio, pkey, NULL, NULL, 0, 0, NULL)) {
338             LOGE("PEM write bio PrivateKey failed");
339             CfPrintOpensslError();
340             CfBlobFree(&collection->prikey);
341             BIO_free_all(memBio);
342             return CF_ERR_CRYPTO_OPERATION;
343         }
344     } else {
345         if (!i2d_PKCS8PrivateKey_bio(memBio, pkey, NULL, NULL, 0, NULL, NULL)) {
346             LOGE("PrivateKey i2d failed");
347             CfPrintOpensslError();
348             CfBlobFree(&collection->prikey);
349             BIO_free_all(memBio);
350             return CF_ERR_CRYPTO_OPERATION;
351         }
352     }
353     BUF_MEM *buf = NULL;
354     if (BIO_get_mem_ptr(memBio, &buf) < 0 || buf == NULL) {
355         LOGE("Failed to get mem ptr!");
356         CfBlobFree(&collection->prikey);
357         BIO_free_all(memBio);
358         return CF_ERR_MALLOC;
359     }
360     collection->prikey->size = buf->length;
361     collection->prikey->data = (uint8_t *)CfMalloc(collection->prikey->size, 0);
362     if (collection->prikey->data == NULL) {
363         LOGE("Failed to malloc pri key data!");
364         CfBlobFree(&collection->prikey);
365         BIO_free_all(memBio);
366         return CF_ERR_MALLOC;
367     }
368     (void)memcpy_s(collection->prikey->data, buf->length, buf->data, buf->length);
369     BIO_free_all(memBio);
370     return CF_SUCCESS;
371 }
372 
AllocateAndConvertCertStack(STACK_OF (X509)* ca,HcfX509P12Collection * collection,bool isGet)373 CfResult AllocateAndConvertCertStack(STACK_OF(X509) *ca, HcfX509P12Collection *collection, bool isGet)
374 {
375     if (!isGet) {
376         LOGI("The other certs for P12 does not need to be parsed!");
377         return CF_SUCCESS;
378     }
379     if (ca == NULL) {
380         LOGI("P12 dose not have other certs!");
381         return CF_SUCCESS;
382     }
383     int32_t count = sk_X509_num(ca);
384     if (count <= 0) {
385         LOGI("P12 other certs num is 0!");
386         return CF_SUCCESS;
387     }
388     collection->otherCerts = (HcfX509Certificate **)CfMalloc(sizeof(HcfX509Certificate *) * count, 0);
389     collection->otherCertsCount = (uint32_t)count;
390     if (collection->otherCerts == NULL) {
391         LOGE("Failed to malloc otherCerts!");
392         return CF_ERR_MALLOC;
393     }
394     for (uint32_t i = 0; i < collection->otherCertsCount; i++) {
395         X509 *cert = sk_X509_value(ca, i);
396         CfResult ret = X509ToHcfX509Certificate(cert, &collection->otherCerts[i]);
397         if (ret != CF_SUCCESS) {
398             LOGE("Failed to convert X509 to HcfX509Certificate!");
399             return ret;
400         }
401     }
402     return CF_SUCCESS;
403 }
404