1 /*
2 * Copyright (c) 2023-2024 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 <openssl/err.h>
19 #include <openssl/x509v3.h>
20 #include <securec.h>
21 #include <string.h>
22
23 #include "cf_log.h"
24 #include "cf_memory.h"
25 #include "cf_result.h"
26 #include "config.h"
27
28 #define TIME_MON_LEN 2
29 #define TIME_HOUR_LEN 8
30 #define TIME_MIN_LEN 10
31 #define TIME_SEC_LEN 12
32
33 typedef struct {
34 char *oid;
35 char *algorithmName;
36 } OidToAlgorithmName;
37
38 static const OidToAlgorithmName g_oidToNameMap[] = {
39 { "1.2.840.113549.1.1.2", "MD2withRSA" },
40 { "1.2.840.113549.1.1.4", "MD5withRSA" },
41 { "1.2.840.113549.1.1.5", "SHA1withRSA" },
42 { "1.2.840.10040.4.3", "SHA1withDSA" },
43 { "1.2.840.10045.4.1", "SHA1withECDSA" },
44 { "1.2.840.113549.1.1.14", "SHA224withRSA" },
45 { "1.2.840.113549.1.1.11", "SHA256withRSA" },
46 { "1.2.840.113549.1.1.12", "SHA384withRSA" },
47 { "1.2.840.113549.1.1.13", "SHA512withRSA" },
48 { "2.16.840.1.101.3.4.3.1", "SHA224withDSA" },
49 { "2.16.840.1.101.3.4.3.2", "SHA256withDSA" },
50 { "1.2.840.10045.4.3.1", "SHA224withECDSA" },
51 { "1.2.840.10045.4.3.2", "SHA256withECDSA" },
52 { "1.2.840.10045.4.3.3", "SHA384withECDSA" },
53 { "1.2.840.10045.4.3.4", "SHA512withECDSA" }
54 };
55
GetAlgorithmName(const char * oid)56 const char *GetAlgorithmName(const char *oid)
57 {
58 if (oid == NULL) {
59 LOGE("Oid is null!");
60 return NULL;
61 }
62
63 uint32_t oidCount = sizeof(g_oidToNameMap) / sizeof(OidToAlgorithmName);
64 for (uint32_t i = 0; i < oidCount; i++) {
65 if (strcmp(g_oidToNameMap[i].oid, oid) == 0) {
66 return g_oidToNameMap[i].algorithmName;
67 }
68 }
69 LOGE("Can not find algorithmName! [oid]: %s", oid);
70 return NULL;
71 }
72
CfPrintOpensslError(void)73 void CfPrintOpensslError(void)
74 {
75 char szErr[LOG_PRINT_MAX_LEN] = { 0 };
76 unsigned long errCode;
77
78 errCode = ERR_get_error();
79 ERR_error_string_n(errCode, szErr, LOG_PRINT_MAX_LEN);
80
81 LOGE("[Openssl]: engine fail, error code = %lu, error string = %s", errCode, szErr);
82 }
83
DeepCopyDataToBlob(const unsigned char * data,uint32_t len,CfBlob * outBlob)84 CfResult DeepCopyDataToBlob(const unsigned char *data, uint32_t len, CfBlob *outBlob)
85 {
86 if (data == NULL || outBlob == NULL) {
87 CF_LOG_E("The input params invalid.");
88 return CF_INVALID_PARAMS;
89 }
90 uint8_t *tmp = (uint8_t *)CfMalloc(len, 0);
91 if (tmp == NULL) {
92 CF_LOG_E("Failed to malloc.");
93 return CF_ERR_MALLOC;
94 }
95 (void)memcpy_s(tmp, len, data, len);
96
97 outBlob->data = tmp;
98 outBlob->size = len;
99 return CF_SUCCESS;
100 }
101
DeepCopyBlobToBlob(const CfBlob * inBlob,CfBlob ** outBlob)102 CfResult DeepCopyBlobToBlob(const CfBlob *inBlob, CfBlob **outBlob)
103 {
104 if (inBlob == NULL || outBlob == NULL) {
105 return CF_SUCCESS;
106 }
107
108 CfBlob *tmp = (CfBlob *)CfMalloc(sizeof(CfBlob), 0);
109 if (tmp == NULL) {
110 LOGE("malloc failed");
111 return CF_ERR_MALLOC;
112 }
113 CfResult res = DeepCopyDataToBlob((const unsigned char *)inBlob->data, inBlob->size, tmp);
114 if (res != CF_SUCCESS) {
115 LOGE("DeepCopyDataToBlob failed");
116 CfFree(tmp);
117 return res;
118 }
119 *outBlob = tmp;
120 return CF_SUCCESS;
121 }
122
CopyExtensionsToBlob(const X509_EXTENSIONS * exts,CfBlob * outBlob)123 CfResult CopyExtensionsToBlob(const X509_EXTENSIONS *exts, CfBlob *outBlob)
124 {
125 if (exts == NULL) { /* if not exist extension, return success */
126 LOGD("No extension!");
127 return CF_SUCCESS;
128 }
129
130 if (sk_X509_EXTENSION_num(exts) <= 0) {
131 LOGD("exts number is smaller than 0");
132 return CF_SUCCESS;
133 }
134
135 unsigned char *extbytes = NULL;
136 int32_t extLen = i2d_X509_EXTENSIONS(exts, &extbytes);
137 if (extLen <= 0) {
138 CF_LOG_E("get extLen failed!");
139 CfPrintOpensslError();
140 return CF_ERR_CRYPTO_OPERATION;
141 }
142
143 CfResult ret = DeepCopyDataToBlob(extbytes, (uint32_t)extLen, outBlob);
144 OPENSSL_free(extbytes);
145 return ret;
146 }
147
CompareDateWithCertTime(const X509 * x509,const ASN1_TIME * inputDate)148 CfResult CompareDateWithCertTime(const X509 *x509, const ASN1_TIME *inputDate)
149 {
150 ASN1_TIME *startDate = X509_get_notBefore(x509);
151 ASN1_TIME *expirationDate = X509_get_notAfter(x509);
152 if ((startDate == NULL) || (expirationDate == NULL)) {
153 LOGE("Date is null in x509 cert!");
154 CfPrintOpensslError();
155 return CF_ERR_CRYPTO_OPERATION;
156 }
157 CfResult res = CF_SUCCESS;
158 /* 0: equal in ASN1_TIME_compare, -1: a < b, 1: a > b, -2: error. */
159 if (ASN1_TIME_compare(inputDate, startDate) < 0) {
160 LOGE("Date is not validate in x509 cert!");
161 res = CF_ERR_CERT_NOT_YET_VALID;
162 } else if (ASN1_TIME_compare(expirationDate, inputDate) < 0) {
163 LOGE("Date is expired in x509 cert!");
164 res = CF_ERR_CERT_HAS_EXPIRED;
165 }
166 return res;
167 }
168
ConvertNameDerDataToString(const unsigned char * data,uint32_t derLen,CfBlob * out)169 CfResult ConvertNameDerDataToString(const unsigned char *data, uint32_t derLen, CfBlob *out)
170 {
171 if (data == NULL || derLen == 0 || out == NULL) {
172 LOGE("The input params invalid!");
173 return CF_INVALID_PARAMS;
174 }
175 X509_NAME *x509Name = d2i_X509_NAME(NULL, &data, derLen);
176 if (x509Name == NULL) {
177 LOGE("x509Name is null!");
178 CfPrintOpensslError();
179 return CF_ERR_CRYPTO_OPERATION;
180 }
181 char *name = X509_NAME_oneline(x509Name, NULL, 0);
182 if (name == NULL) {
183 LOGE("name is null!");
184 CfPrintOpensslError();
185 X509_NAME_free(x509Name);
186 return CF_ERR_CRYPTO_OPERATION;
187 }
188 if (strlen(name) > HCF_MAX_STR_LEN) {
189 LOGE("name is to long!");
190 CfPrintOpensslError();
191 OPENSSL_free(name);
192 X509_NAME_free(x509Name);
193 return CF_ERR_CRYPTO_OPERATION;
194 }
195 CfResult res = DeepCopyDataToBlob((const unsigned char *)name, strlen(name) + 1, out);
196 OPENSSL_free(name);
197 X509_NAME_free(x509Name);
198 return res;
199 }
200
CompareNameObject(const X509 * cert,const CfBlob * derBlob,X509NameType type,bool * compareRes)201 CfResult CompareNameObject(const X509 *cert, const CfBlob *derBlob, X509NameType type, bool *compareRes)
202 {
203 X509_NAME *name = NULL;
204 if (type == NAME_TYPE_SUBJECT) {
205 name = X509_get_subject_name(cert);
206 } else if (type == NAME_TYPE_ISSUER) {
207 name = X509_get_issuer_name(cert);
208 }
209 if (name == NULL) {
210 LOGE("x509Cert get name failed!");
211 CfPrintOpensslError();
212 return CF_ERR_CRYPTO_OPERATION;
213 }
214 char *nameStr = X509_NAME_oneline(name, NULL, 0);
215 if (nameStr == NULL) {
216 LOGE("x509Cert name oneline failed!");
217 CfPrintOpensslError();
218 return CF_ERR_CRYPTO_OPERATION;
219 }
220
221 CfBlob nameBlob = { 0 };
222 CfResult res = ConvertNameDerDataToString(derBlob->data, derBlob->size, &nameBlob);
223 if (res != CF_SUCCESS) {
224 LOGE("x509Cert ConvertNameDerDataToString failed!");
225 OPENSSL_free(nameStr);
226 return res;
227 }
228 uint32_t len = strlen(nameStr) + 1;
229 if (len != nameBlob.size || strncmp((const char *)nameStr, (const char *)nameBlob.data, nameBlob.size) != 0) {
230 LOGE("name do not match!");
231 *compareRes = false;
232 } else {
233 *compareRes = true;
234 }
235 CfBlobDataFree(&nameBlob);
236 OPENSSL_free(nameStr);
237 return CF_SUCCESS;
238 }
239
CompareBigNum(const CfBlob * lhs,const CfBlob * rhs,int * out)240 CfResult CompareBigNum(const CfBlob *lhs, const CfBlob *rhs, int *out)
241 {
242 if ((lhs->data == NULL) || (lhs->size == 0) || (rhs->data == NULL) || (rhs->size == 0)) {
243 LOGE("Invalid params!");
244 return CF_INVALID_PARAMS;
245 }
246
247 BIGNUM *lhsBigNum = BN_bin2bn(lhs->data, lhs->size, NULL);
248 if (lhsBigNum == NULL) {
249 LOGE("bin to big number fail!");
250 CfPrintOpensslError();
251 return CF_INVALID_PARAMS;
252 }
253 BIGNUM *rhsBigNum = BN_bin2bn(rhs->data, rhs->size, NULL);
254 if (rhsBigNum == NULL) {
255 LOGE("bin to big number fail!");
256 CfPrintOpensslError();
257 BN_free(lhsBigNum);
258 return CF_INVALID_PARAMS;
259 }
260 *out = BN_cmp(lhsBigNum, rhsBigNum);
261 BN_free(lhsBigNum);
262 BN_free(rhsBigNum);
263 return CF_SUCCESS;
264 }
265
GetX509EncodedDataStream(const X509 * certificate,int * dataLength)266 uint8_t *GetX509EncodedDataStream(const X509 *certificate, int *dataLength)
267 {
268 if (certificate == NULL) {
269 LOGE("The input params null.");
270 return NULL;
271 }
272
273 unsigned char *der = NULL;
274 int32_t length = i2d_X509(certificate, &der);
275 if (length <= 0) {
276 LOGE("Failed to convert internal x509 to der format!");
277 CfPrintOpensslError();
278 return NULL;
279 }
280 uint8_t *data = (uint8_t *)CfMalloc(length, 0);
281 if (data == NULL) {
282 LOGE("Failed to malloc for x509 der data!");
283 OPENSSL_free(der);
284 return NULL;
285 }
286 (void)memcpy_s(data, length, der, length);
287 OPENSSL_free(der);
288 *dataLength = length;
289
290 return data;
291 }
292
Asn1TimeToStr(const ASN1_GENERALIZEDTIME * time)293 char *Asn1TimeToStr(const ASN1_GENERALIZEDTIME *time)
294 {
295 char buffer[24];
296 if (time == NULL || time->data == NULL) {
297 return NULL;
298 }
299
300 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%.6s-", time->data + TIME_MON_LEN) < 0 ||
301 snprintf_s(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), sizeof(buffer) - strlen(buffer) - 1,
302 "%.2s:", time->data + TIME_HOUR_LEN) < 0 ||
303 snprintf_s(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), sizeof(buffer) - strlen(buffer) - 1,
304 "%.2s:", time->data + TIME_MIN_LEN) < 0 ||
305 snprintf_s(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), sizeof(buffer) - strlen(buffer) - 1,
306 "%.2sZ", time->data + TIME_SEC_LEN) < 0) {
307 return NULL;
308 }
309
310 char *result = strdup(buffer);
311 if (result == NULL) {
312 return NULL;
313 }
314
315 return result;
316 }
317
CfArrayContains(const CfArray * self,const CfArray * sub)318 bool CfArrayContains(const CfArray *self, const CfArray *sub)
319 {
320 for (uint32_t i = 0; i < self->count; ++i) {
321 bool found = false;
322 for (uint32_t j = 0; j < sub->count; ++j) {
323 if (self->data[i].size == sub->data[j].size &&
324 memcmp(self->data[i].data, sub->data[j].data, self->data[i].size) == 0) {
325 found = true;
326 break;
327 }
328 }
329 if (!found) {
330 return false;
331 }
332 }
333 return true;
334 }
335
DeepCopyDataToOut(const char * data,uint32_t len,CfBlob * out)336 CfResult DeepCopyDataToOut(const char *data, uint32_t len, CfBlob *out)
337 {
338 out->data = (uint8_t *)CfMalloc(len, 0);
339 if (out->data == NULL) {
340 LOGE("Failed to malloc for sig algorithm params!");
341 return CF_ERR_MALLOC;
342 }
343 if (memcpy_s(out->data, len, data, len) != EOK) {
344 CF_LOG_E("Failed to memcpy_s");
345 CfFree(out->data);
346 out->data = NULL;
347 return CF_ERR_COPY;
348 }
349 out->size = len;
350 return CF_SUCCESS;
351 }
352
CheckIsSelfSigned(const X509 * cert)353 bool CheckIsSelfSigned(const X509 *cert)
354 {
355 if (cert == NULL) {
356 return false;
357 }
358 bool ret = false;
359 X509_NAME *issuer = X509_get_issuer_name(cert);
360 if (issuer == NULL) {
361 LOGE("x509 get issuer name failed!");
362 CfPrintOpensslError();
363 return ret;
364 }
365
366 X509_NAME *subject = X509_get_subject_name(cert);
367 if (subject == NULL) {
368 LOGE("x509 get subject name failed!");
369 CfPrintOpensslError();
370 return ret;
371 }
372
373 ret = (X509_NAME_cmp(issuer, subject) == 0);
374 return ret;
375 }
376
CheckIsLeafCert(X509 * cert)377 bool CheckIsLeafCert(X509 *cert)
378 {
379 if (cert == NULL) {
380 return false;
381 }
382
383 if (X509_check_ca(cert)) {
384 return false;
385 }
386
387 return true;
388 }
389
IsOrderCertChain(STACK_OF (X509)* certsChain,bool * isOrder)390 CfResult IsOrderCertChain(STACK_OF(X509) *certsChain, bool *isOrder)
391 {
392 int num = sk_X509_num(certsChain);
393 if (num == 1) {
394 LOGI("1 certs is order chain.");
395 return CF_SUCCESS;
396 }
397
398 X509 *cert = NULL;
399 X509 *certNext = NULL;
400 X509_NAME *issuerName = NULL;
401 X509_NAME *subjectName = NULL;
402 for (int i = num - 1; i > 0; --i) {
403 cert = sk_X509_value(certsChain, i);
404 if (cert == NULL) {
405 LOGE("sk X509 value is null, failed!");
406 CfPrintOpensslError();
407 return CF_ERR_CRYPTO_OPERATION;
408 }
409 certNext = sk_X509_value(certsChain, i - 1);
410 if (certNext == NULL) {
411 LOGE("sk X509 value is null, failed!");
412 CfPrintOpensslError();
413 return CF_ERR_CRYPTO_OPERATION;
414 }
415
416 subjectName = X509_get_subject_name(cert);
417 if (subjectName == NULL) {
418 LOGE("x509 get subject name failed!");
419 CfPrintOpensslError();
420 return CF_ERR_CRYPTO_OPERATION;
421 }
422 issuerName = X509_get_issuer_name(certNext);
423 if (issuerName == NULL) {
424 LOGE("x509 get subject name failed!");
425 CfPrintOpensslError();
426 return CF_ERR_CRYPTO_OPERATION;
427 }
428
429 if (X509_NAME_cmp(subjectName, issuerName) != 0) {
430 *isOrder = false;
431 LOGI("is a misOrder chain.");
432 break;
433 }
434 }
435
436 return CF_SUCCESS;
437 }
438
CheckSelfPubkey(X509 * cert,const EVP_PKEY * pubKey)439 CfResult CheckSelfPubkey(X509 *cert, const EVP_PKEY *pubKey)
440 {
441 EVP_PKEY *certPublicKey = X509_get_pubkey(cert);
442 if (certPublicKey == NULL) {
443 LOGE("get cert public key failed!");
444 CfPrintOpensslError();
445 return CF_ERR_CRYPTO_OPERATION;
446 }
447
448 int isMatch = EVP_PKEY_cmp(certPublicKey, pubKey);
449 if (isMatch != CF_OPENSSL_SUCCESS) {
450 LOGE("cmp cert public key failed!");
451 CfPrintOpensslError();
452 EVP_PKEY_free(certPublicKey);
453 return CF_ERR_CRYPTO_OPERATION;
454 }
455
456 EVP_PKEY_free(certPublicKey);
457 return CF_SUCCESS;
458 }
459
FindCertificateBySubject(STACK_OF (X509)* certs,X509_NAME * subjectName)460 X509 *FindCertificateBySubject(STACK_OF(X509) *certs, X509_NAME *subjectName)
461 {
462 X509_STORE_CTX *ctx = NULL;
463 X509 *cert = NULL;
464 X509_OBJECT *obj = NULL;
465
466 X509_STORE *store = X509_STORE_new();
467 if (store == NULL) {
468 return NULL;
469 }
470 for (int i = 0; i < sk_X509_num(certs); i++) {
471 cert = sk_X509_value(certs, i);
472 if (X509_STORE_add_cert(store, cert) != 1) {
473 X509_STORE_free(store);
474 return NULL;
475 }
476 }
477
478 if (!(ctx = X509_STORE_CTX_new())) {
479 X509_STORE_free(store);
480 return NULL;
481 }
482 if (X509_STORE_CTX_init(ctx, store, NULL, NULL) != 1) {
483 X509_STORE_free(store);
484 X509_STORE_CTX_free(ctx);
485 return NULL;
486 }
487 obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, subjectName);
488 if (obj == NULL) {
489 X509_STORE_free(store);
490 X509_STORE_CTX_free(ctx);
491 return NULL;
492 }
493 cert = X509_OBJECT_get0_X509(obj);
494 X509_STORE_free(store);
495 X509_OBJECT_free(obj);
496 X509_STORE_CTX_free(ctx);
497
498 return cert;
499 }
500
SubAltNameArrayDataClearAndFree(SubAltNameArray * array)501 void SubAltNameArrayDataClearAndFree(SubAltNameArray *array)
502 {
503 if (array == NULL) {
504 LOGD("The input array is null, no need to free.");
505 return;
506 }
507 if (array->data != NULL) {
508 for (uint32_t i = 0; i < array->count; ++i) {
509 CF_FREE_BLOB(array->data[i].name);
510 }
511 CfFree(array->data);
512 array->data = NULL;
513 array->count = 0;
514 }
515 }
516
GetPubKeyDataFromX509(X509 * x509,CfBlob ** pub)517 CfResult GetPubKeyDataFromX509(X509 *x509, CfBlob **pub)
518 {
519 EVP_PKEY *pkey = X509_get0_pubkey(x509);
520 if (pkey == NULL) {
521 return CF_ERR_CRYPTO_OPERATION;
522 }
523
524 *pub = (CfBlob *)CfMalloc(sizeof(CfBlob), 0);
525 if (*pub == NULL) {
526 LOGE("Failed to malloc pub key!");
527 return CF_ERR_MALLOC;
528 }
529
530 int32_t size = i2d_PUBKEY(pkey, &((*pub)->data));
531 if (size <= 0) {
532 LOGE("Failed to convert public key to DER format");
533 CfFree(*pub);
534 *pub = NULL;
535 return CF_INVALID_PARAMS;
536 }
537 (*pub)->size = (uint32_t)size;
538 return CF_SUCCESS;
539 }
540
GetSubjectNameFromX509(X509 * cert,CfBlob ** sub)541 CfResult GetSubjectNameFromX509(X509 *cert, CfBlob **sub)
542 {
543 if (cert == NULL) {
544 LOGE("No certificate found in when get subject name");
545 return CF_INVALID_PARAMS;
546 }
547 X509_NAME *name = X509_get_subject_name(cert);
548 if (!name) {
549 LOGE("Failed to get subject name!");
550 return CF_INVALID_PARAMS;
551 }
552 *sub = (CfBlob *)CfMalloc(sizeof(CfBlob), 0);
553 if (*sub == NULL) {
554 LOGE("Failed to malloc pub key!");
555 return CF_ERR_MALLOC;
556 }
557
558 int32_t size = i2d_X509_NAME(name, &((*sub)->data));
559 if (size <= 0) {
560 LOGE("Failed to get subject DER data!");
561 CfFree(*sub);
562 *sub = NULL;
563 return CF_ERR_CRYPTO_OPERATION;
564 }
565 (*sub)->size = (uint32_t)size;
566 return CF_SUCCESS;
567 }
568
GetNameConstraintsFromX509(X509 * cert,CfBlob ** name)569 CfResult GetNameConstraintsFromX509(X509 *cert, CfBlob **name)
570 {
571 if (cert == NULL) {
572 LOGE("No certificate found in when get name constraints");
573 return CF_INVALID_PARAMS;
574 }
575 ASN1_BIT_STRING *nc = X509_get_ext_d2i(cert, NID_name_constraints, NULL, NULL);
576 if (!nc) {
577 LOGE("No nameConstraints found in certificate");
578 return CF_INVALID_PARAMS;
579 }
580 *name = (CfBlob *)CfMalloc(sizeof(CfBlob), 0);
581 if (*name == NULL) {
582 LOGE("Failed to malloc pub key!");
583 return CF_ERR_MALLOC;
584 }
585 int32_t size = i2d_ASN1_BIT_STRING(nc, &((*name)->data));
586 ASN1_BIT_STRING_free(nc);
587 if (size < 0) {
588 LOGE("Failed to get name DER data!");
589 CfFree(*name);
590 *name = NULL;
591 return CF_ERR_CRYPTO_OPERATION;
592 }
593 (*name)->size = (uint32_t)size;
594 return CF_SUCCESS;
595 }
596