• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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