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