From 463f569b78ede8f7fe79b4ddf859ca57e615308a Mon Sep 17 00:00:00 2001 From: lcc Date: Fri, 7 Mar 2025 12:25:04 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E7=AE=97=E6=B3=95=E5=BA=93=E6=94=AF?= =?UTF-8?q?=E6=8C=81sm2=E7=AD=BE=E5=90=8D=E6=95=B0=E6=8D=AE=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lcc --- common/src/asy_key_params.c | 11 + .../crypto_operation/sm2_ec_signature_data.c | 73 ++++++ frameworks/frameworks.gni | 7 +- frameworks/js/napi/crypto/BUILD.gn | 1 + .../inc/napi_crypto_framework_defines.h | 3 + .../napi/crypto/inc/napi_sm2_ec_signature.h | 40 ++++ frameworks/js/napi/crypto/src/napi_init.cpp | 2 + .../napi/crypto/src/napi_sm2_ec_signature.cpp | 217 ++++++++++++++++++ .../algorithm_parameter/sm2_crypto_params.h | 6 + .../crypto_operation/sm2_ec_signature_data.h | 51 ++++ .../common/inc/openssl_adapter.h | 11 + .../common/src/openssl_adapter.c | 35 +++ .../inc/cipher_sm2_ecdsa_signature_openssl.h | 32 +++ .../src/cipher_sm2_ecdsa_signature_openssl.c | 128 +++++++++++ plugin/plugin.gni | 1 + test/unittest/BUILD.gn | 1 + .../sm2/crypto_sm2_ecdsa_signature_test.cpp | 130 +++++++++++ 17 files changed, 747 insertions(+), 2 deletions(-) create mode 100644 frameworks/crypto_operation/sm2_ec_signature_data.c create mode 100644 frameworks/js/napi/crypto/inc/napi_sm2_ec_signature.h create mode 100644 frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp create mode 100644 interfaces/inner_api/crypto_operation/sm2_ec_signature_data.h create mode 100644 plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_ecdsa_signature_openssl.h create mode 100644 plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c create mode 100644 test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp diff --git a/common/src/asy_key_params.c b/common/src/asy_key_params.c index 61b178d..a525620 100644 --- a/common/src/asy_key_params.c +++ b/common/src/asy_key_params.c @@ -482,3 +482,14 @@ void DestroySm2CipherTextSpec(Sm2CipherTextSpec *spec) HcfFree(spec); } +void DestroySm2EcSignatureSpec(Sm2EcSignatureDataSpec *spec) +{ + if (spec == NULL) { + return; + } + HcfFree(spec->rCoordinate.data); + spec->rCoordinate.data = NULL; + HcfFree(spec->sCoordinate.data); + spec->sCoordinate.data = NULL; + HcfFree(spec); +} diff --git a/frameworks/crypto_operation/sm2_ec_signature_data.c b/frameworks/crypto_operation/sm2_ec_signature_data.c new file mode 100644 index 0000000..deecb09 --- /dev/null +++ b/frameworks/crypto_operation/sm2_ec_signature_data.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2025 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 "sm2_ec_signature_data.h" +#include +#include "cipher_sm2_ecdsa_signature_openssl.h" +#include "log.h" +#include "memory.h" +#include "utils.h" + +static bool CheckSm2EcSignatureDataSpec(Sm2EcSignatureDataSpec *spec) +{ + if (spec == NULL) { + LOGE("Spec is null"); + return false; + } + if ((spec->rCoordinate.data == NULL) || (spec->rCoordinate.len == 0)) { + LOGE("Spec.xCoordinate is null"); + return false; + } + if ((spec->sCoordinate.data == NULL) || (spec->sCoordinate.len == 0)) { + LOGE("Spec.yCoordinate is null"); + return false; + } + return true; +} + +HcfResult HcfGenEcSignatureDataBySpec(Sm2EcSignatureDataSpec *spec, HcfBlob *output) +{ + if (output == NULL) { + LOGE("Invalid param output!"); + return HCF_INVALID_PARAMS; + } + if (!CheckSm2EcSignatureDataSpec(spec)) { + LOGE("Invalid param spec!"); + return HCF_INVALID_PARAMS; + } + HcfResult res = HcfSm2SpecToDerData(spec, output); + if (res != HCF_SUCCESS) { + LOGE("Failed to convert construct to asn1!"); + } + return res; +} + +HcfResult HcfGenEcSignatureSpecByData(HcfBlob *input, Sm2EcSignatureDataSpec **returnSpc) +{ + if (input == NULL) { + LOGE("Invalid param input!"); + return HCF_INVALID_PARAMS; + } + if (returnSpc == NULL) { + LOGE("Invalid param returnSpc!"); + return HCF_INVALID_PARAMS; + } + HcfResult res = HcfDerDataToSm2Spec(input, returnSpc); + if (res != HCF_SUCCESS) { + LOGE("Failed to convert asn1 to construct!"); + return res; + } + return HCF_SUCCESS; +} \ No newline at end of file diff --git a/frameworks/frameworks.gni b/frameworks/frameworks.gni index e5b4de1..8a87bdc 100644 --- a/frameworks/frameworks.gni +++ b/frameworks/frameworks.gni @@ -57,8 +57,11 @@ framework_md_files = [ "${framework_path}/crypto_operation/md.c" ] framework_kdf_files = [ "${framework_path}/crypto_operation/kdf.c" ] -framework_sm2_crypto_util_files = - [ "${framework_path}/crypto_operation/sm2_crypto_util.c" ] +framework_sm2_crypto_util_files = [ + "${framework_path}/crypto_operation/sm2_crypto_util.c", + "${framework_path}/crypto_operation/sm2_ec_signature_data.c" + + ] framework_files = framework_key_agreement_files + framework_signature_files + diff --git a/frameworks/js/napi/crypto/BUILD.gn b/frameworks/js/napi/crypto/BUILD.gn index 33d96ee..629594b 100644 --- a/frameworks/js/napi/crypto/BUILD.gn +++ b/frameworks/js/napi/crypto/BUILD.gn @@ -55,6 +55,7 @@ ohos_shared_library("cryptoframework_napi") { "src/napi_rand.cpp", "src/napi_sign.cpp", "src/napi_sm2_crypto_util.cpp", + "src/napi_sm2_ec_signature.cpp", "src/napi_sym_key.cpp", "src/napi_sym_key_generator.cpp", "src/napi_utils.cpp", diff --git a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h index 5874584..c94bc34 100644 --- a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h +++ b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h @@ -93,6 +93,9 @@ const std::string SM2_UTIL_PARAM_Y_COORDINATE = "yCoordinate"; const std::string SM2_UTIL_PARAM_CIPHER_TEXT_DATA = "cipherTextData"; const std::string SM2_UTIL_PARAM_HASH_DATA = "hashData"; +const std::string SM2_EC_SIGNATURE_PARAM_R = "r"; +const std::string SM2_EC_SIGNATURE_PARAM_S = "s"; + const std::string KDF_PARAMS_SALT = "salt"; const std::string KDF_PARAMS_KEY_SIZE = "keySize"; diff --git a/frameworks/js/napi/crypto/inc/napi_sm2_ec_signature.h b/frameworks/js/napi/crypto/inc/napi_sm2_ec_signature.h new file mode 100644 index 0000000..3bd45ef --- /dev/null +++ b/frameworks/js/napi/crypto/inc/napi_sm2_ec_signature.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2025 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. + */ + +#ifndef HCF_NAPI_SM2_EC_SIGNATURE_H +#define HCF_NAPI_SM2_EC_SIGNATURE_H + +#include + +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "sm2_ec_signature_data.h" + +namespace OHOS { +namespace CryptoFramework { +class NapiSm2EcSignature { +public: + explicit NapiSm2EcSignature(); + ~NapiSm2EcSignature(); + + static napi_value JsGenEcSignatureDataSpec(napi_env env, napi_callback_info info); + static napi_value JsGenEcSignatureData(napi_env env, napi_callback_info info); + static napi_value SignatureUtilsConstructor(napi_env env, napi_callback_info info); + static napi_value SignatureUtilsConstructorClass(napi_env env); + static void DefineNapiSm2EcSignatureJSClass(napi_env env, napi_value exports); +}; +} // namespace CryptoFramework +} // namespace OHOS +#endif diff --git a/frameworks/js/napi/crypto/src/napi_init.cpp b/frameworks/js/napi/crypto/src/napi_init.cpp index b36f0d3..5d9c3cd 100644 --- a/frameworks/js/napi/crypto/src/napi_init.cpp +++ b/frameworks/js/napi/crypto/src/napi_init.cpp @@ -37,6 +37,7 @@ #include "napi_key.h" #include "napi_utils.h" #include "napi_crypto_framework_defines.h" +#include "napi_sm2_ec_signature.h" #include "key.h" #include "asy_key_params.h" @@ -233,6 +234,7 @@ static napi_value ModuleExport(napi_env env, napi_value exports) NapiECCKeyUtil::DefineNapiECCKeyUtilJSClass(env, exports); NapiDHKeyUtil::DefineNapiDHKeyUtilJSClass(env, exports); NapiSm2CryptoUtil::DefineNapiSm2CryptoUtilJSClass(env, exports); + NapiSm2EcSignature::DefineNapiSm2EcSignatureJSClass(env, exports); LOGD("module init end."); return exports; } diff --git a/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp b/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp new file mode 100644 index 0000000..ca9927f --- /dev/null +++ b/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2025 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 "napi_sm2_ec_signature.h" + +#include +#include "securec.h" +#include "log.h" +#include "memory.h" +#include "napi_crypto_framework_defines.h" +#include "napi_utils.h" + +namespace OHOS { +namespace CryptoFramework { +NapiSm2EcSignature::NapiSm2EcSignature() {} +NapiSm2EcSignature::~NapiSm2EcSignature() {} + +static bool GetSm2EcSignatureDataSpecFromNapiValue(napi_env env, napi_value arg, Sm2EcSignatureDataSpec **returnSpec) +{ + if ((env == nullptr) || (arg == nullptr) || (returnSpec == nullptr)) { + LOGE("Invalid params."); + return false; + } + Sm2EcSignatureDataSpec *tempSpec = + static_cast(HcfMalloc(sizeof(Sm2EcSignatureDataSpec), 0)); + if (tempSpec == nullptr) { + LOGE("Malloc failed!"); + return false; + } + napi_value rCoordinate = GetDetailAsyKeySpecValue(env, arg, SM2_EC_SIGNATURE_PARAM_R); + napi_value sCoordinate = GetDetailAsyKeySpecValue(env, arg, SM2_EC_SIGNATURE_PARAM_S); + if ((rCoordinate == nullptr) || (sCoordinate == nullptr)) { + LOGE("Invalid params!"); + DestroySm2EcSignatureSpec(tempSpec); + return false; + } + bool ret = GetBigIntFromNapiValue(env, rCoordinate, &tempSpec->rCoordinate); + if (!ret) { + LOGE("Failed to get valid r coordinate."); + DestroySm2EcSignatureSpec(tempSpec); + return false; + } + ret = GetBigIntFromNapiValue(env, sCoordinate, &tempSpec->sCoordinate); + if (!ret) { + LOGE("Failed to get valid s coordinate."); + DestroySm2EcSignatureSpec(tempSpec); + return false; + } + *returnSpec = tempSpec; + return true; +} + +napi_value NapiSm2EcSignature::JsGenEcSignatureData(napi_env env, napi_callback_info info) +{ + size_t expectedArgc = PARAMS_NUM_ONE; + size_t argc = ARGS_SIZE_ONE; + napi_value argv[ARGS_SIZE_ONE] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != expectedArgc) { + LOGE("The input args num is invalid."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid.")); + return nullptr; + } + Sm2EcSignatureDataSpec *spec = nullptr; + if (!GetSm2EcSignatureDataSpecFromNapiValue(env, argv[0], &spec)) { + LOGE("Failed to get spec."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get spec.")); + return nullptr; + } + HcfBlob *output = static_cast(HcfMalloc(sizeof(HcfBlob), 0)); + if (output == NULL) { + LOGE("Failed to allocate HcfBlob memory!"); + DestroySm2EcSignatureSpec(spec); + napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "Failed to allocate memory.")); + return nullptr; + } + HcfResult res = HcfGenEcSignatureDataBySpec(spec, output); + if (res != HCF_SUCCESS) { + LOGE("Gen cipher text by spec fail."); + HcfFree(output); + DestroySm2EcSignatureSpec(spec); + napi_throw(env, GenerateBusinessError(env, res, "gen cipher text by spec fail.")); + return nullptr; + } + napi_value instance = ConvertObjectBlobToNapiValue(env, output); + HcfBlobDataFree(output); + HcfFree(output); + DestroySm2EcSignatureSpec(spec); + return instance; +} + +static bool CheckSm2CipherTextSpec(Sm2EcSignatureDataSpec *spec) +{ + if (spec == nullptr) { + LOGE("Invalid spec!"); + return false; + } + if (spec->rCoordinate.data == nullptr || spec->rCoordinate.len == 0) { + LOGE("Invalid rCoordinate!"); + return false; + } + if (spec->sCoordinate.data == nullptr || spec->sCoordinate.len == 0) { + LOGE("Invalid sCoordinate!"); + return false; + } + return true; +} + +static bool BuildSm2CipherTextSpecToNapiValue(napi_env env, Sm2EcSignatureDataSpec *spec, napi_value *instance) +{ + if (!BuildSetNamedProperty(env, &(spec->rCoordinate), SM2_EC_SIGNATURE_PARAM_R.c_str(), instance)) { + LOGE("Build rCoordinate failed!"); + return false; + } + if (!BuildSetNamedProperty(env, &(spec->sCoordinate), SM2_EC_SIGNATURE_PARAM_S.c_str(), instance)) { + LOGE("Build sCoordinate failed!"); + return false; + } + return true; +} + +static napi_value ConvertSm2CipherTextSpecToNapiValue(napi_env env, Sm2EcSignatureDataSpec *spec) +{ + if (!CheckSm2CipherTextSpec(spec)) { + LOGE("Invalid spec!"); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Invalid spec!")); + return NapiGetNull(env); + } + napi_value instance; + napi_status status = napi_create_object(env, &instance); + if (status != napi_ok) { + LOGE("Create object failed!"); + napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create object failed!")); + return NapiGetNull(env); + } + if (!BuildSm2CipherTextSpecToNapiValue(env, spec, &instance)) { + LOGE("Build object failed!"); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build object failed!")); + return NapiGetNull(env); + } + return instance; +} + +napi_value NapiSm2EcSignature::JsGenEcSignatureDataSpec(napi_env env, napi_callback_info info) +{ + size_t expectedArgc = PARAMS_NUM_ONE; + size_t argc = ARGS_SIZE_ONE; + napi_value argv[ARGS_SIZE_ONE] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != expectedArgc) { + LOGE("The input args num is invalid."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid.")); + return nullptr; + } + HcfBlob *cipherText = GetBlobFromNapiUint8Arr(env, argv[0]); + if (cipherText == nullptr) { + LOGE("Failed to get cipherText."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get cipherText.")); + return nullptr; + } + Sm2EcSignatureDataSpec *returnSpec = nullptr; + HcfResult res = HcfGenEcSignatureSpecByData(cipherText, &returnSpec); + if (res != HCF_SUCCESS) { + LOGE("Get cipher text spec fail."); + HcfBlobDataFree(cipherText); + HcfFree(cipherText); + napi_throw(env, GenerateBusinessError(env, res, "get cipher text spec fail.")); + return nullptr; + } + napi_value instance = ConvertSm2CipherTextSpecToNapiValue(env, returnSpec); + DestroySm2EcSignatureSpec(returnSpec); + HcfBlobDataFree(cipherText); + HcfFree(cipherText); + return instance; +} + +napi_value NapiSm2EcSignature::SignatureUtilsConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t argc = ARGS_SIZE_ONE; + napi_value argv[ARGS_SIZE_ONE] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + return thisVar; +} + +napi_value NapiSm2EcSignature::SignatureUtilsConstructorClass(napi_env env) +{ + napi_value cons = nullptr; + napi_property_descriptor clzDes[] = { + DECLARE_NAPI_STATIC_FUNCTION("genEccSignature", NapiSm2EcSignature::JsGenEcSignatureData), + DECLARE_NAPI_STATIC_FUNCTION("genEccSignatureSpec", NapiSm2EcSignature::JsGenEcSignatureDataSpec), + }; + NAPI_CALL(env, napi_define_class(env, "SignatureUtils", NAPI_AUTO_LENGTH, + NapiSm2EcSignature::SignatureUtilsConstructor, + nullptr, sizeof(clzDes) / sizeof(clzDes[0]), clzDes, &cons)); + return cons; +} + +void NapiSm2EcSignature::DefineNapiSm2EcSignatureJSClass(napi_env env, napi_value exports) +{ + napi_set_named_property(env, exports, "SignatureUtils", NapiSm2EcSignature::SignatureUtilsConstructorClass(env)); +} +} // CryptoFramework +} // OHOS + \ No newline at end of file diff --git a/interfaces/inner_api/algorithm_parameter/sm2_crypto_params.h b/interfaces/inner_api/algorithm_parameter/sm2_crypto_params.h index 92db7f4..3a02cc6 100644 --- a/interfaces/inner_api/algorithm_parameter/sm2_crypto_params.h +++ b/interfaces/inner_api/algorithm_parameter/sm2_crypto_params.h @@ -26,11 +26,17 @@ typedef struct Sm2CipherTextSpec { HcfBlob hashData; } Sm2CipherTextSpec; +typedef struct Sm2EcSignatureDataSpec { + HcfBigInteger rCoordinate; + HcfBigInteger sCoordinate; +} Sm2EcSignatureDataSpec; + #ifdef __cplusplus extern "C" { #endif void DestroySm2CipherTextSpec(Sm2CipherTextSpec *spec); +void DestroySm2EcSignatureSpec(Sm2EcSignatureDataSpec *spec); #ifdef __cplusplus } diff --git a/interfaces/inner_api/crypto_operation/sm2_ec_signature_data.h b/interfaces/inner_api/crypto_operation/sm2_ec_signature_data.h new file mode 100644 index 0000000..d1b4c6b --- /dev/null +++ b/interfaces/inner_api/crypto_operation/sm2_ec_signature_data.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2025 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. + */ + +#ifndef HCF_SM2_CRYPTO_UTIL_H +#define HCF_SM2_CRYPTO_UTIL_H + +#include "result.h" +#include "sm2_crypto_params.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Generate the SM2 ciphertext in ASN.1 format according to the specific data. + * + * @param spec - indicates the EC signature data spec.. + * @param output - indicates the signature data in DER format. + * @return Returns the status code of the execution. + * @since 20 + * @version 1.0 + */ +HcfResult HcfGenEcSignatureDataBySpec(Sm2EcSignatureDataSpec *spec, HcfBlob *output); +/** + * @brief Get the specific data from the SM2 ciphertext in ASN.1 format. + * + * @param input - indicates the signature data in DER format. + * @param returnSpc - indicates the EC signature data spec.. + * @return Returns the status code of the execution. + * @since 20 + * @version 1.0 + */ +HcfResult HcfGenEcSignatureSpecByData(HcfBlob *input, Sm2EcSignatureDataSpec **returnSpc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugin/openssl_plugin/common/inc/openssl_adapter.h b/plugin/openssl_plugin/common/inc/openssl_adapter.h index 1affe17..9134fd4 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -365,6 +366,16 @@ struct Sm2CipherTextSt { ASN1_OCTET_STRING *c2; }; +typedef struct ECDSA_SIG_st ECDSA_SIG; + +ECDSA_SIG *OpensslEcdsaSigNew(); +ECDSA_SIG *OpensslD2iSm2EcdsaSig(const unsigned char **inputData, int dataLen); +int OpensslI2dSm2EcdsaSig(ECDSA_SIG *sm2Text, unsigned char **returnData); +void OpensslSm2EcdsaSigFree(ECDSA_SIG *sm2Text); +const BIGNUM *OpensslEcdsaSigGet0r(const ECDSA_SIG *sig); +const BIGNUM *OpensslEcdsaSigGet0s(const ECDSA_SIG *sig); +int OpensslEcdsaSigSet0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); + void OpensslSm2CipherTextFree(struct Sm2CipherTextSt *sm2Text); struct Sm2CipherTextSt *OpensslD2iSm2CipherText(const uint8_t *ciphertext, size_t cipherTextLen); void OpensslAsn1OctetStringFree(ASN1_OCTET_STRING *field); diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index 81c0851..98c3b3b 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -1408,6 +1408,41 @@ const unsigned char *OpensslAsn1StringGet0Data(ASN1_OCTET_STRING *p) return ASN1_STRING_get0_data(p); } +ECDSA_SIG *OpensslEcdsaSigNew() +{ + return ECDSA_SIG_new(); +} + +ECDSA_SIG *OpensslD2iSm2EcdsaSig(const unsigned char **inputData, int dataLen) +{ + return d2i_ECDSA_SIG(NULL, inputData, dataLen); +} + +int OpensslI2dSm2EcdsaSig(ECDSA_SIG *sm2Text, unsigned char **returnData) +{ + return i2d_ECDSA_SIG(sm2Text, returnData); +} + +void OpensslSm2EcdsaSigFree(ECDSA_SIG *sm2Text) +{ + return ECDSA_SIG_free(sm2Text); +} + +const BIGNUM *OpensslEcdsaSigGet0r(const ECDSA_SIG *sig) +{ + return ECDSA_SIG_get0_r(sig); +} + +const BIGNUM *OpensslEcdsaSigGet0s(const ECDSA_SIG *sig) +{ + return ECDSA_SIG_get0_s(sig); +} + +int OpensslEcdsaSigSet0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + return ECDSA_SIG_set0(sig, r, s); +} + OSSL_PARAM_BLD *OpensslOsslParamBldNew(void) { return OSSL_PARAM_BLD_new(); diff --git a/plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_ecdsa_signature_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_ecdsa_signature_openssl.h new file mode 100644 index 0000000..a75cd17 --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_ecdsa_signature_openssl.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2025 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. + */ + +#ifndef HCF_CIPHER_SM2_ECDSA_SIGNATURE_OPENSSL_H +#define HCF_CIPHER_SM2_ECDSA_SIGNATURE_OPENSSL_H + +#include "sm2_crypto_params.h" +#include "result.h" + +#ifdef __cplusplus +extern "C" { +#endif + +HcfResult HcfSm2SpecToDerData(Sm2EcSignatureDataSpec *spec, HcfBlob *output); +HcfResult HcfDerDataToSm2Spec(HcfBlob *input, Sm2EcSignatureDataSpec **returnSpec); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c new file mode 100644 index 0000000..d9ae81e --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2025 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 "cipher_sm2_ecdsa_signature_openssl.h" +#include +#include +#include "log.h" +#include "memory.h" +#include "openssl_adapter.h" +#include "openssl_common.h" +#include "securec.h" +#include "utils.h" + +static HcfResult BuildSm2Ciphertext(const Sm2EcSignatureDataSpec *spec, ECDSA_SIG *sm2Text) +{ + if (spec == NULL || sm2Text == NULL) { + LOGE("Invalid params"); + return HCF_INVALID_PARAMS; + } + BIGNUM *r = NULL; + BIGNUM *s = NULL; + if (BigIntegerToBigNum(&(spec->rCoordinate), &r) != HCF_SUCCESS) { + LOGE("Build r failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + if (BigIntegerToBigNum(&(spec->sCoordinate), &s) != HCF_SUCCESS) { + LOGE("Build s failed."); + OpensslBnFree(r); + return HCF_ERR_CRYPTO_OPERATION; + } + if (OpensslEcdsaSigSet0(sm2Text, r, s) != HCF_OPENSSL_SUCCESS) { + LOGE("Set SM2 ECDSA signature failed."); + OpensslBnFree(r); + OpensslBnFree(s); + return HCF_ERR_CRYPTO_OPERATION; + } + return HCF_SUCCESS; +} + +HcfResult HcfSm2SpecToDerData(Sm2EcSignatureDataSpec *spec, HcfBlob *output) +{ + if (spec == NULL || output == NULL) { + LOGE("Invalid params"); + return HCF_INVALID_PARAMS; + } + ECDSA_SIG *sig = OpensslEcdsaSigNew(); + HcfResult res = BuildSm2Ciphertext(spec, sig); + if (res != HCF_SUCCESS) { + OpensslSm2EcdsaSigFree(sig); + LOGE("SM2 build SM2Ciphertext fail"); + return res; + } + unsigned char *returnData = NULL; + int returnDataLen = OpensslI2dSm2EcdsaSig(sig, &returnData); + OpensslSm2EcdsaSigFree(sig); + if (returnData == NULL || returnDataLen < 0) { + LOGE("SM2 openssl [i2d_SM2_Ciphertext] error"); + HcfPrintOpensslError(); + return HCF_ERR_CRYPTO_OPERATION; + } + output->data = returnData; + output->len = (size_t)returnDataLen; + return HCF_SUCCESS; +} + +static HcfResult BuildSm2EcdsaSigSpec(ECDSA_SIG *sig, Sm2EcSignatureDataSpec *tempSpec) +{ + const BIGNUM *r = OpensslEcdsaSigGet0r(sig); + const BIGNUM *s = OpensslEcdsaSigGet0s(sig); + if (r == NULL || s == NULL) { + LOGE("get r or s failed"); + return HCF_ERR_CRYPTO_OPERATION; + } + if (BigNumToBigInteger(r, &(tempSpec->rCoordinate)) != HCF_SUCCESS) { + LOGE("BigNumToBigInteger rCoordinate failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + if (BigNumToBigInteger(s, &(tempSpec->sCoordinate)) != HCF_SUCCESS) { + LOGE("BigNumToBigInteger sCoordinate failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + return HCF_SUCCESS; +} + +HcfResult HcfDerDataToSm2Spec(HcfBlob *input, Sm2EcSignatureDataSpec **returnSpec) +{ + if (input == NULL || returnSpec == NULL) { + LOGE("Invalid signature params"); + return HCF_INVALID_PARAMS; + } + + Sm2EcSignatureDataSpec *tempSpec = (Sm2EcSignatureDataSpec *)(HcfMalloc(sizeof(Sm2EcSignatureDataSpec), 0)); + if (tempSpec == NULL) { + LOGE("Failed to allocate Sm2EcSignatureDataSpec memory"); + return HCF_ERR_MALLOC; + } + const unsigned char *data = (const unsigned char *)input->data; + ECDSA_SIG *sig = OpensslD2iSm2EcdsaSig(&data, (int)input->len); + if (sig == NULL) { + LOGE("SM2 build SM2Ciphertext fail"); + DestroySm2EcSignatureSpec(tempSpec); + OpensslSm2EcdsaSigFree(sig); + return HCF_ERR_CRYPTO_OPERATION; + } + HcfResult res = BuildSm2EcdsaSigSpec(sig, tempSpec); + if (res != HCF_SUCCESS) { + LOGE("SM2 build SM2ECDSA sig spec fail"); + DestroySm2EcSignatureSpec(tempSpec); + OpensslSm2EcdsaSigFree(sig); + return res; + } + + *returnSpec = tempSpec; + OpensslSm2EcdsaSigFree(sig); + return HCF_SUCCESS; +} \ No newline at end of file diff --git a/plugin/plugin.gni b/plugin/plugin.gni index 9785bad..b95ff88 100644 --- a/plugin/plugin.gni +++ b/plugin/plugin.gni @@ -76,6 +76,7 @@ plugin_cipher_files = [ "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_crypto_util_openssl.c", + "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c", ] plugin_hmac_files = diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 2275276..3999e0b 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -127,6 +127,7 @@ ohos_unittest("crypto_framework_test") { "src/sm2/crypto_sm2_asy_key_generator_by_spec_sub_test.cpp", "src/sm2/crypto_sm2_asy_key_generator_by_spec_test.cpp", "src/sm2/crypto_sm2_util_test.cpp", + "src/sm2/crypto_sm2_ecdsa_signature_test.cpp" ] sources += framework_files + plugin_files diff --git a/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp b/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp new file mode 100644 index 0000000..85b6acd --- /dev/null +++ b/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2025 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 "securec.h" +#include "blob.h" +#include "cipher_sm2_ecdsa_signature_openssl.h" +#include "sm2_crypto_util.h" +#include "sm2_crypto_params.h" +#include "log.h" +#include "memory.h" +#include "cstring" + +using namespace std; +using namespace testing::ext; + +namespace { +class CryptoSm2EcdsaSignature : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void CryptoSm2EcdsaSignature::SetUp() {} +void CryptoSm2EcdsaSignature::TearDown() {} +void CryptoSm2EcdsaSignature::SetUpTestCase() {} +void CryptoSm2EcdsaSignature::TearDownTestCase() {} + +static unsigned char g_rCoordinate[] = { + 107, 93, 198, 247, 119, 18, 40, 110, 90, 156, 193, 158, 205, 113, 170, 128, 146, 109, 75, 17, 181, 109, 110, + 91, 149, 5, 110, 233, 209, 78, 229, 96 +}; + +static unsigned char g_sCoordinate[] = { + 45, 153, 88, 82, 104, 221, 226, 43, 174, 21, 122, 248, 5, 232, 105, 41, 92, 95, 102, 224, 216, 149, 85, 236, + 110, 6, 64, 188, 149, 70, 70, 183 +}; + +HcfResult ConstructCorrectSm2Spec(Sm2EcSignatureDataSpec **spec) +{ + Sm2EcSignatureDataSpec *tempSpec = + static_cast(HcfMalloc(sizeof(Sm2EcSignatureDataSpec), 0)); + if (tempSpec == nullptr) { + return HCF_ERR_MALLOC; + } + tempSpec->rCoordinate.data = g_rCoordinate; + tempSpec->rCoordinate.len = sizeof(g_sCoordinate); + tempSpec->sCoordinate.data = g_sCoordinate; + tempSpec->sCoordinate.len = sizeof(g_sCoordinate); + *spec = tempSpec; + return HCF_SUCCESS; +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfSm2SpecToDerDataAndBack, TestSize.Level0) +{ + Sm2EcSignatureDataSpec *spec = nullptr; + ASSERT_EQ(ConstructCorrectSm2Spec(&spec), HCF_SUCCESS); + + // Convert SM2 spec to DER data + HcfBlob derOutput = { .data = nullptr, .len = 0 }; + EXPECT_EQ(HcfSm2SpecToDerData(spec, &derOutput), HCF_SUCCESS); + EXPECT_NE(derOutput.data, nullptr); + EXPECT_GT(derOutput.len, 0); + + // Convert DER data back to SM2 spec + Sm2EcSignatureDataSpec *returnSpec = nullptr; + EXPECT_EQ(HcfDerDataToSm2Spec(&derOutput, &returnSpec), HCF_SUCCESS); + EXPECT_NE(returnSpec, nullptr); + + // Validate the converted spec matches the original + EXPECT_EQ(returnSpec->rCoordinate.len, spec->rCoordinate.len); + EXPECT_EQ(memcmp(returnSpec->rCoordinate.data, spec->rCoordinate.data, spec->rCoordinate.len), 0); + EXPECT_EQ(returnSpec->sCoordinate.len, spec->sCoordinate.len); + EXPECT_EQ(memcmp(returnSpec->sCoordinate.data, spec->sCoordinate.data, spec->sCoordinate.len), 0); + + // Free allocated resources + HcfBlobDataFree(&derOutput); + DestroySm2EcSignatureSpec(returnSpec); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfSm2SpecToDerData_NullInput, TestSize.Level0) +{ + HcfBlob derOutput = { .data = nullptr, .len = 0 }; + EXPECT_EQ(HcfSm2SpecToDerData(nullptr, &derOutput), HCF_INVALID_PARAMS); +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfSm2SpecToDerData_NullOutput, TestSize.Level0) +{ + Sm2EcSignatureDataSpec *spec = nullptr; + ASSERT_EQ(ConstructCorrectSm2Spec(&spec), HCF_SUCCESS); + EXPECT_EQ(HcfSm2SpecToDerData(spec, nullptr), HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_NullInput, TestSize.Level0) +{ + Sm2EcSignatureDataSpec *returnSpec = nullptr; + EXPECT_EQ(HcfDerDataToSm2Spec(nullptr, &returnSpec), HCF_INVALID_PARAMS); +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_NullOutput, TestSize.Level0) +{ + HcfBlob derInput = { .data = g_rCoordinate, .len = sizeof(g_rCoordinate) }; + EXPECT_EQ(HcfDerDataToSm2Spec(&derInput, nullptr), HCF_INVALID_PARAMS); +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_InvalidData, TestSize.Level0) +{ + unsigned char invalidData[] = { 0x00, 0x01, 0x02, 0x03 }; + HcfBlob derInput = { .data = invalidData, .len = sizeof(invalidData) }; + Sm2EcSignatureDataSpec *returnSpec = nullptr; + EXPECT_EQ(HcfDerDataToSm2Spec(&derInput, &returnSpec), HCF_ERR_CRYPTO_OPERATION); +} + +} \ No newline at end of file -- Gitee From c1eb79531289745dc6a479b6fb4842b3aa114291 Mon Sep 17 00:00:00 2001 From: lcc Date: Thu, 20 Mar 2025 11:31:43 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0DES=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lcc --- common/inc/params_parser.h | 3 + common/src/params_parser.c | 2 + frameworks/crypto_operation/cipher.c | 10 +- frameworks/key/sym_key_generator.c | 10 +- .../common/inc/openssl_adapter.h | 6 + .../common/src/openssl_adapter.c | 30 +++ .../crypto_operation/cipher/inc/aes_openssl.h | 2 - .../crypto_operation/cipher/inc/des_openssl.h | 31 +++ ...er_3des_openssl.c => cipher_des_openssl.c} | 128 ++++++++++- .../sym_key_generator/src/sym_key_openssl.c | 5 +- plugin/plugin.gni | 2 +- test/unittest/src/crypto_3des_cipher_test.cpp | 206 +++++++++++++++++- 12 files changed, 404 insertions(+), 31 deletions(-) create mode 100644 plugin/openssl_plugin/crypto_operation/cipher/inc/des_openssl.h rename plugin/openssl_plugin/crypto_operation/cipher/src/{cipher_3des_openssl.c => cipher_des_openssl.c} (72%) diff --git a/common/inc/params_parser.h b/common/inc/params_parser.h index a5a434a..d51625a 100644 --- a/common/inc/params_parser.h +++ b/common/inc/params_parser.h @@ -35,6 +35,7 @@ typedef enum { typedef enum { HCF_ALG_AES = 1, HCF_ALG_DES, + HCF_ALG_3DES, HCF_ALG_RSA, HCF_ALG_ECC, HCF_ALG_DSA, @@ -60,6 +61,7 @@ typedef enum { HCF_ALG_AES_192, HCF_ALG_AES_256, HCF_ALG_SM4_128, + HCF_ALG_DES_64, HCF_ALG_3DES_192, HCF_ALG_MODE_NONE, @@ -124,6 +126,7 @@ typedef enum { HCF_ALG_SM2_DEFAULT, HCF_ALG_AES_DEFAULT, HCF_ALG_SM4_DEFAULT, + HCF_ALG_DES_DEFAULT, HCF_ALG_3DES_DEFAULT, HCF_ALG_HMAC_DEFAULT, HCF_ALG_ECC_BRAINPOOL_DEFAULT, diff --git a/common/src/params_parser.c b/common/src/params_parser.c index b76bd15..07da926 100644 --- a/common/src/params_parser.c +++ b/common/src/params_parser.c @@ -32,6 +32,7 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"AES256", HCF_ALG_KEY_TYPE, HCF_ALG_AES_256}, {"SM4_128", HCF_ALG_KEY_TYPE, HCF_ALG_SM4_128}, {"3DES192", HCF_ALG_KEY_TYPE, HCF_ALG_3DES_192}, + {"DES64", HCF_ALG_KEY_TYPE, HCF_ALG_DES_64}, {"ECB", HCF_ALG_MODE, HCF_ALG_MODE_ECB}, {"CBC", HCF_ALG_MODE, HCF_ALG_MODE_CBC}, @@ -107,6 +108,7 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"SM2", HCF_ALG_TYPE, HCF_ALG_SM2_DEFAULT}, {"AES", HCF_ALG_TYPE, HCF_ALG_AES_DEFAULT}, {"SM4", HCF_ALG_TYPE, HCF_ALG_SM4_DEFAULT}, + {"DES", HCF_ALG_TYPE, HCF_ALG_DES_DEFAULT}, {"3DES", HCF_ALG_TYPE, HCF_ALG_3DES_DEFAULT}, {"HMAC", HCF_ALG_TYPE, HCF_ALG_HMAC_DEFAULT}, {"PBKDF2", HCF_ALG_TYPE, HCF_ALG_PBKDF2_DEFAULT}, diff --git a/frameworks/crypto_operation/cipher.c b/frameworks/crypto_operation/cipher.c index f73c844..e524bbe 100644 --- a/frameworks/crypto_operation/cipher.c +++ b/frameworks/crypto_operation/cipher.c @@ -15,6 +15,7 @@ #include "cipher.h" #include "aes_openssl.h" +#include "des_openssl.h" #include "config.h" #include "securec.h" #include "result.h" @@ -47,6 +48,7 @@ static const HcfCipherGenAbility CIPHER_ABILITY_SET[] = { { HCF_ALG_RSA, { HcfCipherRsaCipherSpiCreate } }, { HCF_ALG_SM2, { HcfCipherSm2CipherSpiCreate } }, { HCF_ALG_AES, { HcfCipherAesGeneratorSpiCreate } }, + { HCF_ALG_3DES, { HcfCipherDesGeneratorSpiCreate } }, { HCF_ALG_DES, { HcfCipherDesGeneratorSpiCreate } }, { HCF_ALG_SM4, { HcfCipherSm4GeneratorSpiCreate } } }; @@ -64,9 +66,12 @@ static void SetKeyType(HcfAlgParaValue value, void *cipher) case HCF_ALG_SM4_DEFAULT: cipherAttr->algo = HCF_ALG_SM4; break; - case HCF_ALG_3DES_DEFAULT: + case HCF_ALG_DES_DEFAULT: cipherAttr->algo = HCF_ALG_DES; break; + case HCF_ALG_3DES_DEFAULT: + cipherAttr->algo = HCF_ALG_3DES; + break; case HCF_ALG_RSA_DEFAULT: cipherAttr->algo = HCF_ALG_RSA; break; @@ -95,6 +100,9 @@ static void SetKeyLength(HcfAlgParaValue value, void *cipher) cipherAttr->algo = HCF_ALG_SM4; break; case HCF_ALG_3DES_192: + cipherAttr->algo = HCF_ALG_3DES; + break; + case HCF_ALG_DES_64: cipherAttr->algo = HCF_ALG_DES; break; case HCF_OPENSSL_RSA_512: diff --git a/frameworks/key/sym_key_generator.c b/frameworks/key/sym_key_generator.c index e753c91..ad1a671 100644 --- a/frameworks/key/sym_key_generator.c +++ b/frameworks/key/sym_key_generator.c @@ -29,7 +29,8 @@ #define AES_KEY_SIZE_192 192 #define AES_KEY_SIZE_256 256 #define SM4_KEY_SIZE_128 128 -#define DES_KEY_SIZE_192 192 +#define DES_KEY_SIZE_64 64 +#define TRIPLE_DES_KEY_SIZE_192 192 #define HMAC_KEY_SIZE_SHA1 160 #define HMAC_KEY_SIZE_SHA224 224 #define HMAC_KEY_SIZE_SHA256 256 @@ -59,6 +60,7 @@ static const SymKeyGenAbility SYMKEY_ABILITY_SET[] = { { HCF_ALG_AES, { HcfSymKeyGeneratorSpiCreate }}, { HCF_ALG_SM4, { HcfSymKeyGeneratorSpiCreate }}, { HCF_ALG_DES, { HcfSymKeyGeneratorSpiCreate }}, + { HCF_ALG_3DES, { HcfSymKeyGeneratorSpiCreate }}, { HCF_ALG_HMAC, { HcfSymKeyGeneratorSpiCreate }} }; @@ -98,8 +100,12 @@ static void SetKeyLength(HcfAlgParaValue value, void *attr) keyAttr->keySize = SM4_KEY_SIZE_128; break; case HCF_ALG_3DES_192: + keyAttr->algo = HCF_ALG_3DES; + keyAttr->keySize = TRIPLE_DES_KEY_SIZE_192; + break; + case HCF_ALG_DES_64: keyAttr->algo = HCF_ALG_DES; - keyAttr->keySize = DES_KEY_SIZE_192; + keyAttr->keySize = DES_KEY_SIZE_64; break; default: break; diff --git a/plugin/openssl_plugin/common/inc/openssl_adapter.h b/plugin/openssl_plugin/common/inc/openssl_adapter.h index 9134fd4..315f563 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -302,6 +302,12 @@ const EVP_CIPHER *OpensslEvpDesEde3Ofb(void); const EVP_CIPHER *OpensslEvpDesEde3Cfb64(void); const EVP_CIPHER *OpensslEvpDesEde3Cfb1(void); const EVP_CIPHER *OpensslEvpDesEde3Cfb8(void); +const EVP_CIPHER *OpensslEvpDesEcb(void); +const EVP_CIPHER *OpensslEvpDesCbc(void); +const EVP_CIPHER *OpensslEvpDesOfb(void); +const EVP_CIPHER *OpensslEvpDesCfb64(void); +const EVP_CIPHER *OpensslEvpDesCfb1(void); +const EVP_CIPHER *OpensslEvpDesCfb8(void); EVP_CIPHER *OpensslEvpCipherFetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties); void OpensslEvpCipherFree(EVP_CIPHER *cipher); EVP_CIPHER_CTX *OpensslEvpCipherCtxNew(void); diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index 98c3b3b..2007b87 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -1225,6 +1225,36 @@ const EVP_CIPHER *OpensslEvpDesEde3Cfb8(void) return EVP_des_ede3_cfb8(); } +const EVP_CIPHER *OpensslEvpDesEcb(void) +{ + return EVP_des_ecb(); +} + +const EVP_CIPHER *OpensslEvpDesCbc(void) +{ + return EVP_des_cbc(); +} + +const EVP_CIPHER *OpensslEvpDesOfb(void) +{ + return EVP_des_ofb(); +} + +const EVP_CIPHER *OpensslEvpDesCfb64(void) +{ + return EVP_des_cfb64(); +} + +const EVP_CIPHER *OpensslEvpDesCfb1(void) +{ + return EVP_des_cfb1(); +} + +const EVP_CIPHER *OpensslEvpDesCfb8(void) +{ + return EVP_des_cfb8(); +} + int OpensslSm2CipherTextSize(const EC_KEY *key, const EVP_MD *digest, size_t msgLen, size_t *cipherTextSize) { return ossl_sm2_ciphertext_size(key, digest, msgLen, cipherTextSize); diff --git a/plugin/openssl_plugin/crypto_operation/cipher/inc/aes_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/aes_openssl.h index 5fcb3da..d5fcce5 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/inc/aes_openssl.h +++ b/plugin/openssl_plugin/crypto_operation/cipher/inc/aes_openssl.h @@ -21,8 +21,6 @@ extern "C" { #endif -HcfResult HcfCipherDesGeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator); - HcfResult HcfCipherAesGeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator); #ifdef __cplusplus diff --git a/plugin/openssl_plugin/crypto_operation/cipher/inc/des_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/des_openssl.h new file mode 100644 index 0000000..4331256 --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/inc/des_openssl.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2025 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. + */ +#ifndef HCF_DES_OPENSSL_H +#define HCF_DES_OPENSSL_H + +#include "cipher_factory_spi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +HcfResult HcfCipherDesGeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_3des_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c similarity index 72% rename from plugin/openssl_plugin/crypto_operation/cipher/src/cipher_3des_openssl.c rename to plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c index b8c1c45..9c50c2f 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_3des_openssl.c +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "des_openssl.h" #include "log.h" #include "blob.h" #include "memory.h" @@ -26,7 +27,9 @@ #include "openssl_class.h" #define DES_BLOCK_SIZE 8 -#define DES_SIZE_192 24 +#define DES_SIZE_64 8 +#define DES_IV_SIZE 8 +#define TRIPLE_DES_SIZE_192 24 typedef struct { HcfCipherGeneratorSpi base; @@ -44,7 +47,7 @@ static const EVP_CIPHER *DefaultCipherType(void) return OpensslEvpDesEde3Ecb(); } -static const EVP_CIPHER *GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl) +static const EVP_CIPHER *Get3DesCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl) { switch (impl->attr.mode) { case HCF_ALG_MODE_ECB: @@ -66,6 +69,28 @@ static const EVP_CIPHER *GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl return DefaultCipherType(); } +static const EVP_CIPHER *GetDesCipherType(HcfCipherDesGeneratorSpiOpensslImpl *impl) +{ + switch (impl->attr.mode) { + case HCF_ALG_MODE_ECB: + return OpensslEvpDesEcb(); + case HCF_ALG_MODE_CBC: + return OpensslEvpDesCbc(); + case HCF_ALG_MODE_OFB: + return OpensslEvpDesOfb(); + case HCF_ALG_MODE_CFB: + case HCF_ALG_MODE_CFB64: + return OpensslEvpDesCfb64(); + case HCF_ALG_MODE_CFB1: + return OpensslEvpDesCfb1(); + case HCF_ALG_MODE_CFB8: + return OpensslEvpDesCfb8(); + default: + break; + } + return OpensslEvpDesEcb(); +} + static HcfResult InitCipherData(enum HcfCryptoMode opMode, CipherData **cipherData) { HcfResult ret = HCF_INVALID_PARAMS; @@ -91,10 +116,9 @@ clearup: return ret; } -static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode, - HcfKey *key, HcfParamsSpec *params) +static HcfResult ValidateCipherInitParams(HcfCipherGeneratorSpi *self, HcfKey *key) { - if ((self == NULL) || (key == NULL)) { /* params maybe is null */ + if ((self == NULL) || (key == NULL)) { LOGE("Invalid input parameter."); return HCF_INVALID_PARAMS; } @@ -106,27 +130,104 @@ static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMod LOGE("Class is not match."); return HCF_INVALID_PARAMS; } + return HCF_SUCCESS; +} + +static const EVP_CIPHER *GetCipherType(HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl, SymKeyImpl *keyImpl) +{ + if (cipherImpl->attr.algo == HCF_ALG_3DES) { + if (keyImpl->keyMaterial.len < TRIPLE_DES_SIZE_192) { + LOGE("Init failed, the input key size is smaller than keySize specified in cipher."); + return NULL; + } + return Get3DesCipherType(cipherImpl); + } else if (cipherImpl->attr.algo == HCF_ALG_DES) { + if (keyImpl->keyMaterial.len != DES_SIZE_64) { + LOGE("Init failed, the input key size is smaller than keySize specified in cipher."); + return NULL; + } + return GetDesCipherType(cipherImpl); + } + return NULL; +} + +static const unsigned char *GetIvData(HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl, HcfParamsSpec *params) +{ + if (cipherImpl == NULL) { + LOGE("cipherImpl is NULL."); + return NULL; + } + + // ECB mode does not require an IV + if (cipherImpl->attr.mode == HCF_ALG_MODE_ECB) { + return NULL; + } + + if (params == NULL) { + LOGE("params is NULL, but IV is required for non-ECB modes."); + return NULL; + } + + HcfIvParamsSpec *spec = (HcfIvParamsSpec *)params; + + if (spec->iv.data == NULL) { + LOGE("IV data is NULL, but IV is required for non-ECB modes."); + return NULL; + } + + if (cipherImpl->attr.algo == HCF_ALG_DES) { + // Ensure IV length is exactly 8 bytes for DES + if (spec->iv.len != DES_IV_SIZE) { + LOGE("DES IV length is invalid."); + return NULL; + } + return (const unsigned char *)spec->iv.data; + } else if (cipherImpl->attr.algo == HCF_ALG_3DES) { + // For 3DES, IV length is not strictly validated here + return (const unsigned char *)spec->iv.data; + } else { + LOGE("Unsupported algorithm for IV retrieval."); + return NULL; + } +} + +static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode, + HcfKey *key, HcfParamsSpec *params) +{ + HcfResult ret = ValidateCipherInitParams(self, key); + if (ret != HCF_SUCCESS) { + return ret; + } HcfCipherDesGeneratorSpiOpensslImpl *cipherImpl = (HcfCipherDesGeneratorSpiOpensslImpl *)self; SymKeyImpl *keyImpl = (SymKeyImpl *)key; int32_t enc = (opMode == ENCRYPT_MODE) ? 1 : 0; - if (keyImpl->keyMaterial.len < DES_SIZE_192) { - LOGE("Init failed, the input key size is smaller than keySize specified in cipher."); + const EVP_CIPHER *cipher = GetCipherType(cipherImpl, keyImpl); + if (cipher == NULL) { return HCF_INVALID_PARAMS; } - if (InitCipherData(opMode, &(cipherImpl->cipherData)) != HCF_SUCCESS) { + + if (InitCipherData(opMode, &(cipherImpl->cipherData)) != HCF_SUCCESS) { LOGE("InitCipherData failed"); return HCF_INVALID_PARAMS; } - HcfResult ret = HCF_ERR_CRYPTO_OPERATION; + + ret = HCF_ERR_CRYPTO_OPERATION; CipherData *data = cipherImpl->cipherData; - if (OpensslEvpCipherInit(data->ctx, GetCipherType(cipherImpl), NULL, NULL, enc) != HCF_OPENSSL_SUCCESS) { + + if (OpensslEvpCipherInit(data->ctx, cipher, NULL, NULL, enc) != HCF_OPENSSL_SUCCESS) { HcfPrintOpensslError(); LOGD("[error] Cipher init failed."); goto clearup; } - if (OpensslEvpCipherInit(data->ctx, NULL, keyImpl->keyMaterial.data, GetIv(params), enc) != HCF_OPENSSL_SUCCESS) { + const unsigned char *iv = GetIvData(cipherImpl, params); + if (iv == NULL && cipherImpl->attr.mode != HCF_ALG_MODE_ECB) { + LOGE("IV is required for non-ECB modes."); + ret = HCF_INVALID_PARAMS; + goto clearup; + } + if (OpensslEvpCipherInit(data->ctx, NULL, keyImpl->keyMaterial.data, iv, enc) != HCF_OPENSSL_SUCCESS) { HcfPrintOpensslError(); LOGD("[error] Cipher init key and iv failed."); goto clearup; @@ -138,8 +239,11 @@ static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMod goto clearup; } return HCF_SUCCESS; + clearup: - FreeCipherData(&(cipherImpl->cipherData)); + if (cipherImpl->cipherData != NULL) { + FreeCipherData(&(cipherImpl->cipherData)); + } return ret; } diff --git a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c index dc7391b..6d7ff0a 100644 --- a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c +++ b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c @@ -27,7 +27,8 @@ #define KEY_BIT 8 #define AES_ALG_NAME "AES" #define SM4_ALG_NAME "SM4" -#define DES_ALG_NAME "3DES" +#define DES_ALG_NAME "DES" +#define TRIPLE_DES_ALG_NAME "3DES" #define HMAC_ALG_NAME "HMAC" typedef struct { @@ -193,6 +194,8 @@ static char *GetAlgoNameType(HcfAlgValue type) return SM4_ALG_NAME; case HCF_ALG_DES: return DES_ALG_NAME; + case HCF_ALG_3DES: + return TRIPLE_DES_ALG_NAME; case HCF_ALG_HMAC: return HMAC_ALG_NAME; default: diff --git a/plugin/plugin.gni b/plugin/plugin.gni index b95ff88..c952c6e 100644 --- a/plugin/plugin.gni +++ b/plugin/plugin.gni @@ -70,7 +70,7 @@ plugin_sym_key_files = [ plugin_cipher_files = [ "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_rsa_openssl.c", - "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_3des_openssl.c", + "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_aes_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_aes_common.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c", diff --git a/test/unittest/src/crypto_3des_cipher_test.cpp b/test/unittest/src/crypto_3des_cipher_test.cpp index e6b2f49..3b9f86d 100644 --- a/test/unittest/src/crypto_3des_cipher_test.cpp +++ b/test/unittest/src/crypto_3des_cipher_test.cpp @@ -23,7 +23,7 @@ #include "detailed_iv_params.h" #include "detailed_gcm_params.h" #include "detailed_ccm_params.h" -#include "aes_openssl.h" +#include "des_openssl.h" using namespace std; using namespace testing::ext; @@ -52,7 +52,7 @@ void Crypto3DesCipherTest::TearDown() // add destroy here, this will be called w { } -static HcfResult GenerateDesSymKey(HcfSymKey **key) +static HcfResult Generate3DesSymKey(HcfSymKey **key) { HcfSymKeyGenerator *generator = nullptr; @@ -70,6 +70,24 @@ static HcfResult GenerateDesSymKey(HcfSymKey **key) return ret; } +static HcfResult GenerateDesSymKey(HcfSymKey **key) +{ + HcfSymKeyGenerator *generator = nullptr; + + HcfResult ret = HcfSymKeyGeneratorCreate("DES64", &generator); + if (ret != HCF_SUCCESS) { + LOGE("HcfSymKeyGeneratorCreate failed!"); + return ret; + } + + ret = generator->generateSymKey(generator, key); + if (ret != HCF_SUCCESS) { + LOGE("generateSymKey failed!"); + } + HcfObjDestroy(generator); + return ret; +} + static int32_t DesEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, uint8_t *cipherText, int *cipherTextLen) { @@ -991,7 +1009,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest025, TestSize.Level0) ivSpec.iv.data = iv; ivSpec.iv.len = DES_IV_LEN; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|CFB1|NoPadding", &cipher); @@ -1018,7 +1036,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest026, TestSize.Level0) ivSpec.iv.data = iv; ivSpec.iv.len = DES_IV_LEN; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|CFB8|NoPadding", &cipher); @@ -1045,7 +1063,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest027, TestSize.Level0) ivSpec.iv.data = iv; ivSpec.iv.len = DES_IV_LEN; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|PKCS5", &cipher); @@ -1066,7 +1084,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest028, TestSize.Level0) HcfCipher *cipher = nullptr; HcfSymKey *key = nullptr; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|ECB|PKCS5", &cipher); @@ -1107,7 +1125,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest030, TestSize.Level0) HcfCipher *cipher = nullptr; HcfSymKey *key = nullptr; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|ECB|PKCS5", &cipher); @@ -1128,7 +1146,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest031, TestSize.Level0) HcfBlob input = { .data = plainText, .len = PLAINTEXT_LEN }; HcfBlob output = { .data = nullptr, .len = 0 }; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|ECB|PKCS5", &cipher); @@ -1156,7 +1174,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest032, TestSize.Level0) HcfBlob input = { .data = plainText, .len = PLAINTEXT_LEN }; HcfBlob output = { .data = nullptr, .len = 0 }; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|ECB|PKCS5", &cipher); @@ -1185,7 +1203,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest033, TestSize.Level0) HcfBlob input = { .data = plainText, .len = PLAINTEXT_LEN }; HcfBlob output = { .data = nullptr, .len = 0 }; - ret = GenerateDesSymKey(&key); + ret = Generate3DesSymKey(&key); EXPECT_EQ(ret, HCF_SUCCESS); ret = HcfCipherCreate("3DES192|ECB|PKCS5", &cipher); @@ -1219,7 +1237,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest034, TestSize.Level0) HcfBlob input = { .data = plainText, .len = PLAINTEXT_LEN }; HcfBlob output = { .data = nullptr, .len = 0 }; - int ret = GenerateDesSymKey(&key); + int ret = Generate3DesSymKey(&key); ASSERT_EQ(ret, 0); ret = HcfCipherCreate("3DES192|ECB|PKCS5", &cipher); @@ -1249,7 +1267,7 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest035, TestSize.Level0) HcfCipherGeneratorSpi *cipher = nullptr; CipherAttr params = { - .algo = HCF_ALG_DES, + .algo = HCF_ALG_3DES, .mode = HCF_ALG_MODE_ECB, .paddingMode = HCF_ALG_PADDING_PKCS5, }; @@ -1281,4 +1299,168 @@ HWTEST_F(Crypto3DesCipherTest, Crypto3DesCipherTest035, TestSize.Level0) HcfObjDestroy(cipher); HcfBlobDataFree(&dataArray); } + +HWTEST_F(Crypto3DesCipherTest, CryptoDesCipherTest001, TestSize.Level0) +{ + int ret = 0; + uint8_t cipherText[CIPHER_TEXT_LEN] = {0}; + int cipherTextLen = CIPHER_TEXT_LEN; + + HcfSymKey *key = nullptr; + HcfCipher *cipher = nullptr; + + ret = GenerateDesSymKey(&key); + if (ret != 0) { + LOGE("GenerateDesSymKey failed!"); + goto clearup; + } + + ret = HcfCipherCreate("DES64|ECB|PKCS7", &cipher); + if (ret != 0) { + LOGE("HcfCipherCreate failed!"); + goto clearup; + } + + ret = DesEncrypt(cipher, key, nullptr, cipherText, &cipherTextLen); + if (ret != 0) { + LOGE("DesEncrypt failed! %{public}d", ret); + goto clearup; + } + + ret = DesDecrypt(cipher, key, nullptr, cipherText, cipherTextLen); + if (ret != 0) { + LOGE("DesDecrypt failed! %{public}d", ret); + } + +clearup: + HcfObjDestroy(key); + HcfObjDestroy(cipher); + EXPECT_EQ(ret, 0); +} + +static HcfResult ConvertDesSymKey(HcfBlob *dataBlob, HcfSymKey **key) +{ + HcfSymKeyGenerator *generator = nullptr; + + HcfResult ret = HcfSymKeyGeneratorCreate("DES64", &generator); + if (ret != HCF_SUCCESS) { + LOGE("HcfSymKeyGeneratorCreate failed!"); + return ret; + } + + ret = generator->convertSymKey(generator, dataBlob, key); + if (ret != HCF_SUCCESS) { + LOGE("generateSymKey failed!"); + } + HcfObjDestroy(generator); + return ret; +} + +HWTEST_F(Crypto3DesCipherTest, CryptoDesCipherTestVecderEnc, TestSize.Level0) +{ + int ret = 0; + uint8_t plainText[] = {0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74}; // "Now is t" + uint8_t keyData[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; // Test key + uint8_t expectedCipherText[] = {0x3f, 0xa4, 0x0e, 0x8a, 0x98, 0x4d, 0x48, 0x15}; // Expected ciphertext + + HcfBlob input = {.data = plainText, .len = sizeof(plainText)}; + HcfBlob output = {}; + HcfBlob keyDataBlob = {.data = keyData, .len = sizeof(keyData)}; + + HcfSymKey *key = nullptr; + HcfCipher *cipher = nullptr; + + // Convert key data to HcfSymKey + ret = ConvertDesSymKey(&keyDataBlob, &key); + if (ret != 0) { + LOGE("ConvertDesSymKey failed! ret: %{public}d", ret); + goto clearup; + } + + // Create DES cipher + ret = HcfCipherCreate("DES64|ECB|NoPadding", &cipher); + if (ret != 0) { + LOGE("HcfCipherCreate failed! ret: %{public}d", ret); + goto clearup; + } + + // Encrypt + ret = cipher->init(cipher, ENCRYPT_MODE, (HcfKey *)key, nullptr); + if (ret != 0) { + LOGE("Cipher init failed for encryption! ret: %{public}d", ret); + goto clearup; + } + + ret = cipher->doFinal(cipher, &input, &output); + if (ret != 0) { + LOGE("Cipher update failed for encryption! ret: %{public}d", ret); + goto clearup; + } + + // Verify ciphertext + EXPECT_EQ(output.len, sizeof(expectedCipherText)); + EXPECT_EQ(memcmp(output.data, expectedCipherText, sizeof(expectedCipherText)), 0); + +clearup: + HcfObjDestroy(key); + HcfObjDestroy(cipher); + if (output.data != nullptr) { + HcfBlobDataFree(&output); + } + EXPECT_EQ(ret, 0); +} + +HWTEST_F(Crypto3DesCipherTest, CryptoDesCipherTestVecderDec, TestSize.Level0) +{ + int ret = 0; + uint8_t expectedCipherText[] = {0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74}; // "Now is t" + uint8_t keyData[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; // Test key + uint8_t plainText[] = {0x3f, 0xa4, 0x0e, 0x8a, 0x98, 0x4d, 0x48, 0x15}; // Expected ciphertext + + HcfBlob input = {.data = plainText, .len = sizeof(plainText)}; + HcfBlob output = {}; + HcfBlob keyDataBlob = {.data = keyData, .len = sizeof(keyData)}; + + HcfSymKey *key = nullptr; + HcfCipher *cipher = nullptr; + + // Convert key data to HcfSymKey + ret = ConvertDesSymKey(&keyDataBlob, &key); + if (ret != 0) { + LOGE("ConvertDesSymKey failed! ret: %{public}d", ret); + goto clearup; + } + + // Create DES cipher + ret = HcfCipherCreate("DES64|ECB|NoPadding", &cipher); + if (ret != 0) { + LOGE("HcfCipherCreate failed! ret: %{public}d", ret); + goto clearup; + } + + // Encrypt + ret = cipher->init(cipher, DECRYPT_MODE, (HcfKey *)key, nullptr); + if (ret != 0) { + LOGE("Cipher init failed for encryption! ret: %{public}d", ret); + goto clearup; + } + + ret = cipher->doFinal(cipher, &input, &output); + if (ret != 0) { + LOGE("Cipher update failed for encryption! ret: %{public}d", ret); + goto clearup; + } + + // Verify ciphertext + EXPECT_EQ(output.len, sizeof(expectedCipherText)); + EXPECT_EQ(memcmp(output.data, expectedCipherText, sizeof(expectedCipherText)), 0); + +clearup: + HcfObjDestroy(key); + HcfObjDestroy(cipher); + if (output.data != nullptr) { + HcfBlobDataFree(&output); + } + EXPECT_EQ(ret, 0); +} } -- Gitee From 3fd1e7093de37a6ed80993ef32fd90399f1b3f4e Mon Sep 17 00:00:00 2001 From: lcc Date: Wed, 16 Apr 2025 17:58:08 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=AF=B9=E9=9A=8F=E6=9C=BA=E7=94=9F?= =?UTF-8?q?=E6=88=90DES=E5=AF=86=E9=92=A5=E5=81=9A=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lcc --- .../common/inc/openssl_adapter.h | 2 + .../common/src/openssl_adapter.c | 6 ++ .../sym_key_generator/src/sym_key_openssl.c | 56 +++++++++++++++++-- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/plugin/openssl_plugin/common/inc/openssl_adapter.h b/plugin/openssl_plugin/common/inc/openssl_adapter.h index 315f563..f830458 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -331,6 +331,8 @@ int OpensslPkcs5Pbkdf2Hmac(const char *pass, int passlen, const unsigned char *s EC_GROUP *OpensslEcGroupNewByCurveName(int nid); +int OpensslEvpEncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); int OpensslEvpCipherCtxCtrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); DH *OpensslDhNew(void); diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index 2007b87..f4ec918 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -1288,6 +1288,12 @@ EC_GROUP *OpensslEcGroupNewByCurveName(int nid) return EC_GROUP_new_by_curve_name(nid); } +int OpensslEvpEncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv) +{ + return EVP_EncryptInit(ctx, cipher, key, iv); +} + int OpensslEvpCipherCtxCtrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) { return EVP_CIPHER_CTX_ctrl(ctx, type, arg, ptr); diff --git a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c index 6d7ff0a..1358513 100644 --- a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c +++ b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c @@ -148,6 +148,42 @@ static HcfResult HcfSymmKeySpiCreate(int32_t keyLen, SymKeyImpl *symKey) return res; } +static HcfResult HcfDesSymmKeySpiCreate(int32_t keyLen, SymKeyImpl *symKey) +{ + if ((keyLen == 0) || (symKey == NULL)) { + LOGE("Invalid input parameter!"); + return HCF_INVALID_PARAMS; + } + uint8_t *keyMaterial = (uint8_t *)HcfMalloc(keyLen, 0); + if (keyMaterial == NULL) { + LOGE("keyMaterial malloc failed!"); + return HCF_ERR_MALLOC; + } + EVP_CIPHER_CTX *ctx = OpensslEvpCipherCtxNew(); + if (ctx == NULL) { + LOGE("Failed to create EVP_CIPHER_CTX!"); + HcfFree(keyMaterial); + return HCF_ERR_CRYPTO_OPERATION; + } + if (OpensslEvpEncryptInit(ctx, OpensslEvpDesEcb(), NULL, NULL) != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error] EVP_CipherInit failed!"); + return false; + } + if (OpensslEvpCipherCtxCtrl(ctx, EVP_CTRL_RAND_KEY, 0, keyMaterial) != 1) { + HcfPrintOpensslError(); + LOGE("EVP_CIPHER_CTX_ctrl failed to validate DES key!"); + EVP_CIPHER_CTX_free(ctx); + HcfFree(keyMaterial); + return HCF_INVALID_PARAMS; + } + + EVP_CIPHER_CTX_free(ctx); + symKey->keyMaterial.data = keyMaterial; + symKey->keyMaterial.len = keyLen; + return HCF_SUCCESS; +} + static void DestroySymKeyGeneratorSpi(HcfObjectBase *base) { if (base == NULL) { @@ -270,11 +306,21 @@ static HcfResult GenerateSymmKey(HcfSymKeyGeneratorSpi *self, HcfSymKey **symmKe return HCF_ERR_MALLOC; } HcfSymKeyGeneratorSpiOpensslImpl *impl = (HcfSymKeyGeneratorSpiOpensslImpl *)self; - HcfResult res = HcfSymmKeySpiCreate(impl->attr.keySize / KEY_BIT, returnSymmKey); - if (res != HCF_SUCCESS) { - HcfFree(returnSymmKey); - return res; + HcfResult res = HCF_SUCCESS; + if (impl->attr.algo == HCF_ALG_DES) { + res = HcfDesSymmKeySpiCreate(impl->attr.keySize / KEY_BIT, returnSymmKey); + if (res != HCF_SUCCESS) { + HcfFree(returnSymmKey); + return res; + } + } else { + res = HcfSymmKeySpiCreate(impl->attr.keySize / KEY_BIT, returnSymmKey); + if (res != HCF_SUCCESS) { + HcfFree(returnSymmKey); + return res; + } } + returnSymmKey->algoName = GetAlgoName(impl, impl->attr.keySize); returnSymmKey->key.clearMem = ClearMem; returnSymmKey->key.key.getEncoded = GetEncoded; @@ -283,7 +329,7 @@ static HcfResult GenerateSymmKey(HcfSymKeyGeneratorSpi *self, HcfSymKey **symmKe returnSymmKey->key.key.base.destroy = DestroySymKeySpi; returnSymmKey->key.key.base.getClass = GetSymKeyClass; *symmKey = (HcfSymKey *)returnSymmKey; - return HCF_SUCCESS; + return res; } static bool IsBlobKeyLenValid(SymKeyAttr attr, const HcfBlob *key) -- Gitee From 6bf5342eb04158dd50ad00910b23eea64c340865 Mon Sep 17 00:00:00 2001 From: lcc Date: Wed, 23 Apr 2025 17:10:15 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E7=AE=97=E6=B3=95=E5=BA=936.0=E9=9C=80?= =?UTF-8?q?=E6=B1=82=E9=92=88=E5=AF=B9=E6=96=B0=E5=A2=9E=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=A0=81=E8=BF=9B=E8=A1=8C=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lcc --- frameworks/frameworks.gni | 7 +++---- .../js/napi/crypto/inc/napi_crypto_framework_defines.h | 1 + frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp | 4 ++-- frameworks/js/napi/crypto/src/napi_utils.cpp | 2 ++ interfaces/inner_api/common/result.h | 2 ++ .../cipher/src/cipher_sm2_ecdsa_signature_openssl.c | 6 +++--- .../key/sym_key_generator/src/sym_key_openssl.c | 4 +++- test/unittest/BUILD.gn | 2 +- test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp | 8 ++++---- 9 files changed, 21 insertions(+), 15 deletions(-) diff --git a/frameworks/frameworks.gni b/frameworks/frameworks.gni index 8a87bdc..9d10da1 100644 --- a/frameworks/frameworks.gni +++ b/frameworks/frameworks.gni @@ -57,11 +57,10 @@ framework_md_files = [ "${framework_path}/crypto_operation/md.c" ] framework_kdf_files = [ "${framework_path}/crypto_operation/kdf.c" ] -framework_sm2_crypto_util_files = [ +framework_sm2_crypto_util_files = [ "${framework_path}/crypto_operation/sm2_crypto_util.c", - "${framework_path}/crypto_operation/sm2_ec_signature_data.c" - - ] + "${framework_path}/crypto_operation/sm2_ec_signature_data.c", +] framework_files = framework_key_agreement_files + framework_signature_files + diff --git a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h index c94bc34..76f8605 100644 --- a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h +++ b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h @@ -36,6 +36,7 @@ constexpr uint32_t JS_ERR_INVALID_PARAMS = 401; constexpr uint32_t JS_ERR_NOT_SUPPORT = 801; constexpr uint32_t JS_ERR_OUT_OF_MEMORY = 17620001; constexpr uint32_t JS_ERR_RUNTIME_ERROR = 17620002; +constexpr uint32_t JS_ERR_PARAMETER_CHECK_FAILED = 17620003; constexpr uint32_t JS_ERR_CRYPTO_OPERATION = 17630001; constexpr int32_t SPEC_ITEM_TYPE_BIG_INT = 1; diff --git a/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp b/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp index ca9927f..76b8bbd 100644 --- a/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp +++ b/frameworks/js/napi/crypto/src/napi_sm2_ec_signature.cpp @@ -135,7 +135,7 @@ static napi_value ConvertSm2CipherTextSpecToNapiValue(napi_env env, Sm2EcSignatu { if (!CheckSm2CipherTextSpec(spec)) { LOGE("Invalid spec!"); - napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Invalid spec!")); + napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "Invalid spec!")); return NapiGetNull(env); } napi_value instance; @@ -147,7 +147,7 @@ static napi_value ConvertSm2CipherTextSpecToNapiValue(napi_env env, Sm2EcSignatu } if (!BuildSm2CipherTextSpecToNapiValue(env, spec, &instance)) { LOGE("Build object failed!"); - napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build object failed!")); + napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "build object failed!")); return NapiGetNull(env); } return instance; diff --git a/frameworks/js/napi/crypto/src/napi_utils.cpp b/frameworks/js/napi/crypto/src/napi_utils.cpp index 236d988..18f4544 100644 --- a/frameworks/js/napi/crypto/src/napi_utils.cpp +++ b/frameworks/js/napi/crypto/src/napi_utils.cpp @@ -1912,6 +1912,8 @@ static uint32_t GetJsErrValueByErrCode(HcfResult errCode) return JS_ERR_RUNTIME_ERROR; case HCF_ERR_CRYPTO_OPERATION: return JS_ERR_CRYPTO_OPERATION; + case HCF_ERR_PARAMETER_CHECK_FAILED: + return JS_ERR_PARAMETER_CHECK_FAILED; default: return JS_ERR_DEFAULT_ERR; } diff --git a/interfaces/inner_api/common/result.h b/interfaces/inner_api/common/result.h index 24088e2..a0e72a9 100644 --- a/interfaces/inner_api/common/result.h +++ b/interfaces/inner_api/common/result.h @@ -28,6 +28,8 @@ typedef enum HcfResult { HCF_ERR_MALLOC = -20001, /** Indicates that call napi api fails. */ HCF_ERR_NAPI = -20002, + /** Indicates that parameter check failed. */ + HCF_ERR_PARAMETER_CHECK_FAILED = -20003, /** Indicates that third part has something wrong. */ HCF_ERR_CRYPTO_OPERATION = -30001, diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c index d9ae81e..b402e01 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c @@ -27,7 +27,7 @@ static HcfResult BuildSm2Ciphertext(const Sm2EcSignatureDataSpec *spec, ECDSA_SI { if (spec == NULL || sm2Text == NULL) { LOGE("Invalid params"); - return HCF_INVALID_PARAMS; + return HCF_ERR_PARAMETER_CHECK_FAILED; } BIGNUM *r = NULL; BIGNUM *s = NULL; @@ -53,7 +53,7 @@ HcfResult HcfSm2SpecToDerData(Sm2EcSignatureDataSpec *spec, HcfBlob *output) { if (spec == NULL || output == NULL) { LOGE("Invalid params"); - return HCF_INVALID_PARAMS; + return HCF_ERR_PARAMETER_CHECK_FAILED; } ECDSA_SIG *sig = OpensslEcdsaSigNew(); HcfResult res = BuildSm2Ciphertext(spec, sig); @@ -98,7 +98,7 @@ HcfResult HcfDerDataToSm2Spec(HcfBlob *input, Sm2EcSignatureDataSpec **returnSpe { if (input == NULL || returnSpec == NULL) { LOGE("Invalid signature params"); - return HCF_INVALID_PARAMS; + return HCF_ERR_PARAMETER_CHECK_FAILED; } Sm2EcSignatureDataSpec *tempSpec = (Sm2EcSignatureDataSpec *)(HcfMalloc(sizeof(Sm2EcSignatureDataSpec), 0)); diff --git a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c index 1358513..16079ee 100644 --- a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c +++ b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c @@ -167,8 +167,10 @@ static HcfResult HcfDesSymmKeySpiCreate(int32_t keyLen, SymKeyImpl *symKey) } if (OpensslEvpEncryptInit(ctx, OpensslEvpDesEcb(), NULL, NULL) != HCF_OPENSSL_SUCCESS) { HcfPrintOpensslError(); + HcfFree(keyMaterial); + EVP_CIPHER_CTX_free(ctx); LOGD("[error] EVP_CipherInit failed!"); - return false; + return HCF_ERR_CRYPTO_OPERATION; } if (OpensslEvpCipherCtxCtrl(ctx, EVP_CTRL_RAND_KEY, 0, keyMaterial) != 1) { HcfPrintOpensslError(); diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 3999e0b..eee19a4 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -126,8 +126,8 @@ ohos_unittest("crypto_framework_test") { "src/native/native_sym_key_test.cpp", "src/sm2/crypto_sm2_asy_key_generator_by_spec_sub_test.cpp", "src/sm2/crypto_sm2_asy_key_generator_by_spec_test.cpp", + "src/sm2/crypto_sm2_ecdsa_signature_test.cpp", "src/sm2/crypto_sm2_util_test.cpp", - "src/sm2/crypto_sm2_ecdsa_signature_test.cpp" ] sources += framework_files + plugin_files diff --git a/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp b/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp index 85b6acd..87ace8a 100644 --- a/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp +++ b/test/unittest/src/sm2/crypto_sm2_ecdsa_signature_test.cpp @@ -96,27 +96,27 @@ HWTEST_F(CryptoSm2EcdsaSignature, HcfSm2SpecToDerDataAndBack, TestSize.Level0) HWTEST_F(CryptoSm2EcdsaSignature, HcfSm2SpecToDerData_NullInput, TestSize.Level0) { HcfBlob derOutput = { .data = nullptr, .len = 0 }; - EXPECT_EQ(HcfSm2SpecToDerData(nullptr, &derOutput), HCF_INVALID_PARAMS); + EXPECT_EQ(HcfSm2SpecToDerData(nullptr, &derOutput), HCF_ERR_PARAMETER_CHECK_FAILED); } HWTEST_F(CryptoSm2EcdsaSignature, HcfSm2SpecToDerData_NullOutput, TestSize.Level0) { Sm2EcSignatureDataSpec *spec = nullptr; ASSERT_EQ(ConstructCorrectSm2Spec(&spec), HCF_SUCCESS); - EXPECT_EQ(HcfSm2SpecToDerData(spec, nullptr), HCF_INVALID_PARAMS); + EXPECT_EQ(HcfSm2SpecToDerData(spec, nullptr), HCF_ERR_PARAMETER_CHECK_FAILED); HcfFree(spec); } HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_NullInput, TestSize.Level0) { Sm2EcSignatureDataSpec *returnSpec = nullptr; - EXPECT_EQ(HcfDerDataToSm2Spec(nullptr, &returnSpec), HCF_INVALID_PARAMS); + EXPECT_EQ(HcfDerDataToSm2Spec(nullptr, &returnSpec), HCF_ERR_PARAMETER_CHECK_FAILED); } HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_NullOutput, TestSize.Level0) { HcfBlob derInput = { .data = g_rCoordinate, .len = sizeof(g_rCoordinate) }; - EXPECT_EQ(HcfDerDataToSm2Spec(&derInput, nullptr), HCF_INVALID_PARAMS); + EXPECT_EQ(HcfDerDataToSm2Spec(&derInput, nullptr), HCF_ERR_PARAMETER_CHECK_FAILED); } HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_InvalidData, TestSize.Level0) -- Gitee