• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "certificate_openssl_common.h"
17 
18 #include <securec.h>
19 #include <string.h>
20 
21 #include "cf_log.h"
22 #include "cf_memory.h"
23 #include "cf_result.h"
24 #include "config.h"
25 
26 #include <openssl/err.h>
27 
28 typedef struct {
29     char *oid;
30     char *algorithmName;
31 } OidToAlgorithmName;
32 
33 static const OidToAlgorithmName g_oidToNameMap[] = {
34     { "1.2.840.113549.1.1.2", "MD2withRSA" },
35     { "1.2.840.113549.1.1.4", "MD5withRSA" },
36     { "1.2.840.113549.1.1.5", "SHA1withRSA" },
37     { "1.2.840.10040.4.3", "SHA1withDSA" },
38     { "1.2.840.10045.4.1", "SHA1withECDSA" },
39     { "1.2.840.113549.1.1.14", "SHA224withRSA" },
40     { "1.2.840.113549.1.1.11", "SHA256withRSA" },
41     { "1.2.840.113549.1.1.12", "SHA384withRSA" },
42     { "1.2.840.113549.1.1.13", "SHA512withRSA" },
43     { "2.16.840.1.101.3.4.3.1", "SHA224withDSA" },
44     { "2.16.840.1.101.3.4.3.2", "SHA256withDSA" },
45     { "1.2.840.10045.4.3.1", "SHA224withECDSA" },
46     { "1.2.840.10045.4.3.2", "SHA256withECDSA" },
47     { "1.2.840.10045.4.3.3", "SHA384withECDSA" },
48     { "1.2.840.10045.4.3.4", "SHA512withECDSA" }
49 };
50 
GetAlgorithmName(const char * oid)51 const char *GetAlgorithmName(const char *oid)
52 {
53     if (oid == NULL) {
54         LOGE("Oid is null!");
55         return NULL;
56     }
57 
58     uint32_t oidCount = sizeof(g_oidToNameMap) / sizeof(OidToAlgorithmName);
59     for (uint32_t i = 0; i < oidCount; i++) {
60         if (strcmp(g_oidToNameMap[i].oid, oid) == 0) {
61             return g_oidToNameMap[i].algorithmName;
62         }
63     }
64     LOGE("Can not find algorithmName! [oid]: %s", oid);
65     return NULL;
66 }
67 
CfPrintOpensslError(void)68 void CfPrintOpensslError(void)
69 {
70     char szErr[LOG_PRINT_MAX_LEN] = { 0 };
71     unsigned long errCode;
72 
73     errCode = ERR_get_error();
74     ERR_error_string_n(errCode, szErr, LOG_PRINT_MAX_LEN);
75 
76     LOGE("[Openssl]: engine fail, error code = %lu, error string = %s", errCode, szErr);
77 }
78 
DeepCopyDataToBlob(const unsigned char * data,uint32_t len,CfBlob * outBlob)79 CfResult DeepCopyDataToBlob(const unsigned char *data, uint32_t len, CfBlob *outBlob)
80 {
81     uint8_t *tmp = (uint8_t *)CfMalloc(len);
82     if (tmp == NULL) {
83         CF_LOG_E("Failed to malloc");
84         return CF_ERR_MALLOC;
85     }
86     (void)memcpy_s(tmp, len, data, len);
87 
88     outBlob->data = tmp;
89     outBlob->size = len;
90     return CF_SUCCESS;
91 }
92 
DeepCopyBlobToBlob(const CfBlob * inBlob,CfBlob ** outBlob)93 CfResult DeepCopyBlobToBlob(const CfBlob *inBlob, CfBlob **outBlob)
94 {
95     if (inBlob == NULL || outBlob == NULL) {
96         return CF_SUCCESS;
97     }
98 
99     CfBlob *tmp = (CfBlob *)HcfMalloc(sizeof(CfBlob), 0);
100     if (tmp == NULL) {
101         LOGE("malloc failed");
102         return CF_ERR_MALLOC;
103     }
104     CfResult res = DeepCopyDataToBlob((const unsigned char *)inBlob->data, inBlob->size, tmp);
105     if (res != CF_SUCCESS) {
106         LOGE("DeepCopyDataToBlob failed");
107         CfFree(tmp);
108         return res;
109     }
110     *outBlob = tmp;
111     return CF_SUCCESS;
112 }
113 
CopyExtensionsToBlob(const X509_EXTENSIONS * exts,CfBlob * outBlob)114 CfResult CopyExtensionsToBlob(const X509_EXTENSIONS *exts, CfBlob *outBlob)
115 {
116     if (exts == NULL) { /* if not exist extension, return success */
117         LOGD("No extension!");
118         return CF_SUCCESS;
119     }
120 
121     if (sk_X509_EXTENSION_num(exts) <= 0) {
122         LOGD("exts number is smaller than 0");
123         return CF_SUCCESS;
124     }
125 
126     unsigned char *extbytes = NULL;
127     int32_t extLen = i2d_X509_EXTENSIONS(exts, &extbytes);
128     if (extLen <= 0) {
129         CF_LOG_E("get extLen failed!");
130         CfPrintOpensslError();
131         return CF_ERR_CRYPTO_OPERATION;
132     }
133 
134     CfResult ret = DeepCopyDataToBlob(extbytes, (uint32_t)extLen, outBlob);
135     OPENSSL_free(extbytes);
136     return ret;
137 }
138 
CompareDateWithCertTime(const X509 * x509,const ASN1_TIME * inputDate)139 CfResult CompareDateWithCertTime(const X509 *x509, const ASN1_TIME *inputDate)
140 {
141     ASN1_TIME *startDate = X509_get_notBefore(x509);
142     ASN1_TIME *expirationDate = X509_get_notAfter(x509);
143     if ((startDate == NULL) || (expirationDate == NULL)) {
144         LOGE("Date is null in x509 cert!");
145         CfPrintOpensslError();
146         return CF_ERR_CRYPTO_OPERATION;
147     }
148     CfResult res = CF_SUCCESS;
149     /* 0: equal in ASN1_TIME_compare, -1: a < b, 1: a > b, -2: error. */
150     if (ASN1_TIME_compare(inputDate, startDate) < 0) {
151         LOGE("Date is not validate in x509 cert!");
152         res = CF_ERR_CERT_NOT_YET_VALID;
153     } else if (ASN1_TIME_compare(expirationDate, inputDate) < 0) {
154         LOGE("Date is expired in x509 cert!");
155         res = CF_ERR_CERT_HAS_EXPIRED;
156     }
157     return res;
158 }
159 
ConvertNameDerDataToString(const unsigned char * data,uint32_t derLen,CfBlob * out)160 CfResult ConvertNameDerDataToString(const unsigned char *data, uint32_t derLen, CfBlob *out)
161 {
162     if (data == NULL || derLen == 0 || out == NULL) {
163         LOGE("input params valid!");
164         return CF_INVALID_PARAMS;
165     }
166     X509_NAME *x509Name = d2i_X509_NAME(NULL, &data, derLen);
167     if (x509Name == NULL) {
168         LOGE("x509Name is null!");
169         CfPrintOpensslError();
170         return CF_ERR_CRYPTO_OPERATION;
171     }
172     char *name = X509_NAME_oneline(x509Name, NULL, 0);
173     if (name == NULL || strlen(name) > HCF_MAX_STR_LEN) {
174         LOGE("name is null!");
175         CfPrintOpensslError();
176         X509_NAME_free(x509Name);
177         return CF_ERR_CRYPTO_OPERATION;
178     }
179     CfResult res = DeepCopyDataToBlob((const unsigned char *)name, strlen(name) + 1, out);
180     OPENSSL_free(name);
181     X509_NAME_free(x509Name);
182     return res;
183 }
184 
CompareNameObject(const X509 * cert,const CfBlob * derBlob,X509NameType type,bool * compareRes)185 CfResult CompareNameObject(const X509 *cert, const CfBlob *derBlob, X509NameType type, bool *compareRes)
186 {
187     X509_NAME *name = NULL;
188     if (type == NAME_TYPE_SUBECT) {
189         name = X509_get_subject_name(cert);
190     } else if (type == NAME_TYPE_ISSUER) {
191         name = X509_get_issuer_name(cert);
192     }
193     if (name == NULL) {
194         LOGE("x509Cert get name failed!");
195         CfPrintOpensslError();
196         return CF_ERR_CRYPTO_OPERATION;
197     }
198     char *nameStr = X509_NAME_oneline(name, NULL, 0);
199     if (nameStr == NULL) {
200         LOGE("x509Cert name oneline failed!");
201         CfPrintOpensslError();
202         return CF_ERR_CRYPTO_OPERATION;
203     }
204 
205     CfBlob nameBlob = { 0 };
206     CfResult res = ConvertNameDerDataToString(derBlob->data, derBlob->size, &nameBlob);
207     if (res != CF_SUCCESS) {
208         LOGE("x509Cert ConvertNameDerDataToString failed!");
209         OPENSSL_free(nameStr);
210         return res;
211     }
212     uint32_t len = strlen(nameStr) + 1;
213     if (len != nameBlob.size || strncmp((const char *)nameStr, (const char *)nameBlob.data, nameBlob.size) != 0) {
214         LOGE("name do not match!");
215         *compareRes = false;
216     } else {
217         *compareRes = true;
218     }
219     CfBlobDataFree(&nameBlob);
220     OPENSSL_free(nameStr);
221     return CF_SUCCESS;
222 }
223 
CompareBigNum(const CfBlob * lhs,const CfBlob * rhs,int * out)224 CfResult CompareBigNum(const CfBlob *lhs, const CfBlob *rhs, int *out)
225 {
226     if ((lhs->data == NULL) || (lhs->size == 0) || (rhs->data == NULL) || (rhs->size == 0)) {
227         LOGE("Invalid Paramas!");
228         return CF_INVALID_PARAMS;
229     }
230 
231     BIGNUM *lhsBigNum = BN_bin2bn(lhs->data, lhs->size, NULL);
232     if (lhsBigNum == NULL) {
233         LOGE("bin to big number fail!");
234         CfPrintOpensslError();
235         return CF_INVALID_PARAMS;
236     }
237     BIGNUM *rhsBigNum = BN_bin2bn(rhs->data, rhs->size, NULL);
238     if (rhsBigNum == NULL) {
239         LOGE("bin to big number fail!");
240         CfPrintOpensslError();
241         BN_free(lhsBigNum);
242         return CF_INVALID_PARAMS;
243     }
244     *out = BN_cmp(lhsBigNum, rhsBigNum);
245     BN_free(lhsBigNum);
246     BN_free(rhsBigNum);
247     return CF_SUCCESS;
248 }
249 
GetX509EncodedDataStream(const X509 * certificate,int * dataLength)250 uint8_t *GetX509EncodedDataStream(const X509 *certificate, int *dataLength)
251 {
252     if (certificate == NULL) {
253         LOGE("Failed to convert internal x509 to der format!");
254         return NULL;
255     }
256 
257     unsigned char *der = NULL;
258     int32_t length = i2d_X509(certificate, &der);
259     if (length <= 0) {
260         LOGE("Failed to convert internal x509 to der format!");
261         CfPrintOpensslError();
262         return NULL;
263     }
264     uint8_t *data = (uint8_t *)HcfMalloc(length, 0);
265     if (data == NULL) {
266         LOGE("Failed to malloc for x509 der data!");
267         OPENSSL_free(der);
268         return NULL;
269     }
270     (void)memcpy_s(data, length, der, length);
271     OPENSSL_free(der);
272     *dataLength = length;
273 
274     return data;
275 }