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