diff --git a/bundle.json b/bundle.json index 11c5ca2d0b0929178f0311e6466634dceb18b207..f94c83b095de98a679eb2909e562e32acedd0a8e 100644 --- a/bundle.json +++ b/bundle.json @@ -53,6 +53,7 @@ "algorithm_parameter/detailed_pbkdf2_params.h", "algorithm_parameter/detailed_rsa_key_params.h", "algorithm_parameter/kdf_params.h", + "algorithm_parameter/sm2_crypt_params.h", "common/big_integer.h", "common/blob.h", "common/object_base.h", diff --git a/common/src/asy_key_params.c b/common/src/asy_key_params.c index d7a7f1dbc8d611d5301278f67ca4e7ab84079e24..a7bc3591bf9083ac9c5557b5cd300031a39faaeb 100644 --- a/common/src/asy_key_params.c +++ b/common/src/asy_key_params.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Huawei Device Co., Ltd. + * Copyright (C) 2024 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 @@ -25,6 +25,7 @@ #include "detailed_ecc_key_params.h" #include "detailed_rsa_key_params.h" #include "detailed_alg_25519_key_params.h" +#include "sm2_crypt_params.h" #include "memory.h" #include "log.h" @@ -462,3 +463,17 @@ void FreeAsyKeySpec(HcfAsyKeyParamsSpec *spec) } } +void DestroySm2CipherTextSpec(Sm2CipherTextSpec *spec) +{ + if (spec == NULL) { + return; + } + HcfFree(spec->xCoordinate.data); + spec->xCoordinate.data = NULL; + HcfFree(spec->yCoordinate.data); + spec->yCoordinate.data = NULL; + HcfBlobDataFree(&(spec->cipherTextData)); + HcfBlobDataFree(&(spec->hashData)); + HcfFree(spec); +} + diff --git a/frameworks/crypto_operation/sm2_crypt_util.c b/frameworks/crypto_operation/sm2_crypt_util.c new file mode 100644 index 0000000000000000000000000000000000000000..78f65b83801280f334a2c51f4530677f880359be --- /dev/null +++ b/frameworks/crypto_operation/sm2_crypt_util.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2024 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_crypt_util.h" +#include +#include "cipher_sm2_crypt_util_openssl.h" +#include "log.h" +#include "memory.h" +#include "utils.h" + +typedef HcfResult (*HcfSm2SpecToASN1CreateFunc)(Sm2CipherTextSpec *spec, HcfBlob *output); + +typedef struct { + char *mode; + HcfSm2SpecToASN1CreateFunc createFunc; +} HcfSm2UtilAbility; + +static const HcfSm2UtilAbility CONVERT_ABILITY_SET[] = { + { "C1C3C2", HcfSm2ConstructToASN1 }, +}; + +static HcfSm2SpecToASN1CreateFunc FindAbility(const char *mode) +{ + // mode default C1C3C2 + if (HcfStrlen(mode) == 0) { + return CONVERT_ABILITY_SET[0].createFunc; + } + for (uint32_t i = 0; i < sizeof(CONVERT_ABILITY_SET) / sizeof(HcfSm2UtilAbility); i++) { + if (strcmp(mode, CONVERT_ABILITY_SET[i].mode) == 0) { + return CONVERT_ABILITY_SET[i].createFunc; + } + } + return NULL; +} + +static bool checkMode(const char *mode) +{ + if (HcfStrlen(mode) == 0) { + return true; + } + for (uint32_t i = 0; i < sizeof(CONVERT_ABILITY_SET) / sizeof(HcfSm2UtilAbility); i++) { + if (strcmp(mode, CONVERT_ABILITY_SET[i].mode) == 0) { + return true; + } + } + LOGE("Invalid param mode"); + return false; +} + +static bool checkSm2CipherTextSpec(Sm2CipherTextSpec *spec) +{ + if (spec == NULL) { + LOGE("Spec is null"); + return false; + } + if ((spec->xCoordinate.data == NULL) || (spec->xCoordinate.len == 0)) { + LOGE("Spec.xCoordinate is null"); + return false; + } + if ((spec->yCoordinate.data == NULL) || (spec->yCoordinate.len == 0)) { + LOGE("Spec.yCoordinate is null"); + return false; + } + if ((spec->hashData.data == NULL) || (spec->hashData.len == 0)) { + LOGE("Spec.hashData is null"); + return false; + } + if ((spec->cipherTextData.data == NULL) || (spec->cipherTextData.len == 0)) { + LOGE("Spec.cipherTextData is null"); + return false; + } + if (spec->hashData.len != HCF_SM2_C3_LEN) { + LOGE("Invalid param hashData"); + return false; + } + return true; +} + +HcfResult HcfGenCipherTextBySpec(Sm2CipherTextSpec *spec, const char *mode, HcfBlob *output) +{ + if (!checkMode(mode)) { + LOGE("Failed to check mode!"); + return HCF_INVALID_PARAMS; + } + if (output == NULL) { + LOGE("Failed to check output!"); + return HCF_INVALID_PARAMS; + } + if (!checkSm2CipherTextSpec(spec)) { + LOGE("Failed to check spec!"); + return HCF_INVALID_PARAMS; + } + HcfSm2SpecToASN1CreateFunc createFunc = FindAbility(mode); + HcfResult res = createFunc(spec, output); + if (res != HCF_SUCCESS) { + LOGE("Failed to convert construct to asn1!"); + } + return res; +} + +HcfResult HcfGetCipherTextSpec(const char *mode, HcfBlob *input, Sm2CipherTextSpec **returnSpc) +{ + if (!checkMode(mode)) { + LOGE("Failed to check mode!"); + return HCF_INVALID_PARAMS; + } + if (input == NULL) { + LOGE("Failed to check input!"); + return HCF_INVALID_PARAMS; + } + if (returnSpc == NULL) { + LOGE("Failed to check returnSpec!"); + return HCF_INVALID_PARAMS; + } + HcfResult res = HcfASN1ToSm2Construct(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 625e96ca4a61067b342e35b5fbdb15bd7e3371ec..362cd627421115847fba541a40ee915b76233adf 100644 --- a/frameworks/frameworks.gni +++ b/frameworks/frameworks.gni @@ -57,7 +57,9 @@ framework_md_files = [ "${framework_path}/crypto_operation/md.c" ] framework_kdf_files = [ "${framework_path}/crypto_operation/kdf.c" ] +framework_sm2_crypt_util_files = [ "${framework_path}/crypto_operation/sm2_crypt_util.c" ] + framework_files = framework_key_agreement_files + framework_signature_files + framework_cipher_files + framework_key_files + framework_mac_files + - framework_rand_files + framework_md_files + framework_kdf_files + framework_rand_files + framework_md_files + framework_kdf_files + framework_sm2_crypt_util_files diff --git a/frameworks/js/napi/crypto/BUILD.gn b/frameworks/js/napi/crypto/BUILD.gn index ac45bbf7717447c03fe10e79b9e8ebb1d0610406..f611a8f57d11fccc252963a82c847d90d3a5c60b 100644 --- a/frameworks/js/napi/crypto/BUILD.gn +++ b/frameworks/js/napi/crypto/BUILD.gn @@ -63,6 +63,7 @@ ohos_shared_library("cryptoframework_napi") { "src/napi_sym_key_generator.cpp", "src/napi_utils.cpp", "src/napi_verify.cpp", + "src/napi_sm2_crypt_util.cpp", ] deps = [ 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 bf209066c747171abfab270df4c2143cfb274364..94eb39bdb69072ecce9dc91dbb50b7166aa18ed0 100644 --- a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h +++ b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2022-2024 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 @@ -86,6 +86,13 @@ const std::string PBKDF2_PARAMS_ITER = "iterations"; const std::string PBKDF2_PARAMS_PASSWORD = "password"; const std::string PBKDF2_PARAMS_SALT = "salt"; const std::string PBKDF2_PARAMS_KEY_SIZE = "keySize"; + +const std::string SM2_UTIL_PARAM_X_COORDINATE = "xCoordinate"; +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"; + +#include } // namespace CryptoFramework } // namespace OHOS diff --git a/frameworks/js/napi/crypto/inc/napi_sm2_crypt_util.h b/frameworks/js/napi/crypto/inc/napi_sm2_crypt_util.h new file mode 100644 index 0000000000000000000000000000000000000000..46866293cb630a665537916df5298570c97e24dc --- /dev/null +++ b/frameworks/js/napi/crypto/inc/napi_sm2_crypt_util.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 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_CRYPT_UTIL_H +#define HCF_NAPI_SM2_CRYPT_UTIL_H + +#include + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "sm2_crypt_util.h" + +namespace OHOS { +namespace CryptoFramework { +class NapiSm2CryptUtil { +public: + explicit NapiSm2CryptUtil(); + ~NapiSm2CryptUtil(); + + static napi_value JsGenCipherTextBySpec(napi_env env, napi_callback_info info); + static napi_value JsGetCipherTextSpec(napi_env env, napi_callback_info info); + static napi_value Sm2CryptUtilConstructor(napi_env env, napi_callback_info info); + static napi_value Sm2CryptUtilConstructorClass(napi_env env); + static void DefineNapiSm2CryptUtilJSClass(napi_env env, napi_value exports); +}; +} // namespace CryptoFramework +} // namespace OHOS +#endif diff --git a/frameworks/js/napi/crypto/inc/napi_utils.h b/frameworks/js/napi/crypto/inc/napi_utils.h index 30c5632ae6863b6532eec852e5626afb3c28f36e..e3721df1ad1e11b3cacf30020733cd4f28abf3bb 100644 --- a/frameworks/js/napi/crypto/inc/napi_utils.h +++ b/frameworks/js/napi/crypto/inc/napi_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2022-2024 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 @@ -76,6 +76,9 @@ napi_value GenerateBusinessError(napi_env env, HcfResult errCode, const char *er int32_t GetAsyKeySpecType(AsyKeySpecItem targetItemType); int32_t GetSignSpecType(SignSpecItem targetItemType); int32_t GetCipherSpecType(CipherSpecItem targetItemType); + +napi_value GetDetailAsyKeySpecValue(napi_env env, napi_value arg, std::string argName); +bool GetBigIntFromNapiValue(napi_env env, napi_value arg, HcfBigInteger *bigInt); } // 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 e3a47f38ad18ab2b93341fe2e5d262e458d811e1..6f6a730affd34ad00da5ae4acd4065788e2ee203 100644 --- a/frameworks/js/napi/crypto/src/napi_init.cpp +++ b/frameworks/js/napi/crypto/src/napi_init.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2022-2024 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 @@ -26,6 +26,7 @@ #include "napi_pri_key.h" #include "napi_pub_key.h" #include "napi_sign.h" +#include "napi_sm2_crypt_util.h" #include "napi_verify.h" #include "napi_key_agreement.h" #include "napi_mac.h" @@ -231,6 +232,7 @@ static napi_value ModuleExport(napi_env env, napi_value exports) NapiKdf::DefineKdfJSClass(env, exports); NapiECCKeyUtil::DefineNapiECCKeyUtilJSClass(env, exports); NapiDHKeyUtil::DefineNapiDHKeyUtilJSClass(env, exports); + NapiSm2CryptUtil::DefineNapiSm2CryptUtilJSClass(env, exports); LOGD("module init end."); return exports; } diff --git a/frameworks/js/napi/crypto/src/napi_sm2_crypt_util.cpp b/frameworks/js/napi/crypto/src/napi_sm2_crypt_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9220e4c8d213ef9ab5738516e7ed5eaa16a1c18 --- /dev/null +++ b/frameworks/js/napi/crypto/src/napi_sm2_crypt_util.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2022-2024 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_crypt_util.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 { +NapiSm2CryptUtil::NapiSm2CryptUtil() {} +NapiSm2CryptUtil::~NapiSm2CryptUtil() {} + +static HcfBlob *GetBlobFromNapi(napi_env env, napi_value arg, const std::string &name) +{ + // get uint8Array attribute + napi_value data = nullptr; + napi_valuetype valueType = napi_undefined; + napi_status status = napi_get_named_property(env, arg, name.c_str(), &data); + napi_typeof(env, data, &valueType); + if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) { + LOGE("failed to get valid salt"); + return nullptr; + } + return GetBlobFromNapiUint8Arr(env, data); +} + +static bool GetSm2CipherTextSpecFromNapiValue(napi_env env, napi_value arg, Sm2CipherTextSpec **returnSpec) +{ + if ((env == nullptr) || (arg == nullptr) || (returnSpec == nullptr)) { + LOGE("Invalid params."); + return false; + } + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + if (tempSpec == nullptr) { + LOGE("Malloc failed!"); + return false; + } + napi_value xCoordinate = GetDetailAsyKeySpecValue(env, arg, SM2_UTIL_PARAM_X_COORDINATE); + napi_value yCoordinate = GetDetailAsyKeySpecValue(env, arg, SM2_UTIL_PARAM_Y_COORDINATE); + if ((xCoordinate == nullptr) || (yCoordinate == nullptr)) { + LOGE("Invalid params!"); + DestroySm2CipherTextSpec(tempSpec); + return false; + } + bool ret = GetBigIntFromNapiValue(env, xCoordinate, &tempSpec->xCoordinate); + if (!ret) { + LOGE("Failed to get valid x coordinate."); + DestroySm2CipherTextSpec(tempSpec); + return false; + } + ret = GetBigIntFromNapiValue(env, yCoordinate, &tempSpec->yCoordinate); + if (!ret) { + LOGE("Failed to get valid y coordinate."); + DestroySm2CipherTextSpec(tempSpec); + return false; + } + HcfBlob *cipherTextBlob = GetBlobFromNapi(env, arg, SM2_UTIL_PARAM_CIPHER_TEXT_DATA); + if (cipherTextBlob == nullptr) { + LOGE("Failed to get valid cipherTextData."); + DestroySm2CipherTextSpec(tempSpec); + return false; + } + HcfBlob *hashDataBlob = GetBlobFromNapi(env, arg, SM2_UTIL_PARAM_HASH_DATA); + if (hashDataBlob == nullptr) { + LOGE("Failed to get valid hashData."); + HcfBlobDataFree(cipherTextBlob); + HcfFree(cipherTextBlob); + DestroySm2CipherTextSpec(tempSpec); + return false; + } + tempSpec->cipherTextData = *cipherTextBlob; + tempSpec->hashData = *hashDataBlob; + *returnSpec = tempSpec; + HcfFree(cipherTextBlob); + HcfFree(hashDataBlob); + return true; +} + +static bool dealMode(napi_env env, napi_value arg, std::string &returnStr) +{ + napi_valuetype valueType; + napi_typeof(env, arg, &valueType); + if (valueType == napi_null) { + return true; + } + if (valueType == napi_undefined) { + return true; + } + if (!GetStringFromJSParams(env, arg, returnStr)) { + return false; + } + return true; +} + +napi_value NapiSm2CryptUtil::JsGenCipherTextBySpec(napi_env env, napi_callback_info info) +{ + size_t expectedArgc = PARAMS_NUM_TWO; + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + // second attribute mode can be null + if ((argc != expectedArgc) && (argc != (expectedArgc - 1))) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid.")); + LOGE("The input args num is invalid."); + return nullptr; + } + Sm2CipherTextSpec *spec = nullptr; + if (!GetSm2CipherTextSpecFromNapiValue(env, argv[0], &spec)) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get spec.")); + LOGE("Failed to get spec."); + return NapiGetNull(env); + } + std::string dataMode; + if (argc == expectedArgc) { + if (!dealMode(env, argv[1], dataMode)) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get mode.")); + LOGE("Failed to get mode."); + DestroySm2CipherTextSpec(spec); + return nullptr; + } + } + HcfBlob *output = static_cast(HcfMalloc(sizeof(HcfBlob), 0)); + if (output == NULL) { + napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "Failed to allocate memory.")); + LOGE("Failed to allocate HcfBlob memory!"); + DestroySm2CipherTextSpec(spec); + return NapiGetNull(env); + } + HcfResult res = HcfGenCipherTextBySpec(spec, dataMode.c_str(), output); + if (res != HCF_SUCCESS) { + napi_throw(env, GenerateBusinessError(env, res, "gen cipher text by spec fail.")); + LOGE("Gen cipher text by spec fail."); + HcfBlobDataFree(output); + HcfFree(output); + DestroySm2CipherTextSpec(spec); + return NapiGetNull(env); + } + napi_value instance = ConvertBlobToNapiValue(env, output); + HcfBlobDataFree(output); + HcfFree(output); + DestroySm2CipherTextSpec(spec); + return instance; +} + +static bool CheckSm2CipherTextSpec(Sm2CipherTextSpec *spec) +{ + if (spec->xCoordinate.data == nullptr || spec->xCoordinate.len == 0) { + LOGE("Invalid xCoordinate!"); + return false; + } + if (spec->yCoordinate.data == nullptr || spec->yCoordinate.len == 0) { + LOGE("Invalid yCoordinate!"); + return false; + } + if (spec->cipherTextData.data == nullptr || spec->cipherTextData.len == 0) { + LOGE("Invalid cipherTextData!"); + return false; + } + if (spec->hashData.data == nullptr || spec->hashData.len == 0) { + LOGE("Invalid hashData!"); + return false; + } + return true; +} + +static bool BuildBlobNapiValue(napi_env env, HcfBlob *blob, const char *name, napi_value *instance) +{ + napi_value napiData = ConvertCipherBlobToNapiValue(env, blob); + napi_status status = napi_set_named_property(env, *instance, name, napiData); + if (status != napi_ok) { + LOGE("Build blob[napi_value] failed!"); + return false; + } + return true; +} + +static bool BuildSm2CipherTextSpecToNapiValue(napi_env env, Sm2CipherTextSpec *spec, napi_value *instance) +{ + if (!BuildSetNamedProperty(env, &(spec->xCoordinate), SM2_UTIL_PARAM_X_COORDINATE.c_str(), instance)) { + LOGE("Build xCoordinate failed!"); + return false; + } + if (!BuildSetNamedProperty(env, &(spec->yCoordinate), SM2_UTIL_PARAM_Y_COORDINATE.c_str(), instance)) { + LOGE("Build yCoordinate failed!"); + return false; + } + if (!BuildBlobNapiValue(env, &(spec->cipherTextData), SM2_UTIL_PARAM_CIPHER_TEXT_DATA.c_str(), instance)) { + LOGE("Build cipherTextData failed!"); + return false; + } + if (!BuildBlobNapiValue(env, &(spec->hashData), SM2_UTIL_PARAM_HASH_DATA.c_str(), instance)) { + LOGE("Build hashData failed!"); + return false; + } + return true; +} + +napi_value ConvertSm2CipherTextSpecToNapiValue(napi_env env, Sm2CipherTextSpec *spec) +{ + if (!CheckSm2CipherTextSpec(spec)) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Invalid spec!")); + LOGE("Invalid spec!"); + return NapiGetNull(env); + } + napi_value instance; + napi_status status = napi_create_object(env, &instance); + if (status != napi_ok) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "create object failed!")); + LOGE("Create object failed!"); + return NapiGetNull(env); + } + if (!BuildSm2CipherTextSpecToNapiValue(env, spec, &instance)) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build object failed!")); + LOGE("Build object failed!"); + return NapiGetNull(env); + } + return instance; +} + +napi_value NapiSm2CryptUtil::JsGetCipherTextSpec(napi_env env, napi_callback_info info) +{ + size_t expectedArgc = PARAMS_NUM_TWO; + size_t argc = ARGS_SIZE_TWO; + napi_value argv[ARGS_SIZE_TWO] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + // second attribute mode can be null + if ((argc != expectedArgc) && (argc != (expectedArgc - 1))) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid.")); + LOGE("The input args num is invalid."); + return nullptr; + } + HcfBlob *cipherText = GetBlobFromNapiDataBlob(env, argv[0]); + if (cipherText == nullptr) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get cipherText.")); + LOGE("Failed to get cipherText."); + return NapiGetNull(env); + } + std::string dataMode; + if (argc == expectedArgc) { + if (!dealMode(env, argv[1], dataMode)) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get mode.")); + LOGE("Failed to get mode."); + HcfBlobDataFree(cipherText); + HcfFree(cipherText); + return nullptr; + } + } + Sm2CipherTextSpec *returnSpec = nullptr; + HcfResult res = HcfGetCipherTextSpec(dataMode.c_str(), cipherText, &returnSpec); + if (res != HCF_SUCCESS) { + napi_throw(env, GenerateBusinessError(env, res, "get cipher text spec fail.")); + LOGE("Get cipher text spec fail."); + HcfBlobDataFree(cipherText); + HcfFree(cipherText); + return NapiGetNull(env); + } + napi_value instance = ConvertSm2CipherTextSpecToNapiValue(env, returnSpec); + DestroySm2CipherTextSpec(returnSpec); + HcfBlobDataFree(cipherText); + HcfFree(cipherText); + return instance; +} + +napi_value NapiSm2CryptUtil::Sm2CryptUtilConstructor(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 NapiSm2CryptUtil::Sm2CryptUtilConstructorClass(napi_env env) +{ + napi_value cons = nullptr; + napi_property_descriptor clzDes[] = { + DECLARE_NAPI_STATIC_FUNCTION("genCipherTextBySpec", NapiSm2CryptUtil::JsGenCipherTextBySpec), + DECLARE_NAPI_STATIC_FUNCTION("getCipherTextSpec", NapiSm2CryptUtil::JsGetCipherTextSpec), + }; + NAPI_CALL(env, napi_define_class(env, "SM2CryptUtil", NAPI_AUTO_LENGTH, NapiSm2CryptUtil::Sm2CryptUtilConstructor, + nullptr, sizeof(clzDes) / sizeof(clzDes[0]), clzDes, &cons)); + return cons; +} + +void NapiSm2CryptUtil::DefineNapiSm2CryptUtilJSClass(napi_env env, napi_value exports) +{ + napi_set_named_property(env, exports, "SM2CryptUtil", NapiSm2CryptUtil::Sm2CryptUtilConstructorClass(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 a7bcd04e771df25397f5761cdfe6eafcb43e272f..75ac3c3e29dc27d6912d4ef2da331b6af868f9e1 100644 --- a/frameworks/js/napi/crypto/src/napi_utils.cpp +++ b/frameworks/js/napi/crypto/src/napi_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2022-2024 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 @@ -513,7 +513,7 @@ bool GetParamsSpecFromNapiValue(napi_env env, napi_value arg, HcfCryptoMode opMo } } -static napi_value GetDetailAsyKeySpecValue(napi_env env, napi_value arg, string argName) +napi_value GetDetailAsyKeySpecValue(napi_env env, napi_value arg, string argName) { napi_value data = nullptr; napi_valuetype valueType = napi_undefined; diff --git a/interfaces/innerkits/algorithm_parameter/sm2_crypt_params.h b/interfaces/innerkits/algorithm_parameter/sm2_crypt_params.h new file mode 100644 index 0000000000000000000000000000000000000000..65d815f917ef2f93a7d84d9936df1bf6046122e7 --- /dev/null +++ b/interfaces/innerkits/algorithm_parameter/sm2_crypt_params.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 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_CRYPT_PARAMS_H +#define HCF_SM2_CRYPT_PARAMS_H + +#include "big_integer.h" +#include "blob.h" + +typedef struct Sm2CipherTextSpec { + HcfBigInteger xCoordinate; + HcfBigInteger yCoordinate; + HcfBlob cipherTextData; + HcfBlob hashData; +} Sm2CipherTextSpec; + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t HCF_SM2_C3_LEN = 32; + +void DestroySm2CipherTextSpec(Sm2CipherTextSpec *spec); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/interfaces/innerkits/crypto_operation/sm2_crypt_util.h b/interfaces/innerkits/crypto_operation/sm2_crypt_util.h new file mode 100644 index 0000000000000000000000000000000000000000..4e1ddbb243d443d37299afe517833289003ccf5a --- /dev/null +++ b/interfaces/innerkits/crypto_operation/sm2_crypt_util.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 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_CRYPT_UTIL_H +#define HCF_SM2_CRYPT_UTIL_H + +#include "result.h" +#include "sm2_crypt_params.h" + +#ifdef __cplusplus +extern "C" { +#endif + +HcfResult HcfGenCipherTextBySpec(Sm2CipherTextSpec *spec, const char *mode, HcfBlob *output); +HcfResult HcfGetCipherTextSpec(const char *mode, HcfBlob *input, Sm2CipherTextSpec **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 feeeb5831706dde5f1df46943129e0a093d2e4e8..759a926ab9c5fb655bfed9b9639ef4677761e23d 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2022-2024 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 @@ -28,6 +28,9 @@ #include #include +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -314,6 +317,27 @@ int Openssl_DH_up_ref(DH *r); int Openssl_DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); int Openssl_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +// SM2 ASN1 +typedef struct SM2_Ciphertext_st SM2_Ciphertext; +DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext) + +struct SM2_Ciphertext_st { + BIGNUM *C1x; + BIGNUM *C1y; + ASN1_OCTET_STRING *C3; + ASN1_OCTET_STRING *C2; +}; + +void Openssl_SM2_Ciphertext_free(struct SM2_Ciphertext_st *sm2_ctext); +struct SM2_Ciphertext_st *Openssl_d2i_SM2_Ciphertext(const uint8_t *ciphertext, size_t ciphertext_len); +void Openssl_ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *field); +ASN1_OCTET_STRING *Openssl_ASN1_OCTET_STRING_new(void); +int Openssl_ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len); +struct SM2_Ciphertext_st *Openssl_SM2_Ciphertext_new(void); +int Openssl_i2d_SM2_Ciphertext(struct SM2_Ciphertext_st *sm2_ctext, unsigned char **returnData); +int Openssl_ASN1_STRING_length(ASN1_OCTET_STRING *p); +const unsigned char *Openssl_ASN1_STRING_get0_data(ASN1_OCTET_STRING *p); + #ifdef __cplusplus } #endif diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index b48c03e03c12b4cc5a2a009a7aaa0a3fef725c95..e892239984811c610942239501380a6a55963cba 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Huawei Device Co., Ltd. + * Copyright (C) 2022-2024 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 @@ -18,6 +18,15 @@ #include "log.h" #include "result.h" +ASN1_SEQUENCE(SM2_Ciphertext) = { + ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM), + ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM), + ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(SM2_Ciphertext) + +IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) + BIGNUM *Openssl_BN_dup(const BIGNUM *a) { return BN_dup(a); @@ -1292,4 +1301,54 @@ int Openssl_DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) int Openssl_DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) { return DH_set0_key(dh, pub_key, priv_key); -} \ No newline at end of file +} + +struct SM2_Ciphertext_st *Openssl_d2i_SM2_Ciphertext(const uint8_t *ciphertext, size_t ciphertext_len) +{ + return d2i_SM2_Ciphertext(NULL, &ciphertext, ciphertext_len); +} + +void Openssl_SM2_Ciphertext_free(struct SM2_Ciphertext_st *sm2_ctext) +{ + if (sm2_ctext != NULL) { + SM2_Ciphertext_free(sm2_ctext); + } +} + +void Openssl_ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *field) +{ + if (field != NULL) { + ASN1_OCTET_STRING_free(field); + } +} + +ASN1_OCTET_STRING *Openssl_ASN1_OCTET_STRING_new(void) +{ + return ASN1_OCTET_STRING_new(); +} + +int Openssl_ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len) +{ + return ASN1_STRING_set(x, d, len); +} + +struct SM2_Ciphertext_st *Openssl_SM2_Ciphertext_new(void) +{ + return SM2_Ciphertext_new(); +} + +int Openssl_i2d_SM2_Ciphertext(struct SM2_Ciphertext_st *sm2_ctext, unsigned char **returnData) +{ + return i2d_SM2_Ciphertext(sm2_ctext, returnData); +} + +int Openssl_ASN1_STRING_length(ASN1_OCTET_STRING *p) +{ + return ASN1_STRING_length(p); +} + +const unsigned char *Openssl_ASN1_STRING_get0_data(ASN1_OCTET_STRING *p) +{ + return ASN1_STRING_get0_data(p); +} + diff --git a/plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_crypt_util_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_crypt_util_openssl.h new file mode 100644 index 0000000000000000000000000000000000000000..4463933c08ff043e482d335246b43a20e759ff2f --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/inc/cipher_sm2_crypt_util_openssl.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 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_CRYPT_UTIL_OPENSSL_H +#define HCF_CIPHER_SM2_CRYPT_UTIL_OPENSSL_H + +#include "sm2_crypt_params.h" +#include "result.h" + +#ifdef __cplusplus +extern "C" { +#endif + +HcfResult HcfSm2ConstructToASN1(Sm2CipherTextSpec *spec, HcfBlob *output); +HcfResult HcfASN1ToSm2Construct(HcfBlob *input, Sm2CipherTextSpec **returnSpec); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_crypt_util_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_crypt_util_openssl.c new file mode 100644 index 0000000000000000000000000000000000000000..fcc6599357432011cc335b8a54b46b2ac7a8a5c0 --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_crypt_util_openssl.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2024 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_crypt_util_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 Sm2CipherTextSpec *spec, struct SM2_Ciphertext_st *sm2_ctext) +{ + if (BigIntegerToBigNum(&(spec->xCoordinate), &(sm2_ctext->C1x)) != HCF_SUCCESS) { + LOGE("Build x failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + if (BigIntegerToBigNum(&(spec->yCoordinate), &(sm2_ctext->C1y)) != HCF_SUCCESS) { + LOGE("Build y failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + sm2_ctext->C3 = Openssl_ASN1_OCTET_STRING_new(); + sm2_ctext->C2 = Openssl_ASN1_OCTET_STRING_new(); + if (sm2_ctext->C3 == NULL || sm2_ctext->C2 == NULL) { + LOGE("SM2 openssl [ASN1_OCTET_STRING_new] C3 C2 fail"); + HcfPrintOpensslError(); + return HCF_ERR_CRYPTO_OPERATION; + } + if (Openssl_ASN1_OCTET_STRING_set(sm2_ctext->C3, spec->hashData.data, HCF_SM2_C3_LEN) != HCF_OPENSSL_SUCCESS) { + LOGE("SM2 openssl [ASN1_OCTET_STRING_set] c3 error"); + HcfPrintOpensslError(); + return HCF_ERR_CRYPTO_OPERATION; + } + if (Openssl_ASN1_OCTET_STRING_set(sm2_ctext->C2, spec->cipherTextData.data, spec->cipherTextData.len) != HCF_OPENSSL_SUCCESS) { + LOGE("SM2 openssl [ASN1_OCTET_STRING_set] c2 error"); + HcfPrintOpensslError(); + return HCF_ERR_CRYPTO_OPERATION; + } + return HCF_SUCCESS; +} + +HcfResult HcfSm2ConstructToASN1(Sm2CipherTextSpec *spec, HcfBlob *output) +{ + struct SM2_Ciphertext_st *sm2_ctext = Openssl_SM2_Ciphertext_new(); + if (sm2_ctext == NULL) { + LOGE("SM2 openssl [SM2_Ciphertext_new] failed"); + HcfPrintOpensslError(); + return HCF_ERR_CRYPTO_OPERATION; + } + HcfResult res = BuildSM2Ciphertext(spec, sm2_ctext); + if (res != HCF_SUCCESS) { + Openssl_SM2_Ciphertext_free(sm2_ctext); + LOGE("SM2 build SM2Ciphertext fail"); + return res; + } + unsigned char *returnData = NULL; + size_t returnDataLen = Openssl_i2d_SM2_Ciphertext(sm2_ctext, &returnData); + if (returnDataLen < 0) { + LOGE("SM2 openssl [i2d_SM2_Ciphertext] error"); + HcfPrintOpensslError(); + Openssl_SM2_Ciphertext_free(sm2_ctext); + return HCF_ERR_CRYPTO_OPERATION; + } + output->data = returnData; + output->len = returnDataLen; + Openssl_SM2_Ciphertext_free(sm2_ctext); + return HCF_SUCCESS; +} + +static HcfResult BuildSm2CipherTextSpec(Sm2CipherTextSpec *tempSpec, struct SM2_Ciphertext_st *sm2_ctext) +{ + if (BigNumToBigInteger(sm2_ctext->C1x, &(tempSpec->xCoordinate)) != HCF_SUCCESS) { + LOGE("BigNumToBigInteger xCoordinate failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + if (BigNumToBigInteger(sm2_ctext->C1y, &(tempSpec->yCoordinate)) != HCF_SUCCESS) { + LOGE("BigNumToBigInteger yCoordinate failed."); + return HCF_ERR_CRYPTO_OPERATION; + } + const unsigned char *c2Data = Openssl_ASN1_STRING_get0_data(sm2_ctext->C2); + int c2Len = Openssl_ASN1_STRING_length(sm2_ctext->C2); + if (c2Data == NULL) { + LOGE("SM2 openssl [Openssl_ASN1_STRING_get0_data] error."); + return HCF_ERR_CRYPTO_OPERATION; + } + const unsigned char *c3Data = Openssl_ASN1_STRING_get0_data(sm2_ctext->C3); + int c3Len = Openssl_ASN1_STRING_length(sm2_ctext->C3); + if (c3Data == NULL) { + LOGE("SM2 openssl [Openssl_ASN1_STRING_get0_data] error."); + // const c2Data can free? + return HCF_ERR_CRYPTO_OPERATION; + } + + tempSpec->cipherTextData.data = (unsigned char *)HcfMalloc(c2Len, 0); + if (tempSpec->cipherTextData.data == NULL) { + LOGE("Failed to allocate cipherTextData.data memory"); + return HCF_ERR_MALLOC; + } + tempSpec->hashData.data = (unsigned char *)HcfMalloc(c3Len, 0); + if (tempSpec->hashData.data == NULL) { + LOGE("Failed to allocate hashData.data memory"); + HcfFree(tempSpec->cipherTextData.data); + tempSpec->cipherTextData.data = NULL; + return HCF_ERR_MALLOC; + } + (void)memcpy_s(tempSpec->cipherTextData.data, c2Len, c2Data, c2Len); + (void)memcpy_s(tempSpec->hashData.data, c3Len, c3Data, c3Len); + tempSpec->cipherTextData.len = c2Len; + tempSpec->hashData.len = c3Len; + return HCF_SUCCESS; +} + +HcfResult HcfASN1ToSm2Construct(HcfBlob *input, Sm2CipherTextSpec **returnSpec) +{ + struct SM2_Ciphertext_st *sm2_ctext = Openssl_d2i_SM2_Ciphertext(input->data, input->len); + if (sm2_ctext == NULL) { + LOGE("SM2 openssl [d2i_SM2_Ciphertext] error"); + return HCF_ERR_CRYPTO_OPERATION; + } + Sm2CipherTextSpec *tempSpec = (Sm2CipherTextSpec *)(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + if (tempSpec == NULL) { + LOGE("Failed to allocate Sm2CipherTextSpec memory"); + Openssl_SM2_Ciphertext_free(sm2_ctext); + return HCF_ERR_MALLOC; + } + HcfResult res = BuildSm2CipherTextSpec(tempSpec, sm2_ctext); + if (res != HCF_SUCCESS) { + LOGE("SM2 build SM2Ciphertext fail"); + HcfFree(tempSpec); + Openssl_SM2_Ciphertext_free(sm2_ctext); + return res; + } + *returnSpec = tempSpec; + Openssl_SM2_Ciphertext_free(sm2_ctext); + return HCF_SUCCESS; +} \ No newline at end of file diff --git a/plugin/plugin.gni b/plugin/plugin.gni index 4ed4b8da42e1b783ba2b0a1dfe34cc1e18da0836..733f9b1538dfcd864b302551aee1dbc25a5a2f13 100644 --- a/plugin/plugin.gni +++ b/plugin/plugin.gni @@ -75,6 +75,7 @@ plugin_cipher_files = [ "${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_crypt_util_openssl.c", ] plugin_hmac_files = diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index ddcfd68a7ebe412ff6a1088edbfa26f3c48555d0..769b25388ec2fad10726f5bde33d32ec221fa899 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -112,6 +112,7 @@ ohos_unittest("crypto_framework_test") { "src/ecc/crypto_ecc_verify_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_crypt_util_test.cpp", ] sources += framework_files + plugin_files diff --git a/test/unittest/src/ecc/ecc_asy_key_common.cpp b/test/unittest/src/ecc/ecc_asy_key_common.cpp index 9b104fcc75534ca05358bf7bde5fe97b0ed4ea4d..5abf90631f4abe5da2e092d1478b58627e908709 100644 --- a/test/unittest/src/ecc/ecc_asy_key_common.cpp +++ b/test/unittest/src/ecc/ecc_asy_key_common.cpp @@ -16,7 +16,6 @@ #include #include "securec.h" - #include "asy_key_generator.h" #include "detailed_ecc_key_params.h" #include "ecc_asy_key_common.h" diff --git a/test/unittest/src/sm2/crypto_sm2_crypt_util_test.cpp b/test/unittest/src/sm2/crypto_sm2_crypt_util_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef515550a038f9b5e302bb5038494452c5ce8873 --- /dev/null +++ b/test/unittest/src/sm2/crypto_sm2_crypt_util_test.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2024 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 "sm2_crypt_util.h" +#include "log.h" +#include "memory.h" +#include "cstring" + +using namespace std; +using namespace testing::ext; + +namespace { +class CryptoSm2CryptUtilTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void CryptoSm2CryptUtilTest::SetUp() {} +void CryptoSm2CryptUtilTest::TearDown() {} +void CryptoSm2CryptUtilTest::SetUpTestCase(){} +void CryptoSm2CryptUtilTest::TearDownTestCase(){} + +static const char *g_sm2ModeC1C3C2 = "C1C3C2"; +static const char *g_sm2ModeError = "C1C2C2"; +static const int CORRECT_INPUT_LEN = 121; +static const int ERROR_INPUT_LEN = 12; +static uint8_t g_mockCorrectInput[CORRECT_INPUT_LEN] = { + 48,119,2,33,0,183,70,70,149,188,64,6,110,236,85,149,216,224,102,95,92,41,105,232,5,248,122,21,174,43,226,221,104,82,88,153,45,2,32,96,229,78,209,233,110,5,149,91,110,109,181,17,75,109,146,128,170,113,205,158,193,156,90,110,40,18,119,247,198,93,107,4,32,87,167,167,247,88,146,203,234,83,126,117,129,52,142,82,54,152,226,201,111,143,115,169,125,128,42,157,31,114,198,109,244,4,14,100,227,78,195,249,179,43,70,242,69,169,10,65,123}; +static HcfBlob g_correctInput = { + .data = g_mockCorrectInput, + .len = CORRECT_INPUT_LEN + }; +static HcfBlob g_errorInput = { + .data = g_mockCorrectInput, + .len = ERROR_INPUT_LEN + }; +static unsigned char c1x[] = { + 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 + }; +static unsigned char c1y[] = { + 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 c3[] = { + 87,167,167,247,88,146,203,234,83,126,117,129,52,142,82,54,152,226,201,111,143,115,169,125,128,42,157,31,114,198,109,244 + }; +static unsigned char c2[] = { + 100,227,78,195,249,179,43,70,242,69,169,10,65,123 + }; + +HcfResult ConstructCorrectSm2CipherTextSpec(Sm2CipherTextSpec **spec) +{ + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + tempSpec->xCoordinate.data = c1x; + tempSpec->xCoordinate.len = 32; + tempSpec->yCoordinate.data = c1y; + tempSpec->yCoordinate.len = 32; + tempSpec->cipherTextData.data = c2; + tempSpec->cipherTextData.len = 14; + tempSpec->hashData.data = c3; + tempSpec->hashData.len = 32; + *spec = tempSpec; + return HCF_SUCCESS; +} + +HcfResult ConstructMissYErrorSm2CipherTextSpec(Sm2CipherTextSpec **spec) +{ + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + tempSpec->xCoordinate.data = c1x; + tempSpec->xCoordinate.len = 32; + tempSpec->cipherTextData.data = c2; + tempSpec->cipherTextData.len = 14; + tempSpec->hashData.data = c3; + tempSpec->hashData.len = 32; + *spec = tempSpec; + return HCF_SUCCESS; +} + +HcfResult ConstructMissXErrorSm2CipherTextSpec(Sm2CipherTextSpec **spec) +{ + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + tempSpec->yCoordinate.data = c1y; + tempSpec->yCoordinate.len = 32; + tempSpec->cipherTextData.data = c2; + tempSpec->cipherTextData.len = 14; + tempSpec->hashData.data = c3; + tempSpec->hashData.len = 32; + *spec = tempSpec; + return HCF_SUCCESS; +} + +HcfResult ConstructMissHashDataErrorSm2CipherTextSpec(Sm2CipherTextSpec **spec) +{ + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + tempSpec->xCoordinate.data = c1x; + tempSpec->xCoordinate.len = 32; + tempSpec->yCoordinate.data = c1y; + tempSpec->yCoordinate.len = 32; + tempSpec->cipherTextData.data = c2; + tempSpec->cipherTextData.len = 14; + *spec = tempSpec; + return HCF_SUCCESS; +} + +HcfResult ConstructMissCipherDataErrorSm2CipherTextSpec(Sm2CipherTextSpec **spec) +{ + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + tempSpec->xCoordinate.data = c1x; + tempSpec->xCoordinate.len = 32; + tempSpec->yCoordinate.data = c1y; + tempSpec->yCoordinate.len = 32; + tempSpec->hashData.data = c3; + tempSpec->hashData.len = 32; + *spec = tempSpec; + return HCF_SUCCESS; +} + +HcfResult ConstructLenErrorSm2CipherTextSpec(Sm2CipherTextSpec **spec) +{ + // hashData.len != 32 + Sm2CipherTextSpec *tempSpec = static_cast(HcfMalloc(sizeof(Sm2CipherTextSpec), 0)); + tempSpec->xCoordinate.data = c1x; + tempSpec->xCoordinate.len = 32; + tempSpec->yCoordinate.data = c1y; + tempSpec->yCoordinate.len = 32; + tempSpec->hashData.data = c3; + tempSpec->hashData.len = 15; + tempSpec->cipherTextData.data = c2; + tempSpec->cipherTextData.len = 14; + *spec = tempSpec; + return HCF_SUCCESS; +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest001, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec success, case mode = C1C3C2 + int res = 0; + Sm2CipherTextSpec *spec = nullptr; + res = ConstructCorrectSm2CipherTextSpec(&spec); + EXPECT_EQ(res, HCF_SUCCESS); + HcfBlob output = { .data = nullptr, .len = 0 }; + res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_SUCCESS); + res = memcmp(output.data, g_correctInput.data, g_correctInput.len); + HcfBlobDataFree(&output); + HcfFree(spec); + EXPECT_EQ(res, 0); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest002, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec success, case mode = null + int res = 0; + Sm2CipherTextSpec *spec = nullptr; + ConstructCorrectSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + res = HcfGenCipherTextBySpec(spec, NULL, &output); + EXPECT_EQ(res, HCF_SUCCESS); + res = memcmp(output.data, g_correctInput.data, g_correctInput.len); + HcfBlobDataFree(&output); + HcfFree(spec); + EXPECT_EQ(res, 0); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest003, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case mode = C1C2C2 + Sm2CipherTextSpec *spec = nullptr; + ConstructCorrectSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeError, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest004, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case spec miss yCoordinate + Sm2CipherTextSpec *spec = nullptr; + ConstructMissYErrorSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest005, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case spec hashData.len != 32 + Sm2CipherTextSpec *spec = nullptr; + ConstructLenErrorSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest006, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case spec miss xCoordinate + Sm2CipherTextSpec *spec = nullptr; + ConstructMissXErrorSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); + +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest007, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case spec miss hashData + Sm2CipherTextSpec *spec = nullptr; + ConstructMissHashDataErrorSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest008, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case spec miss cipherData + Sm2CipherTextSpec *spec = nullptr; + ConstructMissCipherDataErrorSm2CipherTextSpec(&spec); + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest009, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case output is null + Sm2CipherTextSpec *spec = nullptr; + ConstructCorrectSm2CipherTextSpec(&spec); + HcfResult res = HcfGenCipherTextBySpec(spec, g_sm2ModeC1C3C2, NULL); + EXPECT_EQ(res, HCF_INVALID_PARAMS); + HcfFree(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest010, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case spec is null + HcfBlob output = { .data = nullptr, .len = 0 }; + HcfResult res = HcfGenCipherTextBySpec(nullptr, g_sm2ModeC1C3C2, &output); + EXPECT_EQ(res, HCF_INVALID_PARAMS); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest101, TestSize.Level0) +{ + // test HcfGetCipherTextSpec success, case mode = C1C3C2 + Sm2CipherTextSpec *spec = nullptr; + HcfResult res = HcfGetCipherTextSpec(g_sm2ModeC1C3C2, &g_correctInput, &spec); + EXPECT_EQ(res, HCF_SUCCESS); + DestroySm2CipherTextSpec(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest102, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec success, case mode = null + Sm2CipherTextSpec *spec = nullptr; + HcfResult res = HcfGetCipherTextSpec(NULL, &g_correctInput, &spec); + EXPECT_EQ(res, HCF_SUCCESS); + DestroySm2CipherTextSpec(spec); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest103, TestSize.Level0) +{ + // test HcfGenCipherTextBySpec error, case mode = C1C2C2 + Sm2CipherTextSpec *spec = nullptr; + HcfResult res = HcfGetCipherTextSpec(g_sm2ModeError, &g_correctInput, &spec); + EXPECT_EQ(res, HCF_INVALID_PARAMS); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest104, TestSize.Level0) +{ + // test HcfGetCipherTextSpec error, case input null + Sm2CipherTextSpec *spec = nullptr; + HcfResult res = HcfGetCipherTextSpec(g_sm2ModeC1C3C2, NULL, &spec); + EXPECT_EQ(res, HCF_INVALID_PARAMS); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest105, TestSize.Level0) +{ + // test HcfGetCipherTextSpec error, case input error len + Sm2CipherTextSpec *spec = nullptr; + HcfResult res = HcfGetCipherTextSpec(g_sm2ModeC1C3C2, &g_errorInput, &spec); + EXPECT_EQ(res, HCF_ERR_CRYPTO_OPERATION); +} + +HWTEST_F(CryptoSm2CryptUtilTest, CryptoSm2CryptUtilTest106, TestSize.Level0) +{ + // test HcfGetCipherTextSpec error, case returnSpec is null + HcfResult res = HcfGetCipherTextSpec(g_sm2ModeC1C3C2, &g_correctInput, NULL); + EXPECT_EQ(res, HCF_INVALID_PARAMS); +} +} + +