From c7a0f69b5ce95cdbddbd86eb1329f3741732fc51 Mon Sep 17 00:00:00 2001 From: zhao_zhen_zhou Date: Tue, 3 Jan 2023 22:24:14 -0800 Subject: [PATCH 1/2] add openssl interface Signed-off-by: zhao_zhen_zhou --- .../cert_manager_engine/main/core/BUILD.gn | 1 + .../core/include/x509_certificate_openssl.h | 25 +++++++++ .../main/core/src/x509_certificate_openssl.c | 54 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h create mode 100644 services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c diff --git a/services/cert_manager_standard/cert_manager_engine/main/core/BUILD.gn b/services/cert_manager_standard/cert_manager_engine/main/core/BUILD.gn index 83f68fa..f5cf2d6 100644 --- a/services/cert_manager_standard/cert_manager_engine/main/core/BUILD.gn +++ b/services/cert_manager_standard/cert_manager_engine/main/core/BUILD.gn @@ -61,6 +61,7 @@ ohos_shared_library("cert_manager_engine_core_standard") { "src/cert_manager_uri.c", "src/cm_event_process.c", "src/rbtree.c", + "src/x509_certificate_openssl.c", ] deps = [ diff --git a/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h b/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h new file mode 100644 index 0000000..a44ce97 --- /dev/null +++ b/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cm_type.h" + +enum CertEncodingFormat { + CM_FORMAT_DER = 0, + CM_FORMAT_PEM = 1, +}; + +X509 *CreateX509CertInner(const struct CmBlob *encodeBlob, enum CertEncodingFormat format); + +long GetSerialNumberX509Openssl(X509 *x509Cert); diff --git a/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c b/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c new file mode 100644 index 0000000..909d540 --- /dev/null +++ b/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "x509_certificate_openssl.h" + +#include +#include +#include +#include + +X509 *CreateX509CertInner(const struct CmBlob *encodeBlob, enum CertEncodingFormat format) +{ + if (CmCheckBlob(encodeBlob) != CM_SUCCESS) { + CM_LOG_E("invalid encode cert data"); + return NULL; + } + + X509 *x509 = NULL; + BIO *bio = BIO_new_mem_buf(encodeBlob->data, encodeBlob->size); + if (bio == NULL) { + CM_LOG_E("Openssl bio new buf failed."); + return NULL; + } + CM_LOG_I("The input cert format is: %d.", format); + if (format == CM_FORMAT_DER) { + x509 = d2i_X509_bio(bio, NULL); + } else if (format == CM_FORMAT_PEM) { + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + } + BIO_free(bio); + return x509; +} + +long GetSerialNumberX509Openssl(X509 *x509Cert) +{ + const ASN1_INTEGER *serial = X509_get0_serialNumber(x509Cert); + if (serial == NULL) { + CM_LOG_E("Failed to get serial number!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + return ASN1_INTEGER_get(serial); +} -- Gitee From d2278781839b00bfb40db536dd3d47b2a61a14b8 Mon Sep 17 00:00:00 2001 From: zhao_zhen_zhou Date: Wed, 4 Jan 2023 00:37:14 -0800 Subject: [PATCH 2/2] add test code Signed-off-by: zhao_zhen_zhou --- .../main/common/include/cm_type.h | 4 + .../core/include/x509_certificate_openssl.h | 88 +- .../main/core/src/x509_certificate_openssl.c | 791 +++++++++++++++++- test/unittest/module_test/BUILD.gn | 3 + .../module_test/src/cm_x509_openssl_test.cpp | 684 +++++++++++++++ 5 files changed, 1517 insertions(+), 53 deletions(-) create mode 100644 test/unittest/module_test/src/cm_x509_openssl_test.cpp diff --git a/frameworks/cert_manager_standard/main/common/include/cm_type.h b/frameworks/cert_manager_standard/main/common/include/cm_type.h index 699f847..8042147 100644 --- a/frameworks/cert_manager_standard/main/common/include/cm_type.h +++ b/frameworks/cert_manager_standard/main/common/include/cm_type.h @@ -133,6 +133,10 @@ enum CmErrorCode { CMR_ERROR_AUTH_CHECK_FAILED = -24, CMR_ERROR_KEY_OPERATION_FAILED = -25, CMR_ERROR_NOT_SYSTEMP_APP = -26, + + CMR_ERROR_CRYPTO_OPERATION_FAILED = -27, + CMR_ERROR_CERT_NOT_YET_VALID = -28, + CMR_ERROR_CERT_HAS_EXPIRED = -29, }; enum CMErrorCode { /* temp use */ diff --git a/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h b/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h index a44ce97..4ca400b 100644 --- a/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h +++ b/services/cert_manager_standard/cert_manager_engine/main/core/include/x509_certificate_openssl.h @@ -11,15 +11,79 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - -#include "cm_type.h" - -enum CertEncodingFormat { - CM_FORMAT_DER = 0, - CM_FORMAT_PEM = 1, -}; - -X509 *CreateX509CertInner(const struct CmBlob *encodeBlob, enum CertEncodingFormat format); - -long GetSerialNumberX509Openssl(X509 *x509Cert); + */ +#ifndef X509_CERTIFICATE_OPENSSL_H +#define X509_CERTIFICATE_OPENSSL_H + +#include + +#include "cm_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CM_OPENSSL_SUCCESS 1 /* openssl return 1: success */ + +enum CertEncodingFormat { + CM_FORMAT_DER = 0, + CM_FORMAT_PEM = 1, +}; + +struct CmBlobArray{ + struct CmBlob *data; + uint32_t count; +}; + +X509 *CreateX509CertInner(const struct CmBlob *encodeBlob, enum CertEncodingFormat format); + +void DestroyX509Openssl(X509 **x509Cert); + +void DestroyPkeyOpenssl(EVP_PKEY **pubKey); + +long GetSerialNumberX509Openssl(const X509 *x509Cert); + +int32_t VerifyX509Openssl(X509 *x509Cert, EVP_PKEY *pubKey); + +int32_t GetEncodedX509Openssl(X509 *x509Cert, + struct CmBlob *encodedOutBlob, enum CertEncodingFormat *format); + +int32_t GetPublicKeyX509Openssl(X509 *x509Cert, EVP_PKEY **pubKey); + +int32_t CheckValidityWithDateX509Openssl(const X509 *x509Cert, const char *date); + +long GetVersionX509Openssl(const X509 *x509Cert); + +int32_t GetIssuerDNX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetSubjectDNX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetNotBeforeX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetNotAfterX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetSignatureX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetSigAlgNameX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetSigAlgOidX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetSigAlgParamsX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +int32_t GetKeyUsageX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob); + +void CmArrayDataClearAndFree(struct CmBlobArray *keyUsageObject); + +int32_t GetExtendedKeyUsageX509Openssl(const X509 *x509Cert, struct CmBlobArray *keyUsageOut); + +int32_t GetBasicConstraintsX509Openssl(const X509 *x509Cert); + +int32_t GetSubjectAltNamesX509Openssl(const X509 *x509Cert, struct CmBlobArray *outName); + +int32_t GetIssuerAltNamesX509Openssl(const X509 *x509Cert, struct CmBlobArray *outName); + +#ifdef __cplusplus +} +#endif + +#endif /* X509_CERTIFICATE_OPENSSL_H */ diff --git a/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c b/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c index 909d540..a94a494 100644 --- a/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c +++ b/services/cert_manager_standard/cert_manager_engine/main/core/src/x509_certificate_openssl.c @@ -11,44 +11,753 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - -#include "x509_certificate_openssl.h" - -#include -#include -#include -#include - -X509 *CreateX509CertInner(const struct CmBlob *encodeBlob, enum CertEncodingFormat format) -{ - if (CmCheckBlob(encodeBlob) != CM_SUCCESS) { - CM_LOG_E("invalid encode cert data"); - return NULL; - } - - X509 *x509 = NULL; - BIO *bio = BIO_new_mem_buf(encodeBlob->data, encodeBlob->size); - if (bio == NULL) { - CM_LOG_E("Openssl bio new buf failed."); - return NULL; - } - CM_LOG_I("The input cert format is: %d.", format); - if (format == CM_FORMAT_DER) { - x509 = d2i_X509_bio(bio, NULL); - } else if (format == CM_FORMAT_PEM) { - x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); - } - BIO_free(bio); - return x509; -} - -long GetSerialNumberX509Openssl(X509 *x509Cert) -{ - const ASN1_INTEGER *serial = X509_get0_serialNumber(x509Cert); - if (serial == NULL) { - CM_LOG_E("Failed to get serial number!"); - return CMR_ERROR_INVALID_ARGUMENT; - } - return ASN1_INTEGER_get(serial); -} + */ + +#include "x509_certificate_openssl.h" + +#include +#include +#include +#include +#include + +#include "cm_log.h" +#include "cm_mem.h" +#include "securec.h" + +#define CM_OPENSSL_ERROR_LEN 128 +#define CM_MAX_STR_LEN 1024 +#define CM_MAX_BUFFER_LEN 8192 +#define OID_STR_MAX_LEN 128 +#define CHAR_TO_BIT_LEN 8 +#define FLAG_BIT_LEFT_NUM 0x07 + +struct OidToAlgorithmName{ + char *oid; + char *algorithmName; +}; + +static const struct OidToAlgorithmName OID_TO_NAME_MAP[] = { + { "1.2.840.113549.1.1.2", "MD2withRSA" }, + { "1.2.840.113549.1.1.4", "MD5withRSA" }, + { "1.2.840.113549.1.1.5", "SHA1withRSA" }, + { "1.2.840.10040.4.3", "SHA1withDSA" }, + { "1.2.840.10045.4.1", "SHA1withECDSA" }, + { "1.2.840.113549.1.1.14", "SHA224withRSA" }, + { "1.2.840.113549.1.1.11", "SHA256withRSA" }, + { "1.2.840.113549.1.1.12", "SHA384withRSA" }, + { "1.2.840.113549.1.1.13", "SHA512withRSA" }, + { "2.16.840.1.101.3.4.3.1", "SHA224withDSA" }, + { "2.16.840.1.101.3.4.3.2", "SHA256withDSA" }, + { "1.2.840.10045.4.3.1", "SHA224withECDSA" }, + { "1.2.840.10045.4.3.2", "SHA256withECDSA" }, + { "1.2.840.10045.4.3.3", "SHA384withECDSA" }, + { "1.2.840.10045.4.3.4", "SHA512withECDSA" } +}; + +static const char *GetAlgorithmName(const char *oid) +{ + if (oid == NULL) { + CM_LOG_E("Oid is null!"); + return NULL; + } + for (uint32_t i = 0; i < sizeof(OID_TO_NAME_MAP); i++) { + if (strcmp(OID_TO_NAME_MAP[i].oid, oid) == 0) { + return OID_TO_NAME_MAP[i].algorithmName; + } + } + CM_LOG_E("Can not find algorithmName! [oid]: %s", oid); + return NULL; +} + +static void CmLogOpensslError(void) +{ + char szErr[CM_OPENSSL_ERROR_LEN] = {0}; + unsigned long errCode; + + errCode = ERR_get_error(); + ERR_error_string_n(errCode, szErr, CM_OPENSSL_ERROR_LEN); + + CM_LOG_E("[Openssl]: engine fail, error code = %lu, error string = %s", errCode, szErr); +} + +X509 *CreateX509CertInner(const struct CmBlob *encodeBlob, enum CertEncodingFormat format) +{ + if (CmCheckBlob(encodeBlob) != CM_SUCCESS) { + CM_LOG_E("invalid encode cert data"); + return NULL; + } + + X509 *x509 = NULL; + BIO *bio = BIO_new_mem_buf(encodeBlob->data, encodeBlob->size); + if (bio == NULL) { + CM_LOG_E("Openssl bio new buf failed."); + return NULL; + } + CM_LOG_I("The input cert format is: %d.", format); + if (format == CM_FORMAT_DER) { + x509 = d2i_X509_bio(bio, NULL); + } else if (format == CM_FORMAT_PEM) { + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + } + BIO_free(bio); + return x509; +} + +void DestroyX509Openssl(X509 **x509Cert) +{ + if (x509Cert == NULL || *x509Cert == NULL) { + return; + } + + X509_free(*x509Cert); + x509Cert = NULL; +} + +void DestroyPkeyOpenssl(EVP_PKEY **pubKey) +{ + if (pubKey == NULL || *pubKey == NULL) { + return; + } + EVP_PKEY_free(*pubKey); + *pubKey = NULL; +} + +long GetSerialNumberX509Openssl(const X509 *x509Cert) +{ + if (x509Cert == NULL) { + CM_LOG_E("invalid cert data!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + const ASN1_INTEGER *serial = X509_get0_serialNumber(x509Cert); + if (serial == NULL) { + CM_LOG_E("Failed to get serial number!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + return ASN1_INTEGER_get(serial); +} + +int32_t VerifyX509Openssl(X509 *x509Cert, EVP_PKEY *pubKey) +{ + if ((x509Cert == NULL) || (pubKey == NULL)) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + if (X509_verify(x509Cert, pubKey) != CM_OPENSSL_SUCCESS) { + CM_LOG_E("Failed to verify x509 cert's signature."); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + return CM_SUCCESS; +} + +int32_t GetEncodedX509Openssl(X509 *x509Cert, + struct CmBlob *encodedOutBlob, enum CertEncodingFormat *format) +{ + if ((x509Cert == NULL) || (encodedOutBlob == NULL)) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + int32_t length = i2d_X509(x509Cert, NULL); + if (length <= 0) { + CM_LOG_E("Failed to convert internal x509 to der format!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + unsigned char *der = NULL; + (void)i2d_X509(x509Cert, &der); + encodedOutBlob->data = (uint8_t *)CmMalloc(length); + if (encodedOutBlob->data == NULL) { + CM_LOG_E("Failed to malloc for x509 der data!"); + OPENSSL_free(der); + return CMR_ERROR_MALLOC_FAIL; + } + (void)memcpy_s(encodedOutBlob->data, length, der, length); + OPENSSL_free(der); + encodedOutBlob->size = length; + *format = CM_FORMAT_DER; + return CM_SUCCESS; +} + +int32_t GetPublicKeyX509Openssl(X509 *x509Cert, EVP_PKEY **pubKey) +{ + if ((x509Cert == NULL) || (pubKey == NULL)) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + *pubKey = X509_get_pubkey(x509Cert); + if (*pubKey == NULL) { + CM_LOG_E("Failed to get publick key from x509 cert."); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + + return CM_SUCCESS; +} + +static int32_t CompareDateWithCertTime(const X509 *x509Cert, const ASN1_TIME *inputDate) +{ + ASN1_TIME *startDate = X509_get_notBefore(x509Cert); + ASN1_TIME *expirationDate = X509_get_notAfter(x509Cert); + if ((startDate == NULL) || (expirationDate == NULL)) { + CM_LOG_E("Date is null in x509 cert!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + int32_t ret = CM_SUCCESS; + /* 0: equal in ASN1_TIME_compare, -1: a < b, 1: a > b, -2: error. */ + if (ASN1_TIME_compare(inputDate, startDate) < 0) { + CM_LOG_E("Date is not validate in x509 cert!"); + ret = CMR_ERROR_CERT_NOT_YET_VALID; + } else if (ASN1_TIME_compare(expirationDate, inputDate) < 0) { + CM_LOG_E("Date is expired in x509 cert!"); + ret = CMR_ERROR_CERT_HAS_EXPIRED; + } + return ret; +} + +int32_t CheckValidityWithDateX509Openssl(const X509 *x509Cert, const char *date) +{ + if ((x509Cert == NULL) || (date == NULL)) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + ASN1_TIME *asn1InputDate = ASN1_TIME_new(); + if (asn1InputDate == NULL) { + CM_LOG_E("Failed to malloc for asn1 time."); + return CMR_ERROR_MALLOC_FAIL; + } + if (ASN1_TIME_set_string(asn1InputDate, date) != CM_OPENSSL_SUCCESS) { + CM_LOG_E("Failed to set time for asn1 time."); + CmLogOpensslError(); + ASN1_TIME_free(asn1InputDate); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + int32_t ret = CompareDateWithCertTime(x509Cert, asn1InputDate); + ASN1_TIME_free(asn1InputDate); + return ret; +} + +long GetVersionX509Openssl(const X509 *x509Cert) +{ + if (x509Cert == NULL) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + return X509_get_version(x509Cert) + 1; +} + +static int32_t DeepCopyDataToOut(const char *data, uint32_t len, struct CmBlob *out) +{ + out->data = (uint8_t *)CmMalloc(len); + if (out->data == NULL) { + CM_LOG_E("Failed to malloc for sig algorithm params!"); + return CMR_ERROR_MALLOC_FAIL; + } + (void)memcpy_s(out->data, len, data, len); + out->size = len; + return CM_SUCCESS; +} + +int32_t GetIssuerDNX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("[Get issuerDN openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + X509_NAME *issuerName = X509_get_issuer_name(x509Cert); + if (issuerName == NULL) { + CM_LOG_E("Failed to get x509 issuerName in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + char *issuer = (char *)CmMalloc(CM_MAX_STR_LEN + 1); + if (issuer == NULL) { + CM_LOG_E("Failed to malloc for issuer buffer!"); + return CMR_ERROR_MALLOC_FAIL; + } + (void)memset_s(issuer, CM_MAX_STR_LEN + 1, 0, CM_MAX_STR_LEN + 1); + + int32_t ret = CM_SUCCESS; + do { + X509_NAME_oneline(issuerName, issuer, CM_MAX_STR_LEN); + size_t length = strlen(issuer) + 1; + if (length == 1) { + CM_LOG_E("Failed to get oneline issuerName in openssl!"); + ret = CMR_ERROR_CRYPTO_OPERATION_FAILED; + CmLogOpensslError(); + break; + } + ret = DeepCopyDataToOut(issuer, length, outBlob); + } while (0); + CmFree(issuer); + return ret; +} + +int32_t GetSubjectDNX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("[Get subjectDN openssl]The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + + X509_NAME *subjectName = X509_get_subject_name(x509Cert); + if (subjectName == NULL) { + CM_LOG_E("Failed to get x509 subjectName in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + char *subject = (char *)CmMalloc(CM_MAX_STR_LEN + 1); + if (subject == NULL) { + CM_LOG_E("Failed to malloc for subject buffer!"); + return CMR_ERROR_MALLOC_FAIL; + } + + int32_t ret = CM_SUCCESS; + do { + X509_NAME_oneline(subjectName, subject, CM_MAX_STR_LEN); + size_t length = strlen(subject) + 1; + if (length == 1) { + CM_LOG_E("Failed to get oneline subjectName in openssl!"); + CmLogOpensslError(); + ret = CMR_ERROR_CRYPTO_OPERATION_FAILED; + break; + } + ret = DeepCopyDataToOut(subject, length, outBlob); + } while (0); + CmFree(subject); + return ret; +} + +int32_t GetNotBeforeX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("Get not before, input is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + ASN1_TIME *notBeforeDate = X509_get_notBefore(x509Cert); + if (notBeforeDate == NULL) { + CM_LOG_E("NotBeforeDate is null in x509 cert!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + if (ASN1_TIME_normalize(notBeforeDate) != CM_OPENSSL_SUCCESS) { + CM_LOG_E("Failed to normalize notBeforeDate!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + const char *date = (const char *)(notBeforeDate->data); + if ((date == NULL) || (strlen(date) > CM_MAX_STR_LEN)) { + CM_LOG_E("Failed to get notBeforeDate data!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + uint32_t length = strlen(date) + 1; + return DeepCopyDataToOut(date, length, outBlob); +} + +int32_t GetNotAfterX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("Get not after, input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + ASN1_TIME *notAfterDate = X509_get_notAfter(x509Cert); + if (notAfterDate == NULL) { + CM_LOG_E("NotAfterDate is null in x509 cert!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + if (ASN1_TIME_normalize(notAfterDate) != CM_OPENSSL_SUCCESS) { + CM_LOG_E("Failed to normalize notAfterDate!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + const char *date = (const char *)(notAfterDate->data); + if ((date == NULL) || (strlen(date) > CM_MAX_STR_LEN)) { + CM_LOG_E("Failed to get notAfterDate data!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + uint32_t length = strlen(date) + 1; + return DeepCopyDataToOut(date, length, outBlob); +} + +int32_t GetSignatureX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + const ASN1_BIT_STRING *signature; + X509_get0_signature(&signature, NULL, x509Cert); + if ((signature == NULL) || (signature->length == 0) || (signature->length > CM_MAX_BUFFER_LEN)) { + CM_LOG_E("Failed to get x509 signature in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + outBlob->data = (uint8_t *)CmMalloc(signature->length); + if (outBlob->data == NULL) { + CM_LOG_E("Failed to malloc for signature data!"); + return CMR_ERROR_MALLOC_FAIL; + } + (void)memcpy_s(outBlob->data, signature->length, signature->data, signature->length); + outBlob->size = signature->length; + return CM_SUCCESS; +} + +int32_t GetSigAlgNameX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("[GetSigAlgName openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + const X509_ALGOR *alg; + X509_get0_signature(NULL, &alg, x509Cert); + const ASN1_OBJECT *oidObj; + X509_ALGOR_get0(&oidObj, NULL, NULL, alg); + char oidStr[OID_STR_MAX_LEN] = { 0 }; + int32_t resLen = OBJ_obj2txt(oidStr, OID_STR_MAX_LEN, oidObj, 1); + if ((resLen < 0) || (resLen >= OID_STR_MAX_LEN)) { + CM_LOG_E("Failed to convert x509 object to text!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + const char *algName = GetAlgorithmName(oidStr); + if (algName == NULL) { + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + uint32_t len = strlen(algName) + 1; + return DeepCopyDataToOut(algName, len, outBlob); +} + +int32_t GetSigAlgOidX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("[GetSigAlgOID openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + const X509_ALGOR *alg; + X509_get0_signature(NULL, &alg, x509Cert); + const ASN1_OBJECT *oid; + X509_ALGOR_get0(&oid, NULL, NULL, alg); + char algOid[OID_STR_MAX_LEN] = { 0 }; + int32_t resLen = OBJ_obj2txt(algOid, OID_STR_MAX_LEN, oid, 1); + if ((resLen < 0) || (resLen >= OID_STR_MAX_LEN)) { + CM_LOG_E("Failed to convert x509 object to text!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + uint32_t len = strlen(algOid) + 1; + return DeepCopyDataToOut(algOid, len, outBlob); +} + +int32_t GetSigAlgParamsX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("[GetSigAlgParams openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + const X509_ALGOR *alg; + X509_get0_signature(NULL, &alg, x509Cert); + int32_t paramType = 0; + const void *paramValue = NULL; + X509_ALGOR_get0(NULL, ¶mType, ¶mValue, alg); + if (paramType == V_ASN1_UNDEF) { + CM_LOG_E("get_X509_ALGOR_parameter, no parameters!"); + return CMR_ERROR_NOT_SUPPORTED; + } + ASN1_TYPE *param = ASN1_TYPE_new(); + if (param == NULL) { + CM_LOG_E("Failed to malloc for asn1 type data!"); + return CMR_ERROR_MALLOC_FAIL; + } + if (ASN1_TYPE_set1(param, paramType, paramValue) != CM_OPENSSL_SUCCESS) { + CM_LOG_E("Failed to set asn1 type in openssl!"); + CmLogOpensslError(); + ASN1_TYPE_free(param); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + unsigned char *out = NULL; + int32_t len = i2d_ASN1_TYPE(param, NULL); + if (len <= 0) { + CM_LOG_E("Failed to convert ASN1_TYPE!"); + CmLogOpensslError(); + ASN1_TYPE_free(param); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + (void)i2d_ASN1_TYPE(param, &out); + ASN1_TYPE_free(param); + int32_t ret = DeepCopyDataToOut((const char *)out, len, outBlob); + OPENSSL_free(out); + return ret; +} + +static int32_t ConvertAsn1String2BoolArray(const ASN1_BIT_STRING *string, struct CmBlob *outBlob) +{ + uint32_t length = ASN1_STRING_length(string) * CHAR_TO_BIT_LEN; + if (string->flags & ASN1_STRING_FLAG_BITS_LEFT) { + length -= string->flags & FLAG_BIT_LEFT_NUM; + } + outBlob->data = (uint8_t *)CmMalloc(length); + if (outBlob->data == NULL) { + CM_LOG_E("Failed to malloc for bit array data!"); + return CMR_ERROR_MALLOC_FAIL; + } + for (uint32_t i = 0; i < length; i++) { + outBlob->data[i] = ASN1_BIT_STRING_get_bit(string, i); + } + outBlob->size = length; + return CM_SUCCESS; +} + +int32_t GetKeyUsageX509Openssl(const X509 *x509Cert, struct CmBlob *outBlob) +{ + if ((x509Cert == NULL) || (outBlob == NULL)) { + CM_LOG_E("[GetKeyUsage openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + ASN1_BIT_STRING *keyUsage = (ASN1_BIT_STRING *)X509_get_ext_d2i(x509Cert, NID_key_usage, NULL, NULL); + if ((keyUsage == NULL) || (keyUsage->length <= 0)|| (keyUsage->length >= CM_MAX_STR_LEN)) { + CM_LOG_E("Failed to get x509 keyUsage in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + int32_t ret = ConvertAsn1String2BoolArray(keyUsage, outBlob); + ASN1_BIT_STRING_free(keyUsage); + return ret; +} + +static int32_t DeepCopyExtendedKeyUsage(const STACK_OF(ASN1_OBJECT) *extUsage, + int32_t i, struct CmBlobArray *keyUsageOut) +{ + char usage[OID_STR_MAX_LEN] = { 0 }; + int32_t resLen = OBJ_obj2txt(usage, OID_STR_MAX_LEN, sk_ASN1_OBJECT_value(extUsage, i), 1); + if ((resLen < 0) || (resLen >= OID_STR_MAX_LEN)) { + CM_LOG_E("Failed to convert x509 object to text!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + uint32_t len = strlen(usage) + 1; + keyUsageOut->data[i].data = (uint8_t *)CmMalloc(len); + if (keyUsageOut->data[i].data == NULL) { + CM_LOG_E("Failed to malloc for key usage!"); + return CMR_ERROR_MALLOC_FAIL; + } + (void)memcpy_s(keyUsageOut->data[i].data, len, usage, len); + keyUsageOut->data[i].size = len; + return CM_SUCCESS; +} + +void CmArrayDataClearAndFree(struct CmBlobArray *keyUsageObject) +{ + if (keyUsageObject == NULL || keyUsageObject->data == NULL) { + CM_LOG_E("The input array is null, no need to free."); + return; + } + for (uint32_t i = 0; i < keyUsageObject->count; ++i) { + CM_FREE_PTR(keyUsageObject->data[i].data); + keyUsageObject->data[i].size = 0; + } + keyUsageObject->count = 0; + CM_FREE_PTR(keyUsageObject->data); +} + +int32_t GetExtendedKeyUsageX509Openssl(const X509 *x509Cert, struct CmBlobArray *keyUsageOut) +{ + if ((x509Cert == NULL) || (keyUsageOut == NULL)) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + STACK_OF(ASN1_OBJECT) *extUsage = X509_get_ext_d2i(x509Cert, NID_ext_key_usage, NULL, NULL); + if (extUsage == NULL) { + CM_LOG_E("Failed to get x509 extended keyUsage in openssl!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + int32_t ret = CM_SUCCESS; + do { + int32_t size = sk_ASN1_OBJECT_num(extUsage); + if (size <= 0) { + CM_LOG_E("The extended key usage size in openssl is invalid!"); + CmLogOpensslError(); + ret = CMR_ERROR_CRYPTO_OPERATION_FAILED; + break; + } + int32_t blobSize = sizeof(struct CmBlob) * size; + keyUsageOut->data = (struct CmBlob *)CmMalloc(blobSize); + if (keyUsageOut->data == NULL) { + CM_LOG_E("Failed to malloc for keyUsageOut array!"); + ret = CMR_ERROR_MALLOC_FAIL; + break; + } + keyUsageOut->count = size; + for (int32_t i = 0; i < size; ++i) { + ret = DeepCopyExtendedKeyUsage(extUsage, i, keyUsageOut); + if (ret != CM_SUCCESS) { + CM_LOG_E("Falied to copy extended key usage!"); + break; + } + } + } while (0); + if (ret != CM_SUCCESS) { + CmArrayDataClearAndFree(keyUsageOut); + } + sk_ASN1_OBJECT_pop_free(extUsage, ASN1_OBJECT_free); + return ret; +} + +int32_t GetBasicConstraintsX509Openssl(const X509 *x509Cert) +{ + if (x509Cert == NULL) { + CM_LOG_E("The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + BASIC_CONSTRAINTS *constraints = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(x509Cert, NID_basic_constraints, NULL, NULL); + if (constraints == NULL) { + CM_LOG_E("Failed to get basic constraints in openssl!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + /* Path len is only valid for CA cert. */ + if (!constraints->ca) { + CM_LOG_E("The cert in not a CA!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + if ((constraints->pathlen == NULL) || (constraints->pathlen->type == V_ASN1_NEG_INTEGER)) { + CM_LOG_E("The cert path len is negative in openssl!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + long pathLen = ASN1_INTEGER_get(constraints->pathlen); + if ((pathLen < 0) || (pathLen > INT_MAX)) { + CM_LOG_E("Get the overflow path length in openssl!"); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + return (int32_t)pathLen; +} + +static int32_t DeepCopyAlternativeNames(const STACK_OF(GENERAL_NAME) *altNames, + int32_t i, struct CmBlobArray *outName) +{ + GENERAL_NAME *general = sk_GENERAL_NAME_value(altNames, i); + int32_t generalType = 0; + ASN1_STRING *ans1Str = GENERAL_NAME_get0_value(general, &generalType); + const char *str = (const char *)ASN1_STRING_get0_data(ans1Str); + if ((str == NULL) || (strlen(str) > CM_MAX_STR_LEN)) { + CM_LOG_E("Failed to get x509 altNames string in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + uint32_t nameLen = strlen(str) + 1; + outName->data[i].data = (uint8_t *)CmMalloc(nameLen); + if (outName->data[i].data == NULL) { + CM_LOG_E("Failed to malloc for outName!"); + return CMR_ERROR_MALLOC_FAIL; + } + (void)memcpy_s(outName->data[i].data, nameLen, str, nameLen); + outName->data[i].size = nameLen; + return CM_SUCCESS; +} + +int32_t GetSubjectAltNamesX509Openssl(const X509 *x509Cert, struct CmBlobArray *outName) +{ + if ((x509Cert == NULL) || (outName == NULL)) { + CM_LOG_E("[GetSubjectAltNames openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + STACK_OF(GENERAL_NAME) *subjectAltName = X509_get_ext_d2i(x509Cert, NID_subject_alt_name, NULL, NULL); + if (subjectAltName == NULL) { + CM_LOG_E("Failed to get subjectAltName in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + int32_t ret = CM_SUCCESS; + do { + int32_t size = sk_GENERAL_NAME_num(subjectAltName); + if (size <= 0) { + CM_LOG_E("The subjectAltName number in openssl is invalid!"); + CmLogOpensslError(); + ret = CMR_ERROR_CRYPTO_OPERATION_FAILED; + break; + } + int32_t blobSize = sizeof(struct CmBlob) * size; + outName->data = (struct CmBlob *)CmMalloc(blobSize); + if (outName->data == NULL) { + CM_LOG_E("Failed to malloc for subjectAltName array!"); + ret = CMR_ERROR_MALLOC_FAIL; + break; + } + outName->count = size; + for (int32_t i = 0; i < size; ++i) { + ret = DeepCopyAlternativeNames(subjectAltName, i, outName); + if (ret != CM_SUCCESS) { + CM_LOG_E("Falied to copy subjectAltName!"); + break; + } + } + } while (0); + if (ret != CM_SUCCESS) { + CmArrayDataClearAndFree(outName); + } + GENERAL_NAMES_free(subjectAltName); + return ret; +} + +int32_t GetIssuerAltNamesX509Openssl(const X509 *x509Cert, struct CmBlobArray *outName) +{ + if ((x509Cert == NULL) || (outName == NULL)) { + CM_LOG_E("[GetIssuerAltNames openssl] The input data is null!"); + return CMR_ERROR_INVALID_ARGUMENT; + } + + STACK_OF(GENERAL_NAME) *issuerAltName = X509_get_ext_d2i(x509Cert, NID_issuer_alt_name, NULL, NULL); + if (issuerAltName == NULL) { + CM_LOG_E("Failed to get issuerAltName in openssl!"); + CmLogOpensslError(); + return CMR_ERROR_CRYPTO_OPERATION_FAILED; + } + int32_t ret = CM_SUCCESS; + do { + int32_t size = sk_GENERAL_NAME_num(issuerAltName); + if (size <= 0) { + CM_LOG_E("The issuerAltName number in openssl is invalid!"); + CmLogOpensslError(); + ret = CMR_ERROR_CRYPTO_OPERATION_FAILED; + break; + } + int32_t blobSize = sizeof(struct CmBlob) * size; + outName->data = (struct CmBlob *)CmMalloc(blobSize); + if (outName->data == NULL) { + CM_LOG_E("Failed to malloc for issuerAltName array!"); + ret = CMR_ERROR_MALLOC_FAIL; + break; + } + outName->count = size; + for (int32_t i = 0; i < size; ++i) { + ret = DeepCopyAlternativeNames(issuerAltName, i, outName); + if (ret != CM_SUCCESS) { + CM_LOG_E("Falied to copy issuerAltName!"); + break; + } + } + } while (0); + if (ret != CM_SUCCESS) { + CmArrayDataClearAndFree(outName); + } + GENERAL_NAMES_free(issuerAltName); + return ret; +} diff --git a/test/unittest/module_test/BUILD.gn b/test/unittest/module_test/BUILD.gn index 6be2cff..d93ec81 100644 --- a/test/unittest/module_test/BUILD.gn +++ b/test/unittest/module_test/BUILD.gn @@ -21,9 +21,11 @@ ohos_unittest("cm_module_test") { "src/cm_cert_parse_test.cpp", "src/cm_log_test.cpp", "src/cm_param_test.cpp", + "src/cm_x509_openssl_test.cpp", ] include_dirs = [ + "//base/security/certificate_manager/services/cert_manager_standard/cert_manager_engine/main/core/include", "//third_party/bounds_checking_function/include", "//third_party/openssl/include", "include", @@ -37,6 +39,7 @@ ohos_unittest("cm_module_test") { deps = [ "//base/security/certificate_manager/frameworks/cert_manager_standard/main:cert_manager_standard_frameworks", "//base/security/certificate_manager/interfaces/innerkits/cert_manager_standard/main:cert_manager_sdk", + "//base/security/certificate_manager/services/cert_manager_standard/cert_manager_engine/main/core:cert_manager_engine_core_standard", "//third_party/bounds_checking_function:libsec_static", "//third_party/googletest:gtest_main", "//third_party/openssl:libcrypto_shared", diff --git a/test/unittest/module_test/src/cm_x509_openssl_test.cpp b/test/unittest/module_test/src/cm_x509_openssl_test.cpp new file mode 100644 index 0000000..46904f8 --- /dev/null +++ b/test/unittest/module_test/src/cm_x509_openssl_test.cpp @@ -0,0 +1,684 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "cm_mem.h" +#include "x509_certificate_openssl.h" + +using namespace testing::ext; +namespace { +static char g_deviceTestCert[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIEQDCCAyigAwIBAgIQICAIMRlDU0ytSEUfNeOUJTANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQG\r\n" +"EwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMScwJQYDVQQDDB5IdWF3\r\n" +"ZWkgQ0JHIE1vYmlsZSBFcXVpcG1lbnQgQ0EwHhcNMjAwODMxMTE0MzUzWhcNMzAwODI5MTE0MzUz\r\n" +"WjBvMQswCQYDVQQGEwJDTjEPMA0GA1UECgwGSHVhd2VpMRMwEQYDVQQLDApIdWF3ZWkgQ0JHMTow\r\n" +"OAYDVQQDDDFIVUFXRUlfSFdKQURfODE4ZjhjNDUtOGNmNC00ZTM2LTkxOTMtNTQ5OWMwNzM0YzM4\r\n" +"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArZcfL6ot4z6k3T4X3C26EI557Zvrx9Ci\r\n" +"hNx6RMy+vjXa3E4BkxwZ3r0ADbc+msJOq0IyQJNujaLq35oQvJgMIvBn1xFurBXdOzbygc7G9GKt\r\n" +"sb4rmKUP0QEPHM2/TrxAJT2LNPLrOE047ESe2X76FpDY6oZdsoGJ5I9m/mlfGsxR1l1TeUjwA/Rs\r\n" +"UtISR66aastBy2tU7IubP0B0Gceqy9DnjTQtY9OpkOql08H20C30iCVijK6BmP43X4OMz2MS0leV\r\n" +"K0AHmhiv6ufu166Xtc2JOXRk/MJ+53iprvVEUowKY/ZATUz6iDHDZYM3MdQV+VbFrOevUceOSweY\r\n" +"PaXCzwIDAQABo4HqMIHnMB8GA1UdIwQYMBaAFDXT2UhPcFFNI7Ey1dXdJSHOBS7dMB0GA1UdDgQW\r\n" +"BBSndBqCYYcTB1kMNhYMM4r/vDLteTARBglghkgBhvhCAQEEBAMCBsAwCwYDVR0PBAQDAgTwMGYG\r\n" +"A1UdHwRfMF0wW6BZoFeGVWh0dHA6Ly9jcGtpLWNhd2ViLmh1YXdlaS5jb20vY3BraS9zZXJ2bGV0\r\n" +"L2NybEZpbGVEb3duLmNybD9jZXJ0eXBlPTQmeWVhcj0vY3JsMjAyMC5jcmwwHQYDVR0lBBYwFAYI\r\n" +"KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQCNTqZHRy7BJ+KFOflqwYkeD1Yd\r\n" +"K5XxcZUykw8AefX3SMYzSBzy7IIIhM5bvhWF6r5NnBJYqmyQfy+3K0Z0LQXfsY95U9JBkKl3nQPn\r\n" +"p1PzV8wLp/XYE7ePsbIbjQ1gQdC47sTDjoA73X4wEchdEVJBNUs2e15HRxbzaVJ6ABSKI9AHkxKv\r\n" +"o9iYKFozQaL4y+3Y+Yei/N1kiZZayJqC1uXq45kelc3SCJrVPE4g/Uspf2jjp7xsS+MkmxvSAT9X\r\n" +"OJeDWEeXyt7tvJeodRQgGZVhdtN78mtoaqWqD9Z6a6wpWdC4sZCWJfMjCu4Wd889Pn4MT5DBKBN3\r\n" +"f3+JpOzUJlM9\r\n" +"-----END CERTIFICATE-----\r\n"; + +static char g_rootCert[] = +"-----BEGIN CERTIFICATE-----\r\n" +"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\r\n" +"jI6AaoTlr5I7zPhFbR8/XEs7DzI=\r\n" +"-----END CERTIFICATE-----\r\n"; + +static char g_secondCert[] = +"-----BEGIN CERTIFICATE-----\r\n" +"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\r\n" +"-----END CERTIFICATE-----\r\n"; + +static char g_testInvalidCert[] = +"-----xxxx CERTIFICATE-----\r\n" +"MIIDpzCCAo+gAwIBAgICAQAwDQYJKoZIhvcNAQELBQAwbDELMAkGA1UEBhMCQ04x\r\n" +"CzAJBgNVBAgMAkJKMQswCQYDVQQHDAJCSjELMAkGA1UECgwCSEQxDDAKBgNVBAsM\r\n" +"A2RldjELMAkGA1UEAwwCY2ExGzAZBgkqhkiG9w0BCQEWDGNhQHdvcmxkLmNvbTAe\r\n" +"Fw0yMjA4MTkwNTE2MTVaFw0yMzA4MTkwNTE2MTVaMGwxCzAJBgNVBAYTAkNOMQsw\r\n" +"CQYDVQQIDAJCSjELMAkGA1UEBwwCQkoxCzAJBgNVBAoMAkhEMQwwCgYDVQQLDANk\r\n" +"ZXYxCzAJBgNVBAMMAmNhMRswGQYJKoZIhvcNAQkBFgxjYUB3b3JsZC5jb20wggEi\r\n" +"MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuvLoVT5em7ApBma8xtgpcFcaU\r\n" +"CbXBJSUl2NpFW2sriucbEOvKRdw9KvLa/tSP6CupPZVKIzHAP2oeW88aFBr23miG\r\n" +"iR49M52c73Iw3H3EG2ckK8M1mxEzXSqynivqiNZDKG+bA5cFzcfmk6Th1bJan9w9\r\n" +"Ci8HPSBvgg7Rc6pqNM4HjTHl3Bb6cf4Xh3/GgpjypTd9jAAEyq+l/+1pnTYVlIJA\r\n" +"WGh0Z26RosXfzwfFKH77ysTjoj9ambvGmFsMXvNXEyYmBCeYND6xGj4pa2lylsra\r\n" +"kfYmGxcFQ45Lj5oWdNQQVdvrQiYWu3SJOC/WqB5UIAq92PPrq1apznxfjqABAgMB\r\n" +"AAGjUzBRMB0GA1UdDgQWBBRI5iWwjBMAOCcgcUjUCYJdsvwEMjAfBgNVHSMEGDAW\r\n" +"gBRI5iWwjBMAOCcgcUjUCYJdsvwEMjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\r\n" +"DQEBCwUAA4IBAQABop7EJgS2czHKWVzdEwjbi9m5ZUPy6aOV9paV1e/5IyFNHwun\r\n" +"B64iwcg03+FmIWNuynb1mglHHrUoXygXu9GIR8cWfOI3W+Pnn8fDi8MxQMn/e/Jj\r\n" +"BuGcnRwKynRhyLdkyWYn1YwqenMuFJu9yzkhfAPltGFEuPYCWDatdhm6zhFdu1PE\r\n" +"EMErHpQOT45z5cgC4XqgKlE+n8L4/5RfZnbuUJ3bV+FuI+VApLGXJQlJQAOTqBDg\r\n" +"k7DMSgPUUxYYa6AGMFy6vqQ6hcgCMK08ko8LdjVd1MobKzM9Oh480GFZA/ubR3QW\r\n" +"lv3OuOhmnIxNGcPUiqpSiWKqR5tf1KUImIR9\r\n" +"-----END CERTIFICATE-----\r\n"; + + +/* g_testSelfSignedCaCert +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 272 (0x110) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = CN, ST = BJ, L = BJ, O = HD, OU = dev, CN = ca, emailAddress = ca@cryptoframework.com + Validity + Not Before: Aug 19 12:49:06 2022 GMT + Not After : Aug 16 12:49:06 2032 GMT + Subject: C = CN, ST = BJ, L = BJ, O = HD, OU = dev, CN = ca, emailAddress = ca@cryptoframework.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:9f:29:d0:85:84:ed:6c:30:6e:d0:13:83:e0:1b: + 61:08:f7:dd:63:41:06:4b:54:fb:f0:15:7f:e4:e5: + d5:a0:1a:e1:33:9e:5b:6f:d9:01:17:38:b1:dc:0b: + 55:3c:5d:5c:28:a9:16:c7:ae:88:63:77:d2:1c:17: + ad:71:54:1e:b7:0c:7f:4c:36:b0:29:33:9c:95:59: + fe:b4:1c:7c:43:b9:29:bd:6f:07:3e:83:10:47:20: + 21:26:04:86:1a:8e:05:f6:01:8a:de:6a:7e:9a:b9: + 47:6f:b6:47:f4:e1:ff:26:d5:fa:40:6b:52:5f:86: + b2:c5:db:0c:07:ba:a1:90:b2:e7:a9:46:a6:10:ef: + 98:73:14:3b:b6:b5:de:3f:92:16:64:e1:31:b2:36: + c9:ec:ae:6b:52:da:81:2a:1a:04:97:d8:d4:9f:a2: + ee:35:8f:9a:61:05:47:47:50:da:9d:04:1a:31:d3: + 81:01:a1:46:8e:55:bb:00:c7:8a:93:52:bf:45:cf: + f0:e5:00:fc:f6:1b:2f:f4:81:8f:51:6a:e0:2d:e0: + b5:fb:e3:7a:cc:14:6f:35:5a:32:8a:bf:c0:2b:b2: + d6:a7:17:23:cd:19:2d:ed:f0:85:1d:b8:73:47:17: + 60:53:b4:b8:68:bd:7a:03:e9:db:87:f0:ef:26:06: + aa:01 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:A3:3B:42:63:01:B3:4D:51:F6:E4:2D:B5:83:7F:18:39:2F:B7:B5 + X509v3 Authority Key Identifier: + keyid:8C:A3:3B:42:63:01:B3:4D:51:F6:E4:2D:B5:83:7F:18:39:2F:B7:B5 + + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:2 + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Subject Alternative Name: + email:ca@cryptoframework.com + X509v3 Issuer Alternative Name: + email:ca@cryptoframework.com + Signature Algorithm: sha256WithRSAEncryption + 87:ee:11:13:a7:09:eb:6f:e0:2d:8b:2c:2e:47:3b:11:28:3b: + 7b:12:b0:66:59:a2:b0:7c:81:89:cb:b2:ff:e5:da:80:e6:77: + 71:36:e0:40:d5:e5:42:86:4a:6f:0f:e4:b3:f0:7f:70:89:db: + 40:66:1b:a4:09:b8:ed:2b:9d:a3:e2:3f:1b:dc:63:d1:7e:e0: + 40:1f:70:b5:2a:db:4a:d3:ac:e9:28:e7:2e:26:14:d3:11:5c: + 16:c7:34:8f:a9:36:4a:b9:72:8b:04:50:72:34:b8:3c:e2:a2: + 51:2d:02:9b:71:77:0c:71:9d:8f:9e:4f:94:19:17:c6:e7:57: + 0a:ad:95:dc:9d:d5:c0:a7:f6:6d:58:d0:6f:3c:f6:f8:cf:d0: + d6:6f:8f:ec:58:41:f8:99:9e:3b:c7:9e:9a:4a:8c:43:4b:45: + 31:4d:c4:33:8e:35:36:97:a3:0b:98:85:54:01:a0:a3:09:c2: + f1:2d:01:f9:fc:47:f5:d0:49:b8:73:3a:be:9c:44:5b:0d:dc: + 91:91:43:65:0d:64:77:dd:58:46:0a:fb:8d:8f:1f:73:4b:ff: + 4f:4b:73:1d:66:ce:11:5c:e4:94:42:01:58:bd:66:a2:6a:4b: + 04:2c:1e:d3:f1:b0:f8:13:ba:d1:b7:e2:d8:ca:09:c3:cb:76: + 21:c0:75:43 +*/ +static char g_testSelfSignedCaCert[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIEMjCCAxqgAwIBAgICARAwDQYJKoZIhvcNAQELBQAwdjELMAkGA1UEBhMCQ04x\r\n" +"CzAJBgNVBAgMAkJKMQswCQYDVQQHDAJCSjELMAkGA1UECgwCSEQxDDAKBgNVBAsM\r\n" +"A2RldjELMAkGA1UEAwwCY2ExJTAjBgkqhkiG9w0BCQEWFmNhQGNyeXB0b2ZyYW1l\r\n" +"d29yay5jb20wHhcNMjIwODE5MTI0OTA2WhcNMzIwODE2MTI0OTA2WjB2MQswCQYD\r\n" +"VQQGEwJDTjELMAkGA1UECAwCQkoxCzAJBgNVBAcMAkJKMQswCQYDVQQKDAJIRDEM\r\n" +"MAoGA1UECwwDZGV2MQswCQYDVQQDDAJjYTElMCMGCSqGSIb3DQEJARYWY2FAY3J5\r\n" +"cHRvZnJhbWV3b3JrLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\n" +"AJ8p0IWE7WwwbtATg+AbYQj33WNBBktU+/AVf+Tl1aAa4TOeW2/ZARc4sdwLVTxd\r\n" +"XCipFseuiGN30hwXrXFUHrcMf0w2sCkznJVZ/rQcfEO5Kb1vBz6DEEcgISYEhhqO\r\n" +"BfYBit5qfpq5R2+2R/Th/ybV+kBrUl+GssXbDAe6oZCy56lGphDvmHMUO7a13j+S\r\n" +"FmThMbI2yeyua1LagSoaBJfY1J+i7jWPmmEFR0dQ2p0EGjHTgQGhRo5VuwDHipNS\r\n" +"v0XP8OUA/PYbL/SBj1Fq4C3gtfvjeswUbzVaMoq/wCuy1qcXI80ZLe3whR24c0cX\r\n" +"YFO0uGi9egPp24fw7yYGqgECAwEAAaOByTCBxjAdBgNVHQ4EFgQUjKM7QmMBs01R\r\n" +"9uQttYN/GDkvt7UwHwYDVR0jBBgwFoAUjKM7QmMBs01R9uQttYN/GDkvt7UwEgYD\r\n" +"VR0TAQH/BAgwBgEB/wIBAjALBgNVHQ8EBAMCAQYwHQYDVR0lBBYwFAYIKwYBBQUH\r\n" +"AwEGCCsGAQUFBwMCMCEGA1UdEQQaMBiBFmNhQGNyeXB0b2ZyYW1ld29yay5jb20w\r\n" +"IQYDVR0SBBowGIEWY2FAY3J5cHRvZnJhbWV3b3JrLmNvbTANBgkqhkiG9w0BAQsF\r\n" +"AAOCAQEAh+4RE6cJ62/gLYssLkc7ESg7exKwZlmisHyBicuy/+XagOZ3cTbgQNXl\r\n" +"QoZKbw/ks/B/cInbQGYbpAm47Sudo+I/G9xj0X7gQB9wtSrbStOs6SjnLiYU0xFc\r\n" +"Fsc0j6k2SrlyiwRQcjS4POKiUS0Cm3F3DHGdj55PlBkXxudXCq2V3J3VwKf2bVjQ\r\n" +"bzz2+M/Q1m+P7FhB+JmeO8eemkqMQ0tFMU3EM441NpejC5iFVAGgownC8S0B+fxH\r\n" +"9dBJuHM6vpxEWw3ckZFDZQ1kd91YRgr7jY8fc0v/T0tzHWbOEVzklEIBWL1mompL\r\n" +"BCwe0/Gw+BO60bfi2MoJw8t2IcB1Qw==\r\n" +"-----END CERTIFICATE-----\r\n"; + +X509 *g_x509Data = nullptr; +constexpr int TEST_CERT_VERSION = 3; +constexpr int TEST_CERT_CHAIN_LEN = 2; +constexpr int TEST_CERT_SERIAL_NUMBER = 272; + +class CmX509OpensslTest : public testing::Test { +public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); +}; + +void CmX509OpensslTest::SetUpTestCase(void) +{ + struct CmBlob encodeBlob = { + strlen(g_testSelfSignedCaCert) + 1, reinterpret_cast(g_testSelfSignedCaCert) + }; + g_x509Data = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_NE(g_x509Data, nullptr); +} + +void CmX509OpensslTest::TearDownTestCase(void) +{ + DestroyX509Openssl(&g_x509Data); +} + +void CmX509OpensslTest::SetUp() +{ +} + +void CmX509OpensslTest::TearDown() +{ +} + +/* Generate valid PEM format certificate. */ +HWTEST_F(CmX509OpensslTest, GenerateCert001, TestSize.Level0) +{ + struct CmBlob encodeBlob = { + strlen(g_testSelfSignedCaCert) + 1, reinterpret_cast(g_testSelfSignedCaCert) + }; + X509 *x509Cert = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_NE(x509Cert, nullptr); + DestroyX509Openssl(&x509Cert); +} + +/* Invalid input. */ +HWTEST_F(CmX509OpensslTest, GenerateCert002, TestSize.Level0) +{ + struct CmBlob encodeBlob = { 0, nullptr }; + X509 *x509Cert = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_EQ(x509Cert, nullptr); +} + +/* Invalid PEM format. */ +HWTEST_F(CmX509OpensslTest, GenerateCert003, TestSize.Level0) +{ + struct CmBlob encodeBlob = { strlen(g_testInvalidCert) + 1, reinterpret_cast(g_testInvalidCert) }; + X509 *x509Cert = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_EQ(x509Cert, nullptr); +} + +/* Valid DER format. */ +HWTEST_F(CmX509OpensslTest, GenerateCert004, TestSize.Level0) +{ + struct CmBlob encodedOutBlob = { 0, nullptr }; + enum CertEncodingFormat format; + int32_t ret = GetEncodedX509Openssl(g_x509Data, &encodedOutBlob, &format); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_EQ(format, CM_FORMAT_DER); + EXPECT_NE(encodedOutBlob.data, nullptr); + + X509 *x509Cert = CreateX509CertInner(&encodedOutBlob, format); + EXPECT_NE(x509Cert, nullptr); + DestroyX509Openssl(&x509Cert); + CM_FREE_BLOB(encodedOutBlob); +} + +/* verify self signed cert. */ +HWTEST_F(CmX509OpensslTest, Verify001, TestSize.Level0) +{ + EVP_PKEY *keyOut = nullptr; + int32_t ret = GetPublicKeyX509Openssl(g_x509Data, &keyOut); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(keyOut, nullptr); + + ret = VerifyX509Openssl(g_x509Data, keyOut); + EXPECT_EQ(ret, CM_SUCCESS); + DestroyPkeyOpenssl(&keyOut); +} + +/* use root ca cert's public key to verify next cert. */ +HWTEST_F(CmX509OpensslTest, Verify002, TestSize.Level0) +{ + struct CmBlob rootCertBlob = { + strlen(g_rootCert) + 1, reinterpret_cast(g_rootCert) + }; + X509 *x509RootData = CreateX509CertInner(&rootCertBlob, CM_FORMAT_PEM); + EXPECT_NE(x509RootData, nullptr); + + EVP_PKEY *keyOut = nullptr; + int32_t ret = GetPublicKeyX509Openssl(x509RootData, &keyOut); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(keyOut, nullptr); + + struct CmBlob secondCertBlob = { + strlen(g_secondCert) + 1, reinterpret_cast(g_secondCert) + }; + X509 *x509SecondData = CreateX509CertInner(&secondCertBlob, CM_FORMAT_PEM); + EXPECT_NE(x509SecondData, nullptr); + + ret = VerifyX509Openssl(x509SecondData, keyOut); + EXPECT_EQ(ret, CM_SUCCESS); + DestroyPkeyOpenssl(&keyOut); + DestroyX509Openssl(&x509RootData); + DestroyX509Openssl(&x509SecondData); +} + +/* verify cert with wrong pub key. */ +HWTEST_F(CmX509OpensslTest, Verify003, TestSize.Level0) +{ + struct CmBlob rootCertBlob = { + strlen(g_rootCert) + 1, reinterpret_cast(g_rootCert) + }; + X509 *x509RootData = CreateX509CertInner(&rootCertBlob, CM_FORMAT_PEM); + EXPECT_NE(x509RootData, nullptr); + + EVP_PKEY *keyOut = nullptr; + int32_t ret = GetPublicKeyX509Openssl(x509RootData, &keyOut); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(keyOut, nullptr); + + ret = VerifyX509Openssl(g_x509Data, keyOut); + EXPECT_NE(ret, CM_SUCCESS); + DestroyPkeyOpenssl(&keyOut); + DestroyX509Openssl(&x509RootData); +} + +/* verify cert with invalid input pub key. */ +HWTEST_F(CmX509OpensslTest, Verify004, TestSize.Level0) +{ + int32_t ret = VerifyX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +/* Input valid date. YYMMDDHHMMSSZ */ +HWTEST_F(CmX509OpensslTest, CheckValidityWithDate001, TestSize.Level0) +{ + const char *date = "231018162433Z"; + // validatetime :2022/08/19 - 2032/08/16 + int32_t ret = CheckValidityWithDateX509Openssl(g_x509Data, date); + EXPECT_EQ(ret, CM_SUCCESS); +} + +/* Input valid date. time format: YYYYMMDDHHMMSSZ */ +HWTEST_F(CmX509OpensslTest, CheckValidityWithDate002, TestSize.Level0) +{ + const char *date = "20231018162433Z"; + // validatetime :2022/08/19 - 2032/08/16 + int32_t ret = CheckValidityWithDateX509Openssl(g_x509Data, date); + EXPECT_EQ(ret, CM_SUCCESS); +} + +/* Input invalid date--expiered. */ +HWTEST_F(CmX509OpensslTest, CheckValidityWithDate003, TestSize.Level0) +{ + const char *date = "20991018162433Z"; + // validatetime :2022/08/19 - 2032/08/16 + int32_t ret = CheckValidityWithDateX509Openssl(g_x509Data, date); + EXPECT_EQ(ret, CMR_ERROR_CERT_HAS_EXPIRED); +} + +/* Input invalid date. */ +HWTEST_F(CmX509OpensslTest, CheckValidityWithDate004, TestSize.Level0) +{ + const char *date = "20191018162433Z"; + // validatetime :2022/08/19 - 2032/08/16 + int32_t ret = CheckValidityWithDateX509Openssl(g_x509Data, date); + EXPECT_EQ(ret, CMR_ERROR_CERT_NOT_YET_VALID); +} + +/* Input invalid date form. */ +HWTEST_F(CmX509OpensslTest, CheckValidityWithDate005, TestSize.Level0) +{ + const char *date = "20191018"; + // validatetime :2022/08/19 - 2032/08/16 + int32_t ret = CheckValidityWithDateX509Openssl(g_x509Data, date); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetVersion, TestSize.Level0) +{ + long ver = GetVersionX509Openssl(g_x509Data); + EXPECT_EQ(ver, TEST_CERT_VERSION); +} + +HWTEST_F(CmX509OpensslTest, GetSerialNumber, TestSize.Level0) +{ + long serialNumber = GetSerialNumberX509Openssl(g_x509Data); + EXPECT_EQ(serialNumber, TEST_CERT_SERIAL_NUMBER); +} + +HWTEST_F(CmX509OpensslTest, GetIssuerName001, TestSize.Level0) +{ + struct CmBlob out = { 0, nullptr }; + int32_t ret = GetIssuerDNX509Openssl(g_x509Data, &out); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(out.data, nullptr); + CM_FREE_BLOB(out); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetIssuerName002, TestSize.Level0) +{ + int32_t ret = GetIssuerDNX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetSubjectName001, TestSize.Level0) +{ + struct CmBlob out = { 0, nullptr }; + int32_t ret = GetSubjectDNX509Openssl(g_x509Data, &out); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(out.data, nullptr); + CM_FREE_BLOB(out); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetSubjectName002, TestSize.Level0) +{ + int32_t ret = GetSubjectDNX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetNotBeforeTime001, TestSize.Level0) +{ + struct CmBlob out = { 0, nullptr }; + int32_t ret = GetNotBeforeX509Openssl(g_x509Data, &out); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(out.data, nullptr); + CM_FREE_BLOB(out); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetNotBeforeTime002, TestSize.Level0) +{ + int32_t ret = GetNotBeforeX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetNotAfterTime001, TestSize.Level0) +{ + struct CmBlob out = { 0, nullptr }; + int32_t ret = GetNotAfterX509Openssl(g_x509Data, &out); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(out.data, nullptr); + CM_FREE_BLOB(out); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetNotAfterTime002, TestSize.Level0) +{ + int32_t ret = GetNotAfterX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetSignature001, TestSize.Level0) +{ + struct CmBlob sigOut = { 0, nullptr }; + int32_t ret = GetSignatureX509Openssl(g_x509Data, &sigOut); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(sigOut.data, nullptr); + CM_FREE_BLOB(sigOut); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetSignature002, TestSize.Level0) +{ + int32_t ret = GetSignatureX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetSignatureAlgName001, TestSize.Level0) +{ + struct CmBlob sigAlgName = { 0, nullptr }; + int32_t ret = GetSigAlgNameX509Openssl(g_x509Data, &sigAlgName); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(sigAlgName.data, nullptr); + CM_FREE_BLOB(sigAlgName); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetSignatureAlgName002, TestSize.Level0) +{ + int32_t ret = GetSigAlgNameX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetSignatureAlgOid001, TestSize.Level0) +{ + struct CmBlob sigAlgOid = { 0, nullptr }; + int32_t ret = GetSigAlgOidX509Openssl(g_x509Data, &sigAlgOid); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(sigAlgOid.data, nullptr); + CM_FREE_BLOB(sigAlgOid); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetSignatureAlgOid002, TestSize.Level0) +{ + int32_t ret = GetSigAlgOidX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetSignatureAlgParams001, TestSize.Level0) +{ + struct CmBlob sigAlgParamsOut = { 0, nullptr }; + int32_t ret = GetSigAlgParamsX509Openssl(g_x509Data, &sigAlgParamsOut); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(sigAlgParamsOut.data, nullptr); + CM_FREE_BLOB(sigAlgParamsOut); +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetSignatureAlgParams002, TestSize.Level0) +{ + int32_t ret = GetSigAlgParamsX509Openssl(g_x509Data, nullptr); + EXPECT_NE(ret, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetKeyUsage, TestSize.Level0) +{ + struct CmBlob out = { 0, nullptr }; + int32_t ret = GetKeyUsageX509Openssl(g_x509Data, &out); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(out.data, nullptr); + CM_FREE_BLOB(out); +} + +HWTEST_F(CmX509OpensslTest, GetExtKeyUsage001, TestSize.Level0) +{ + struct CmBlobArray keyUsageOut = { nullptr, 0 }; + int32_t ret = GetExtendedKeyUsageX509Openssl(g_x509Data, &keyUsageOut); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(keyUsageOut.data, nullptr); + CmArrayDataClearAndFree(&keyUsageOut); +} + +/* Cert which has no extended key usage. */ +HWTEST_F(CmX509OpensslTest, GetExtKeyUsage002, TestSize.Level0) +{ + struct CmBlobArray keyUsageOut = { nullptr, 0 }; + struct CmBlob encodeBlob = { + strlen(g_secondCert) + 1, reinterpret_cast(g_secondCert) + }; + X509 *x509Data = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_NE(x509Data, nullptr); + + int32_t ret = GetExtendedKeyUsageX509Openssl(x509Data, &keyUsageOut); + EXPECT_EQ(ret, CMR_ERROR_CRYPTO_OPERATION_FAILED); + EXPECT_EQ(keyUsageOut.data, nullptr); + DestroyX509Openssl(&x509Data); +} + +/* not a CA cert */ +HWTEST_F(CmX509OpensslTest, GetBasicConstraints001, TestSize.Level0) +{ + struct CmBlob encodeBlob = { + strlen(g_deviceTestCert) + 1, reinterpret_cast(g_deviceTestCert) + }; + X509 *x509Data = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_NE(x509Data, nullptr); + + int32_t pathLen = GetBasicConstraintsX509Openssl(x509Data); + EXPECT_EQ(pathLen, CMR_ERROR_CRYPTO_OPERATION_FAILED); /* cert path len is only valid for CA. */ + DestroyX509Openssl(&x509Data); +} + +/* CA cert */ +HWTEST_F(CmX509OpensslTest, GetBasicConstraints002, TestSize.Level0) +{ + int32_t pathLen = GetBasicConstraintsX509Openssl(g_x509Data); + EXPECT_EQ(pathLen, TEST_CERT_CHAIN_LEN); /* g_testSelfSignedCaCert is CA and it's path len is 2. */ +} + +/* invalid input. */ +HWTEST_F(CmX509OpensslTest, GetBasicConstraints003, TestSize.Level0) +{ + int32_t pathLen = GetBasicConstraintsX509Openssl(nullptr); + EXPECT_NE(pathLen, CM_SUCCESS); +} + +HWTEST_F(CmX509OpensslTest, GetSubjectAltNames001, TestSize.Level0) +{ + struct CmBlobArray outName = { nullptr, 0 }; + int32_t ret = GetSubjectAltNamesX509Openssl(g_x509Data, &outName); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(outName.data, nullptr); + CmArrayDataClearAndFree(&outName); +} + +/* cert without subject alternative names. */ +HWTEST_F(CmX509OpensslTest, GetSubjectAltNames002, TestSize.Level0) +{ + struct CmBlob encodeBlob = { + strlen(g_secondCert) + 1, reinterpret_cast(g_secondCert) + }; + X509 *x509Data = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_NE(x509Data, nullptr); + + struct CmBlobArray outName = { nullptr, 0 }; + int32_t ret = GetSubjectAltNamesX509Openssl(x509Data, &outName); + EXPECT_EQ(ret, CMR_ERROR_CRYPTO_OPERATION_FAILED); + EXPECT_EQ(outName.data, nullptr); + DestroyX509Openssl(&x509Data); +} + +HWTEST_F(CmX509OpensslTest, GetIssuerAltNames001, TestSize.Level0) +{ + struct CmBlobArray outName = { nullptr, 0 }; + int32_t ret = GetIssuerAltNamesX509Openssl(g_x509Data, &outName); + EXPECT_EQ(ret, CM_SUCCESS); + EXPECT_NE(outName.data, nullptr); + CmArrayDataClearAndFree(&outName); +} + +/* cert without issuer alternative names. */ +HWTEST_F(CmX509OpensslTest, GetIssuerAltNames002, TestSize.Level0) +{ + struct CmBlob encodeBlob = { + strlen(g_secondCert) + 1, reinterpret_cast(g_secondCert) + }; + X509 *x509Data = CreateX509CertInner(&encodeBlob, CM_FORMAT_PEM); + EXPECT_NE(x509Data, nullptr); + + struct CmBlobArray outName = { nullptr, 0 }; + int32_t ret = GetIssuerAltNamesX509Openssl(x509Data, &outName); + EXPECT_EQ(ret, CMR_ERROR_CRYPTO_OPERATION_FAILED); + EXPECT_EQ(outName.data, nullptr); + DestroyX509Openssl(&x509Data); +} +} +// end of namespace -- Gitee