diff --git a/common/inc/params_parser.h b/common/inc/params_parser.h index a5a434ac3089aebd2c9ef115aec9b1e3eb1326f0..d51625a2be67463518f7118580fd01afd9eb114b 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/asy_key_params.c b/common/src/asy_key_params.c index 61b178de306140da207737159eff993a7dd9dc45..a525620dbc715fde2865ca4f592b652f27442834 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/common/src/params_parser.c b/common/src/params_parser.c index b76bd1580d8163c2168e5b7e1e27f591303a5380..07da92623143f0e72dc5db88eb652a7696d79bbf 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 f73c8442339bd3d160e0e778cf5c8ef2e27958cf..e524bbef7f059309c8e9b1407aabac0c9326a459 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/crypto_operation/sm2_ec_signature_data.c b/frameworks/crypto_operation/sm2_ec_signature_data.c new file mode 100644 index 0000000000000000000000000000000000000000..deecb094f7b747b0e7052b8399121a58dccccc7e --- /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 e5b4de189e35c509172bb64b6b89a3c8d0fc82ee..9d10da1beef2ecdd9c4aebd1c1018b678e158330 100644 --- a/frameworks/frameworks.gni +++ b/frameworks/frameworks.gni @@ -57,8 +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_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 33d96ee2792fda88c9012c0fd033dae25d2834a7..629594b4bf3645d835046545f0da91bbf2d4437d 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 5874584790a84ff6412056f8dd559a65107f1fc7..76f8605985e7cf24d0ae417bf5a034682d82afab 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; @@ -93,6 +94,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 0000000000000000000000000000000000000000..3bd45ef10d855a6fc5437e5ff1081e559bc6c1d2 --- /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 b36f0d3db991d60887b0b6a86de7b355d6161178..5d9c3cdb7644c68b5a119e966e52433e6a465ee7 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 0000000000000000000000000000000000000000..76b8bbdcdec2d2dc08a961b838c94a3089ed370e --- /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_ERR_NAPI, "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_ERR_NAPI, "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/frameworks/js/napi/crypto/src/napi_utils.cpp b/frameworks/js/napi/crypto/src/napi_utils.cpp index 236d988132b0030804fe4ea1af1463831bf091f7..18f4544f3e76af137168d2e3a59630f68221b29e 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/frameworks/key/sym_key_generator.c b/frameworks/key/sym_key_generator.c index e753c910d611cbd7c0d3fb006fcaffa421b398a8..ad1a6710b57dbafd6708e1c00d984981b8101891 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/interfaces/inner_api/algorithm_parameter/sm2_crypto_params.h b/interfaces/inner_api/algorithm_parameter/sm2_crypto_params.h index 92db7f460e1a4f10ddcfb6a769f8c1d86c0716be..3a02cc6cfef1f4673968f5b01cdba631f15b5c72 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/common/result.h b/interfaces/inner_api/common/result.h index 24088e20afeb9f8c77d64831db600191453c79cb..a0e72a9bc54555137b676be9a0164ab4539c17c0 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/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 0000000000000000000000000000000000000000..d1b4c6b7f8f70885f2864a86648bd38e66d2f80f --- /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 1affe17d248732505e49c62729055bfe85bb1ec0..f830458b651c148fc5bff7698b0ba99dd219b8b3 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 @@ -301,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); @@ -324,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); @@ -365,6 +374,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 81c0851c38b4858f79000e01cb09de6aff8c8c33..f4ec918e71f389bc50f8ff5498fefd36844d05f0 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); @@ -1258,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); @@ -1408,6 +1444,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/aes_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/aes_openssl.h index 5fcb3da563c8fd8fd14044ea1f419059145b7c22..d5fcce5f6620af0e996bbdec332684ee47afe742 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/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 0000000000000000000000000000000000000000..a75cd17ea5bd44593c25d14d9d3959b3c0f35f1d --- /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/inc/des_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/des_openssl.h new file mode 100644 index 0000000000000000000000000000000000000000..4331256f61a0b7948af0a3bf545f9830df311fb4 --- /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 b8c1c458979c72c5946af99b96dcf698eb59776a..9c50c2f542444619c6aadfa97ad83e3b6d4e8dcd 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/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 0000000000000000000000000000000000000000..b402e013d95bfbd2b5c2ec0988aa7c09ef122185 --- /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_ERR_PARAMETER_CHECK_FAILED; + } + 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_ERR_PARAMETER_CHECK_FAILED; + } + 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_ERR_PARAMETER_CHECK_FAILED; + } + + 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/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 dc7391ba6910da0058822cc33a4d44cdc82a3dfd..16079ee4ab5d111d920fd76449c810fbb20ed5ea 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 { @@ -147,6 +148,44 @@ 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(); + HcfFree(keyMaterial); + EVP_CIPHER_CTX_free(ctx); + LOGD("[error] EVP_CipherInit failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + 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) { @@ -193,6 +232,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: @@ -267,11 +308,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; @@ -280,7 +331,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) diff --git a/plugin/plugin.gni b/plugin/plugin.gni index 9785bad3f3b08696e4a2fdf0f69fb090158a4714..c952c6e247f194b712d8e33716113ab06d54b8b6 100644 --- a/plugin/plugin.gni +++ b/plugin/plugin.gni @@ -70,12 +70,13 @@ 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", "${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 2275276b914f49397712566fa0ba665d37f8c4c1..eee19a469ac50a61cc696e0e604bc3625cbcf345 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -126,6 +126,7 @@ 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", ] diff --git a/test/unittest/src/crypto_3des_cipher_test.cpp b/test/unittest/src/crypto_3des_cipher_test.cpp index e6b2f498d82aaa8d3078429bc2b63d0eb0f7b20e..3b9f86d52440ff9d3355b4f6db0a83a5b37443c9 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); +} } 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 0000000000000000000000000000000000000000..87ace8a4afe9edf9262ab1df7abb748c102a0f51 --- /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_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_ERR_PARAMETER_CHECK_FAILED); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2EcdsaSignature, HcfDerDataToSm2Spec_NullInput, TestSize.Level0) +{ + Sm2EcSignatureDataSpec *returnSpec = nullptr; + 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_ERR_PARAMETER_CHECK_FAILED); +} + +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