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