1 /*
2 * Copyright (c) 2022-2025 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 "cm_pfx.h"
17
18 #include <openssl/pkcs12.h>
19 #include <openssl/bio.h>
20 #include <openssl/err.h>
21 #include <openssl/pem.h>
22
23 #include "cm_log.h"
24 #include "cm_mem.h"
25 #include "cm_type_inner.h"
26 #include "cm_x509.h"
27
28 // LCOV_EXCL_START
CmGetAppCertChain(X509 * cert,STACK_OF (X509)* caCert,struct AppCert * appCert)29 static int32_t CmGetAppCertChain(X509 *cert, STACK_OF(X509) *caCert, struct AppCert *appCert)
30 {
31 int32_t ret = CM_SUCCESS; uint32_t certCount = 0;
32 X509 *xCert = NULL; char *data = NULL; BIO *out = NULL;
33
34 if (cert == NULL) {
35 CM_LOG_E("app terminal cert is null");
36 return CM_FAILURE;
37 }
38
39 do {
40 out = BIO_new(BIO_s_mem());
41 if (out == NULL) {
42 CM_LOG_E("BIO_new_mem_buf failed");
43 ret = CMR_ERROR_OPENSSL_FAIL;
44 break;
45 }
46 /* copy app terminal cert to bio */
47 if (PEM_write_bio_X509(out, cert) == 0) {
48 CM_LOG_E("Copy app cert to bio faild");
49 ret = CMR_ERROR_OPENSSL_FAIL;
50 break;
51 }
52 certCount++;
53 /* copy app ca cert to bio */
54 for (int32_t i = 0; i < sk_X509_num(caCert); i++) {
55 xCert = sk_X509_value(caCert, i);
56 if (PEM_write_bio_X509(out, xCert) == 0) {
57 CM_LOG_E("Copy app ca cert to bio failed");
58 ret = CMR_ERROR_OPENSSL_FAIL;
59 break;
60 }
61 certCount++;
62 }
63
64 long len = BIO_get_mem_data(out, &data);
65 if (len <= 0) {
66 CM_LOG_E("BIO_get_mem_data faild");
67 ret = CMR_ERROR_OPENSSL_FAIL;
68 break;
69 }
70 if (memcpy_s(appCert->appCertdata, MAX_LEN_CERTIFICATE_CHAIN, data, len) != EOK) {
71 CM_LOG_E("Copy appCert->appCertdata faild");
72 ret = CMR_ERROR_MEM_OPERATION_COPY;
73 break;
74 }
75 /* default certificate chain is packaged as a whole */
76 appCert->certCount = certCount;
77 appCert->certSize = (uint32_t)len;
78 } while (0);
79
80 if (out != NULL) {
81 BIO_free(out);
82 }
83 return ret;
84 }
85
CmParsePkcs12Cert(const struct CmBlob * p12Cert,char * passWd,EVP_PKEY ** pkey,struct AppCert * appCert,X509 ** x509Cert)86 int32_t CmParsePkcs12Cert(const struct CmBlob *p12Cert, char *passWd, EVP_PKEY **pkey,
87 struct AppCert *appCert, X509 **x509Cert)
88 {
89 BIO *bio = NULL;
90 X509 *cert = NULL;
91 PKCS12 *p12 = NULL;
92 int32_t ret = CM_SUCCESS;
93 STACK_OF(X509) *caCert = NULL;
94
95 if (p12Cert == NULL || p12Cert->data == NULL || p12Cert->size > MAX_LEN_CERTIFICATE_CHAIN) {
96 return CMR_ERROR_INVALID_ARGUMENT_APP_CERT;
97 }
98
99 do {
100 bio = BIO_new_mem_buf(p12Cert->data, p12Cert->size);
101 if (bio == NULL) {
102 ret = CMR_ERROR_OPENSSL_FAIL;
103 CM_LOG_E("BIO_new_mem_buf faild");
104 break;
105 }
106
107 p12 = d2i_PKCS12_bio(bio, NULL);
108 if (p12 == NULL) {
109 ret = CMR_ERROR_INVALID_CERT_FORMAT;
110 CM_LOG_E("D2i_PKCS12_bio faild:%s", ERR_error_string(ERR_get_error(), NULL));
111 break;
112 }
113 /* 1 the return value of PKCS12_parse 1 is success */
114 if (PKCS12_parse(p12, passWd, pkey, &cert, &caCert) != 1) {
115 ret = CMR_ERROR_PASSWORD_IS_ERR;
116 CM_LOG_E("Parsing PKCS#12 file faild:%s", ERR_error_string(ERR_get_error(), NULL));
117 break;
118 }
119
120 ret = CmGetAppCertChain(cert, caCert, appCert);
121 if (ret != CM_SUCCESS) {
122 CM_LOG_E("CmGetAppCertChain failed");
123 break;
124 }
125 } while (0);
126
127 if (bio != NULL) {
128 BIO_free(bio);
129 }
130 if (p12 != NULL) {
131 PKCS12_free(p12);
132 }
133 if (caCert != NULL) {
134 sk_X509_pop_free(caCert, X509_free);
135 }
136 if (cert != NULL) {
137 *x509Cert = cert;
138 }
139 return ret;
140 }
141 // LCOV_EXCL_STOP
142