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 }