diff --git a/common/inc/params_parser.h b/common/inc/params_parser.h index ce89d46eb469f24af9da80ee847c960295636eb7..6e333c6aa865f45cbf56d984d331f0b0ab7b5053 100644 --- a/common/inc/params_parser.h +++ b/common/inc/params_parser.h @@ -46,6 +46,7 @@ typedef enum { HCF_ALG_ED25519, HCF_ALG_X25519, HCF_ALG_DH, + HCF_ALG_HKDF, } HcfAlgValue; typedef enum { @@ -170,6 +171,13 @@ typedef enum { HCF_ALG_ONLY_SIGN, HCF_ALG_VERIFY_RECOVER, + // key derivation function, HKDF + HCF_ALG_HKDF_DEFAULT, + + // hkdf mode + HCF_ALG_MODE_EXTRACT_AND_EXPAND, + HCF_ALG_MODE_EXTRACT_ONLY, + HCF_ALG_MODE_EXPAND_ONLY, } HcfAlgParaValue; typedef enum { @@ -233,6 +241,7 @@ typedef struct { typedef struct { HcfAlgValue algo; // algType HcfAlgParaValue md; + HcfAlgParaValue mode; } HcfKdfDeriveParams; typedef HcfResult (*SetParameterFunc) (const HcfParaConfig* config, void *params); diff --git a/common/src/params_parser.c b/common/src/params_parser.c index 3f34c58ef42aac66b44a27ccedd26e00db1132b6..bccee488b4fca43c4e85e32510558cf9e45327bb 100644 --- a/common/src/params_parser.c +++ b/common/src/params_parser.c @@ -110,6 +110,10 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"3DES", HCF_ALG_TYPE, HCF_ALG_3DES_DEFAULT}, {"HMAC", HCF_ALG_TYPE, HCF_ALG_HMAC_DEFAULT}, {"PBKDF2", HCF_ALG_TYPE, HCF_ALG_PBKDF2_DEFAULT}, + {"HKDF", HCF_ALG_TYPE, HCF_ALG_HKDF_DEFAULT}, + {"EXTRACT_AND_EXPAND", HCF_ALG_MODE, HCF_ALG_MODE_EXTRACT_AND_EXPAND}, + {"EXTRACT_ONLY", HCF_ALG_MODE, HCF_ALG_MODE_EXTRACT_ONLY}, + {"EXPAND_ONLY", HCF_ALG_MODE, HCF_ALG_MODE_EXPAND_ONLY}, {"ECC_BP", HCF_ALG_TYPE, HCF_ALG_ECC_BRAINPOOL_DEFAULT}, {"X25519_BP", HCF_ALG_TYPE, HCF_ALG_X25519_DEFAULT}, {"DH", HCF_ALG_TYPE, HCF_ALG_DH_DEFAULT}, diff --git a/frameworks/crypto_operation/kdf.c b/frameworks/crypto_operation/kdf.c index fe95cf5f1dfd2be01f585c4132af762a3fdefbf3..b6fe9b28f1ec98d95acc6a9232434bdaebbf17fa 100644 --- a/frameworks/crypto_operation/kdf.c +++ b/frameworks/crypto_operation/kdf.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 @@ -23,6 +23,7 @@ #include "log.h" #include "params_parser.h" #include "pbkdf2_openssl.h" +#include "hkdf_openssl.h" #include "utils.h" typedef HcfResult (*HcfKdfSpiCreateFunc)(HcfKdfDeriveParams *, HcfKdfSpi **); @@ -44,6 +45,9 @@ static void SetKdfType(HcfAlgParaValue value, HcfKdfDeriveParams *kdf) case HCF_ALG_PBKDF2_DEFAULT: kdf->algo = HCF_ALG_PKBDF2; break; + case HCF_ALG_HKDF_DEFAULT: + kdf->algo = HCF_ALG_HKDF; + break; default: LOGE("Invalid algo %u.", value); break; @@ -55,6 +59,11 @@ static void SetDigest(HcfAlgParaValue value, HcfKdfDeriveParams *kdf) kdf->md = value; } +static void SetMode(HcfAlgParaValue value, HcfKdfDeriveParams *kdf) +{ + kdf->mode = value; +} + static HcfResult ParseKdfParams(const HcfParaConfig *config, void *params) { if (config == NULL || params == NULL) { @@ -71,6 +80,9 @@ static HcfResult ParseKdfParams(const HcfParaConfig *config, void *params) case HCF_ALG_DIGEST: SetDigest(config->paraValue, paramsObj); break; + case HCF_ALG_MODE: + SetMode(config->paraValue, paramsObj); + break; default: ret = HCF_INVALID_PARAMS; break; @@ -80,6 +92,7 @@ static HcfResult ParseKdfParams(const HcfParaConfig *config, void *params) static const HcfKdfGenAbility KDF_ABILITY_SET[] = { { HCF_ALG_PKBDF2, HcfKdfPBKDF2SpiCreate }, + { HCF_ALG_HKDF, HcfKdfHkdfSpiCreate}, }; static HcfKdfSpiCreateFunc FindAbility(HcfKdfDeriveParams* params) 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 56df3700f1b372a9b127d13ca3986cbbd8bb9dcf..ca0a427be831af9126b07c5b5fef737096a56aac 100644 --- a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h +++ b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h @@ -84,13 +84,19 @@ const std::string RSA_KEYPAIR_ASY_KEY_SPEC = "RsaKeyPairParamsSpec"; const std::string PBKDF2_ALG_NAME = "PBKDF2"; 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"; + +const std::string KDF_PARAMS_SALT = "salt"; +const std::string KDF_PARAMS_KEY_SIZE = "keySize"; + +const std::string HKDF_ALG_NAME = "HKDF"; +const std::string HKDF_PARAMS_KEY = "key"; +const std::string HKDF_PARAMS_INFO = "info"; + } // namespace CryptoFramework } // namespace OHOS diff --git a/frameworks/js/napi/crypto/src/napi_kdf.cpp b/frameworks/js/napi/crypto/src/napi_kdf.cpp index 2d1626cd9146eb18d4b8d7e494aa9d72eb4c104c..d15fd273a5eca777d91e6d29396bba0955b2a199 100644 --- a/frameworks/js/napi/crypto/src/napi_kdf.cpp +++ b/frameworks/js/napi/crypto/src/napi_kdf.cpp @@ -21,6 +21,7 @@ #include "napi_utils.h" #include "napi_crypto_framework_defines.h" #include "detailed_pbkdf2_params.h" +#include "detailed_hkdf_params.h" #define PBKDF2_ALG_SIZE 6 @@ -125,7 +126,11 @@ static void KdfGenSecretComplete(napi_env env, napi_status status, void *data) if (PBKDF2_ALG_NAME.compare(context->paramsSpec->algName) == 0) { HcfPBKDF2ParamsSpec *params = reinterpret_cast(context->paramsSpec); returnBlob = ConvertBlobToNapiValue(env, &(params->output)); + } else if (HKDF_ALG_NAME.compare(context->paramsSpec->algName) == 0) { + HcfHkdfParamsSpec *params = reinterpret_cast(context->paramsSpec); + returnBlob = ConvertBlobToNapiValue(env, &(params->output)); } + if (returnBlob == nullptr) { LOGE("returnOutBlob is nullptr!"); returnBlob = NapiGetNull(env); @@ -138,7 +143,7 @@ static void KdfGenSecretComplete(napi_env env, napi_status status, void *data) FreeCryptoFwkCtx(env, context); } -static bool GetInt32FromPBKDF2Params(napi_env env, napi_value arg, const std::string &name, int32_t &retInt) +static bool GetInt32FromKdfParams(napi_env env, napi_value arg, const std::string &name, int32_t &retInt) { // int attribute napi_value dataInt = nullptr; @@ -190,7 +195,7 @@ static bool GetCharArrayFromUint8Arr(napi_env env, napi_value data, HcfBlob *ret return true; } -static bool GetCharArrayFromJsString(napi_env env, napi_value arg, HcfBlob *retPassword) +static bool GetCharArrayFromJsString(napi_env env, napi_value arg, HcfBlob *retBlob) { size_t length = 0; if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) { @@ -215,12 +220,12 @@ static bool GetCharArrayFromJsString(napi_env env, napi_value arg, HcfBlob *retP HcfFree(tmpPassword); return false; } - retPassword->data = reinterpret_cast(tmpPassword); - retPassword->len = length; + retBlob->data = reinterpret_cast(tmpPassword); + retBlob->len = length; return true; } -static bool GetPasswordFromPBKDF2Params(napi_env env, napi_value arg, const std::string &name, HcfBlob *retPassword) +static bool GetKeyOrPwdFromKdfParams(napi_env env, napi_value arg, const std::string &name, HcfBlob *retBlob) { napi_value data = nullptr; napi_valuetype valueType = napi_undefined; @@ -231,12 +236,12 @@ static bool GetPasswordFromPBKDF2Params(napi_env env, napi_value arg, const std: return false; } if (valueType == napi_string) { - if (GetCharArrayFromJsString(env, data, retPassword) != true) { + if (GetCharArrayFromJsString(env, data, retBlob) != true) { LOGE("get char string failed"); return false; } } else { - if (GetCharArrayFromUint8Arr(env, data, retPassword) != true) { + if (GetCharArrayFromUint8Arr(env, data, retBlob) != true) { LOGE("get uint8arr failed"); return false; } @@ -244,7 +249,7 @@ static bool GetPasswordFromPBKDF2Params(napi_env env, napi_value arg, const std: return true; } -static HcfBlob *GetBlobFromPBKDF2ParamsSpec(napi_env env, napi_value arg, const std::string &name) +static HcfBlob *GetBlobFromKdfParamsSpec(napi_env env, napi_value arg, const std::string &name) { // get uint8Array attribute napi_value data = nullptr; @@ -270,14 +275,24 @@ static void SetPBKDF2ParamsSpecAttribute(int iter, const HcfBlob &out, HcfBlob * tmp->base.algName = PBKDF2_ALG_NAME.c_str(); } +static void SetHkdfParamsSpecAttribute(const HcfBlob &out, HcfBlob *salt, const HcfBlob &key, HcfBlob *info, + HcfHkdfParamsSpec *tmpParams) +{ + tmpParams->output = out; + tmpParams->salt = *salt; + tmpParams->key = key; + tmpParams->info = *info; + tmpParams->base.algName = HKDF_ALG_NAME.c_str(); +} + static bool GetPBKDF2ParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **params) { // get attribute from params // int attribute int iter = -1; int keySize = -1; - if (!GetInt32FromPBKDF2Params(env, arg, PBKDF2_PARAMS_ITER, iter) || - !GetInt32FromPBKDF2Params(env, arg, PBKDF2_PARAMS_KEY_SIZE, keySize)) { + if (!GetInt32FromKdfParams(env, arg, PBKDF2_PARAMS_ITER, iter) || + !GetInt32FromKdfParams(env, arg, KDF_PARAMS_KEY_SIZE, keySize)) { LOGE("failed to get valid num"); return false; } @@ -295,12 +310,12 @@ static bool GetPBKDF2ParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec * HcfPBKDF2ParamsSpec *tmp = nullptr; do { // get password - if (!GetPasswordFromPBKDF2Params(env, arg, PBKDF2_PARAMS_PASSWORD, &tmpPassword)) { + if (!GetKeyOrPwdFromKdfParams(env, arg, PBKDF2_PARAMS_PASSWORD, &tmpPassword)) { LOGE("failed to get password"); break; } // get salt attribute - salt = GetBlobFromPBKDF2ParamsSpec(env, arg, PBKDF2_PARAMS_SALT); + salt = GetBlobFromKdfParamsSpec(env, arg, KDF_PARAMS_SALT); if (salt == nullptr) { LOGE("fail to get salt"); break; @@ -324,6 +339,64 @@ static bool GetPBKDF2ParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec * return false; } +static bool GetHkdfParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **params) +{ + int keySize = -1; + if (!GetInt32FromKdfParams(env, arg, KDF_PARAMS_KEY_SIZE, keySize)) { + LOGE("failed to get valid num"); + return false; + } + if (keySize <= 0) { + LOGE("iter and keySize should larger than 0"); + return false; + } + HcfBlob out = { .data = static_cast(HcfMalloc(keySize, 0)), .len = keySize }; + if (out.data == nullptr) { + LOGE("output malloc failed!"); + return false; + } + + HcfBlob *salt = nullptr; + HcfBlob key = { .data = nullptr, .len = 0 }; + HcfBlob *info = nullptr; + HcfHkdfParamsSpec *tmpParams = nullptr; + do { + // get key + if (!GetKeyOrPwdFromKdfParams(env, arg, HKDF_PARAMS_KEY, &key)) { + LOGE("failed to get key"); + break; + } + + // get info态salt + info = GetBlobFromKdfParamsSpec(env, arg, HKDF_PARAMS_INFO); + salt = GetBlobFromKdfParamsSpec(env, arg, KDF_PARAMS_SALT); + if (info == nullptr or salt == nullptr) { + LOGE("fail to get info or salt"); + break; + } + + // malloc tmpParams + tmpParams = static_cast(HcfMalloc(sizeof(HcfHkdfParamsSpec), 0)); + if (tmpParams == nullptr) { + LOGE("hkdf spec malloc failed!"); + break; + } + SetHkdfParamsSpecAttribute(out, salt, key, info, tmpParams); + // only need the data and data length of the salt, so free the blob pointer. + HcfFree(salt); + HcfFree(info); + *params = reinterpret_cast(tmpParams); + return true; + } while (0); + HcfBlobDataClearAndFree(salt); + HcfBlobDataClearAndFree(&key); + HcfBlobDataClearAndFree(info); + HcfFree(salt); + HcfFree(info); + HcfFree(out.data); + return false; +} + static bool GetKdfParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **params) { napi_value data = nullptr; @@ -346,6 +419,8 @@ static bool GetKdfParamsSpec(napi_env env, napi_value arg, HcfKdfParamsSpec **pa } if (algoName.compare(PBKDF2_ALG_NAME) == 0) { return GetPBKDF2ParamsSpec(env, arg, params); + } else if (algoName.compare(HKDF_ALG_NAME) == 0) { + return GetHkdfParamsSpec(env, arg, params); } else { LOGE("Not support that alg"); return false; diff --git a/frameworks/js/napi/crypto/src/napi_sym_key_generator.cpp b/frameworks/js/napi/crypto/src/napi_sym_key_generator.cpp index b1db3fd725c6bb6e6da81b722b9012bb673c1fc6..5b2772e278c65ca44b017884f375f5d2eec9d0b0 100644 --- a/frameworks/js/napi/crypto/src/napi_sym_key_generator.cpp +++ b/frameworks/js/napi/crypto/src/napi_sym_key_generator.cpp @@ -310,7 +310,7 @@ HcfSymKeyGenerator *NapiSymKeyGenerator::GetSymKeyGenerator() const return this->generator_; } -static bool napiGetInstance(napi_env env, HcfSymKey *key, napi_value instance) +static bool NapiGetInstance(napi_env env, HcfSymKey *key, napi_value instance) { NapiSymKey *napiSymKey = new (std::nothrow) NapiSymKey(key); if (napiSymKey == nullptr) { @@ -374,7 +374,7 @@ napi_value NapiSymKeyGenerator::JsGenerateSymKeySync(napi_env env, napi_callback HcfSymKeyGenerator *generator = napiGenerator->GetSymKeyGenerator(); if (generator == nullptr) { - napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "failed to get generator obj.")); + napi_throw(env, GenerateBusinessError(env, HCF_NOT_SUPPORT, "failed to get generator obj.")); LOGE("failed to get generator obj!"); return nullptr; } @@ -388,8 +388,8 @@ napi_value NapiSymKeyGenerator::JsGenerateSymKeySync(napi_env env, napi_callback } napi_value instance = NapiSymKey::CreateSymKey(env); - if (!napiGetInstance(env, key, instance)) { - napi_throw(env, GenerateBusinessError(env, HCF_NOT_SUPPORT, "get instance failed!")); + if (!NapiGetInstance(env, key, instance)) { + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get instance failed!")); LOGE("get instance failed!"); return nullptr; } @@ -441,11 +441,12 @@ napi_value NapiSymKeyGenerator::JsConvertKeySync(napi_env env, napi_callback_inf return nullptr; } - size_t index = 0; - HcfBlob *keyMaterial = GetBlobFromNapiDataBlob(env, argv[index++]); + HcfBlob *keyMaterial = GetBlobFromNapiDataBlob(env, argv[0]); if (keyMaterial == nullptr) { napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get keyMaterial failed!")); LOGE("get keyMaterial failed!"); + HcfBlobDataFree(keyMaterial); + HcfFree(keyMaterial); return nullptr; } @@ -467,7 +468,7 @@ napi_value NapiSymKeyGenerator::JsConvertKeySync(napi_env env, napi_callback_inf } napi_value instance = NapiSymKey::CreateSymKey(env); - if (!napiGetInstance(env, key, instance)) { + if (!NapiGetInstance(env, key, instance)) { napi_throw(env, GenerateBusinessError(env, HCF_NOT_SUPPORT, "get instance failed!")); LOGE("get instance failed!"); return nullptr; diff --git a/interfaces/innerkits/algorithm_parameter/detailed_hkdf_params.h b/interfaces/innerkits/algorithm_parameter/detailed_hkdf_params.h new file mode 100644 index 0000000000000000000000000000000000000000..f6600b8e87043cb06c60d73633cdb470440bceeb --- /dev/null +++ b/interfaces/innerkits/algorithm_parameter/detailed_hkdf_params.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_DETAILED_HKDF_PARAMS_H +#define HCF_DETAILED_HKDF_PARAMS_H + +#include "blob.h" +#include "kdf_params.h" + +typedef struct HcfHkdfParamsSpec HcfHkdfParamsSpec; + +struct HcfHkdfParamsSpec { + HcfKdfParamsSpec base; + HcfBlob key; + HcfBlob salt; + HcfBlob info; + HcfBlob output; +}; + +#endif // HCF_DETAILED_HKDF_PARAMS_H diff --git a/plugin/openssl_plugin/common/inc/openssl_adapter.h b/plugin/openssl_plugin/common/inc/openssl_adapter.h index 45e592d0d45be304b15cf725b3c91d254042ab34..4e3288ed1f299718a8000c375192c55881c23abf 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -320,6 +321,11 @@ int Openssl_EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); 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); +int Openssl_EVP_PKEY_CTX_set_hkdf_mode(EVP_PKEY_CTX *ctx, int mode); +int Openssl_EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); +int Openssl_EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx, const unsigned char *salt, int saltlen); +int Openssl_EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, const unsigned char *key, int keylen); +int Openssl_EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, const unsigned char *info, int infolen); // SM2 ASN1 typedef struct SM2_Ciphertext_st SM2_Ciphertext; diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index ec7477c11e0020e28204a4bb26b870d550bfc86a..0f071430c21912e96a5300beaf27c81afc85c96d 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -1443,4 +1443,28 @@ int Openssl_EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POIN BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { return EC_POINT_get_affine_coordinates(group, p, x, y, ctx); -} \ No newline at end of file +} +int Openssl_EVP_PKEY_CTX_set_hkdf_mode(EVP_PKEY_CTX *ctx, int mode) +{ + return EVP_PKEY_CTX_set_hkdf_mode(ctx, mode); +} + +int Openssl_EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) +{ + return EVP_PKEY_CTX_set_hkdf_md(ctx, md); +} + +int Openssl_EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx, const unsigned char *salt, int saltlen) +{ + return EVP_PKEY_CTX_set1_hkdf_salt(ctx, salt, saltlen); +} + +int Openssl_EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx, const unsigned char *key, int keylen) +{ + return EVP_PKEY_CTX_set1_hkdf_key(ctx, key, keylen); +} + +int Openssl_EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx, const unsigned char *info, int infolen) +{ + return EVP_PKEY_CTX_add1_hkdf_info(ctx, info, infolen); +} diff --git a/plugin/openssl_plugin/crypto_operation/kdf/inc/hkdf_openssl.h b/plugin/openssl_plugin/crypto_operation/kdf/inc/hkdf_openssl.h new file mode 100644 index 0000000000000000000000000000000000000000..edc5d5238650c7a3d6f7374a8ed1f35f7ecc5b4c --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/kdf/inc/hkdf_openssl.h @@ -0,0 +1,31 @@ +/* + * 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_HKDF_OPENSSL_H +#define HCF_HKDF_OPENSSL_H + +#include "kdf_spi.h" +#include "params_parser.h" + +#ifdef __cplusplus +extern "C" { +#endif +HcfResult HcfKdfHkdfSpiCreate(HcfKdfDeriveParams *params, HcfKdfSpi **spiObj); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/plugin/openssl_plugin/crypto_operation/kdf/src/hkdf_openssl.c b/plugin/openssl_plugin/crypto_operation/kdf/src/hkdf_openssl.c new file mode 100644 index 0000000000000000000000000000000000000000..d3e4d41c9d42041853a66c0c3b12b248bbdeded3 --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/kdf/src/hkdf_openssl.c @@ -0,0 +1,309 @@ +/* + * 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 "hkdf_openssl.h" + +#include "log.h" +#include "memory.h" +#include "result.h" +#include "securec.h" +#include "utils.h" +#include "openssl_adapter.h" +#include "openssl_common.h" +#include "detailed_hkdf_params.h" +#include "openssl/kdf.h" + +#define HKDF_ALG_NAME "HKDF" + +typedef struct { + unsigned char *salt; + int saltLen; + unsigned char *key; + int keyLen; + unsigned char *info; + int infoLen; + unsigned char *out; + int outLen; +} HcfHkdfData; + +typedef struct { + HcfKdfSpi base; + const EVP_MD *digestAlg; + int mode; + HcfHkdfData *kdfData; +} OpensslHkdfSpiImpl; + +static const char *EngineGetKdfClass(void) +{ + return "OpensslHkdf"; +} + +static void HcfClearAndFree(unsigned char *blob, int len) +{ + // when blob == null, len must be 0; in check func, len >= 0 + if (blob == NULL) { + return; + } + (void)memset_s(blob, len, 0, len); + HcfFree(blob); +} + +static void FreeHkdfData(HcfHkdfData **data) +{ + if (data == NULL || *data == NULL) { + return; + } + if ((*data)->out != NULL) { + HcfClearAndFree((*data)->out, (*data)->outLen); + (*data)->out = NULL; + (*data)->outLen = 0; + } + if ((*data)->salt != NULL) { + HcfClearAndFree((*data)->salt, (*data)->saltLen); + (*data)->salt = NULL; + (*data)->saltLen = 0; + } + if ((*data)->info != NULL) { + HcfClearAndFree((*data)->info, (*data)->infoLen); + (*data)->info = NULL; + (*data)->infoLen = 0; + } + if ((*data)->key != NULL) { + HcfClearAndFree((*data)->key, (*data)->keyLen); + (*data)->key = NULL; + (*data)->keyLen = 0; + } + HcfFree(*data); + *data = NULL; +} + +static void EngineDestroyKdf(HcfObjectBase *self) +{ + if (self == NULL) { + LOGE("Self ptr is NULL!"); + return; + } + if (!IsClassMatch(self, EngineGetKdfClass())) { + LOGE("Class is not match."); + return; + } + OpensslHkdfSpiImpl *impl = (OpensslHkdfSpiImpl *)self; + FreeHkdfData(&(impl->kdfData)); + impl->digestAlg = NULL; + HcfFree(self); +} + +static bool CheckHkdfParams(HcfHkdfParamsSpec *params) +{ + // openssl only support INT and blob attribute is size_t, it should samller than INT_MAX. + if (params->output.len > INT_MAX || params->salt.len > INT_MAX || params->key.len > INT_MAX || + params->info.len > INT_MAX) { + LOGE("beyond the length"); + return false; + } + + if (params->output.data == NULL || params->output.len == 0) { + LOGE("invalid output"); + return false; + } + if (params->key.data == NULL && params->key.len == 0) { + LOGD("empty key"); + return false; + } + if (params->salt.data == NULL && params->salt.len == 0) { + LOGD("empty salt"); + return true; + } + + if (params->info.data == NULL && params->info.len == 0) { + LOGD("empty info"); + return true; + } + return false; +} + +static bool GetHkdfSaltFromSpec(HcfHkdfData *data, HcfHkdfParamsSpec *params) +{ + data->salt = (unsigned char *)HcfMalloc(params->salt.len, 0); + if (data->salt == NULL) { + return false; + } + (void)memcpy_s(data->salt, params->salt.len, params->salt.data, params->salt.len); + data->saltLen = params->salt.len; + return true; +} + +static bool GetHkdfKeyFromSpec(HcfHkdfData *data, HcfHkdfParamsSpec *params) +{ + data->key = (unsigned char *)HcfMalloc(params->key.len, 0); + if (data->key == NULL) { + return false; + } + (void)memcpy_s(data->key, params->key.len, params->key.data, params->key.len); + data->keyLen = params->key.len; + return true; +} + +static bool GetHkdfInfoFromSpec(HcfHkdfData *data, HcfHkdfParamsSpec *params) +{ + data->info = (unsigned char *)HcfMalloc(params->info.len, 0); + if (data->info == NULL) { + return false; + } + (void)memcpy_s(data->info, params->info.len, params->info.data, params->info.len); + data->infoLen = params->info.len; + return true; +} + +static int32_t GetHkdfMode(OpensslHkdfSpiImpl *self) +{ + switch (self->mode) { + case HCF_ALG_MODE_EXTRACT_AND_EXPAND: + return EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; + case HCF_ALG_MODE_EXTRACT_ONLY: + return EVP_KDF_HKDF_MODE_EXTRACT_ONLY; + case HCF_ALG_MODE_EXPAND_ONLY: + return EVP_KDF_HKDF_MODE_EXPAND_ONLY; + default: + return EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; + } +} + +static HcfResult InitHkdfData(OpensslHkdfSpiImpl *self, HcfHkdfParamsSpec *params) +{ + HcfHkdfData *data = (HcfHkdfData *)HcfMalloc(sizeof(HcfHkdfData), 0); + do { + if (data == NULL) { + LOGE("malloc data failed"); + break; + } + if (!GetHkdfKeyFromSpec(data, params)) { + LOGE("key malloc failed!"); + break; + } + if (!GetHkdfSaltFromSpec(data, params)) { + LOGE("salt malloc failed!"); + break; + } + if (!GetHkdfInfoFromSpec(data, params)) { + LOGE("info malloc failed!"); + break; + } + data->out = (unsigned char *)HcfMalloc(params->output.len, 0); + if (data->out == NULL) { + LOGE("out malloc failed!"); + break; + } + data->outLen = params->output.len; + self->kdfData = data; + return HCF_SUCCESS; + } while (0); + FreeHkdfData(&data); + return HCF_ERR_MALLOC; +} + +static HcfResult OpensslHkdf(OpensslHkdfSpiImpl *self, HcfBlob *output) +{ + EVP_PKEY_CTX *pctx = Openssl_EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + HcfHkdfData *data = self->kdfData; + if (Openssl_EVP_PKEY_derive_init(pctx) <= 0) { + LOGE("PKEY_derive_init filed"); + return HCF_INVALID_PARAMS; + } + LOGE("mode is %d", self->mode); + if (Openssl_EVP_PKEY_CTX_set_hkdf_mode(pctx, GetHkdfMode(self)) <= 0) { + LOGE("PKEY_CTX_set_hkdf_mode filed"); + return HCF_INVALID_PARAMS; + } + if (Openssl_EVP_PKEY_CTX_set_hkdf_md(pctx, self->digestAlg) <= 0) { + LOGE("PKEY_CTX_set_hkdf_md filed"); + return HCF_INVALID_PARAMS; + } + if (Openssl_EVP_PKEY_CTX_set1_hkdf_salt(pctx, data->salt, data->saltLen) <= 0) { + LOGE("PKEY_CTX_set1_hkdf_salt filed"); + return HCF_INVALID_PARAMS; + } + if (Openssl_EVP_PKEY_CTX_set1_hkdf_key(pctx, data->key, data->keyLen) <= 0) { + LOGE("PKEY_CTX_set1_hkdf_key filed"); + return HCF_INVALID_PARAMS; + } + if (Openssl_EVP_PKEY_CTX_add1_hkdf_info(pctx, data->info, data->infoLen) <= 0) { + LOGE("PKEY_CTX_add1_hkdf_info filed"); + return HCF_INVALID_PARAMS; + } + if (Openssl_EVP_PKEY_derive(pctx, data->out, (size_t *)(&(data->outLen))) <=0) { + LOGE("EVP_PKEY_derive filed"); + return HCF_INVALID_PARAMS; + } + + (void)memcpy_s(output->data, data->outLen, data->out, data->outLen); + EVP_PKEY_CTX_free(pctx); + return HCF_SUCCESS; +} + +static HcfResult EngineGenerateSecret(HcfKdfSpi *self, HcfKdfParamsSpec *paramsSpec) +{ + if (self == NULL || paramsSpec == NULL) { + LOGE("Invalid input parameter."); + return HCF_INVALID_PARAMS; + } + if (!IsClassMatch((HcfObjectBase *)self, EngineGetKdfClass())) { + return HCF_INVALID_PARAMS; + } + OpensslHkdfSpiImpl *hkdfImpl = (OpensslHkdfSpiImpl *)self; + if (paramsSpec->algName == NULL || strcmp(paramsSpec->algName, HKDF_ALG_NAME) != 0) { + LOGE("Not hkdf paramsSpec"); + return HCF_INVALID_PARAMS; + } + HcfHkdfParamsSpec *params = (HcfHkdfParamsSpec *)paramsSpec; + if (!CheckHkdfParams(params)) { + LOGE("params error"); + return HCF_INVALID_PARAMS; + } + HcfResult res = InitHkdfData(hkdfImpl, params); + if (res != HCF_SUCCESS) { + LOGE("InitCipherData failed!"); + return HCF_INVALID_PARAMS; + } + res = OpensslHkdf(hkdfImpl, ¶ms->output); + FreeHkdfData(&(hkdfImpl->kdfData)); + return res; +} + +HcfResult HcfKdfHkdfSpiCreate(HcfKdfDeriveParams *params, HcfKdfSpi **spiObj) +{ + if (params == NULL || spiObj == NULL) { + LOGE("Invalid input parameter."); + return HCF_INVALID_PARAMS; + } + EVP_MD *md = NULL; + HcfResult res = GetOpensslDigestAlg(params->md, &md); + if (res != HCF_SUCCESS || md == NULL) { + LOGE("get md failed"); + return HCF_INVALID_PARAMS; + } + OpensslHkdfSpiImpl *returnSpiImpl = (OpensslHkdfSpiImpl *)HcfMalloc(sizeof(OpensslHkdfSpiImpl), 0); + if (returnSpiImpl == NULL) { + LOGE("Failed to allocate returnImpl memory!"); + return HCF_ERR_MALLOC; + } + returnSpiImpl->base.base.getClass = EngineGetKdfClass; + returnSpiImpl->base.base.destroy = EngineDestroyKdf; + returnSpiImpl->base.generateSecret = EngineGenerateSecret; + returnSpiImpl->digestAlg = md; + returnSpiImpl->mode = params->mode; + *spiObj = (HcfKdfSpi *)returnSpiImpl; + return HCF_SUCCESS; +} \ No newline at end of file diff --git a/plugin/plugin.gni b/plugin/plugin.gni index 45f161005e6b242708443c84485856e53fe21c07..8a18e7fd4724e4e49bcaff0b76e6d8eb1333c900 100644 --- a/plugin/plugin.gni +++ b/plugin/plugin.gni @@ -89,6 +89,7 @@ plugin_md_files = plugin_kdf_files = [ "${plugin_path}/openssl_plugin/crypto_operation/kdf/src/pbkdf2_openssl.c", + "${plugin_path}/openssl_plugin/crypto_operation/kdf/src/hkdf_openssl.c", ] plugin_files = plugin_asy_key_generator_files + plugin_key_agreement_files + diff --git a/test/unittest/src/crypto_hkdf_test.cpp b/test/unittest/src/crypto_hkdf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c4c8b8f3a1eab596c4d9b6b16e9c324b19bcb0a --- /dev/null +++ b/test/unittest/src/crypto_hkdf_test.cpp @@ -0,0 +1,466 @@ +/* + * 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 "hkdf_openssl.h" + +#include +#include "securec.h" + +#include "detailed_hkdf_params.h" +#include "kdf.h" +#include "log.h" +#include "memory.h" + +using namespace std; +using namespace testing::ext; + +namespace { +class CryptoHkdfTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void CryptoHkdfTest::SetUpTestCase() {} +void CryptoHkdfTest::TearDownTestCase() {} + +void CryptoHkdfTest::SetUp() // add init here, this will be called before test. +{ +} + +void CryptoHkdfTest::TearDown() // add destroy here, this will be called when test case done. +{ +} + +static const char *g_hkdfName = "HKDF"; +static const char *g_keyData = "012345678901234567890123456789"; +static const char *g_infoData = "infostring"; +static const char *g_saltData = "infostring"; + + +constexpr uint32_t OUT_PUT_MAX_LENGTH = 128; +constexpr uint32_t OUT_PUT_NORMAL_LENGTH = 32; + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest1, TestSize.Level0) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest2, TestSize.Level0) +{ + // mode is default, info data is nullptr + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = nullptr, .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest3, TestSize.Level0) +{ + // default mode is EXTRACT_AND_EXPAND + HcfKdf *generator = nullptr; + HcfKdf *generator1 = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfResult ret1 = HcfKdfCreate("HKDF|SHA256|EXTRACT_AND_EXPAND", &generator1); + EXPECT_EQ(ret1, HCF_SUCCESS); + + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + + HcfHkdfParamsSpec params1 = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret1 = generator->generateSecret(generator, &(params1.base)); + EXPECT_EQ(ret1, HCF_SUCCESS); + EXPECT_EQ(params.output.data, params1.output.data); + + HcfObjDestroy(generator); + HcfObjDestroy(generator1); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest4, TestSize.Level0) +{ + // mode is EXTRACT_ONLY + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256|EXTRACT_ONLY", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest5, TestSize.Level0) +{ + // mode is EXPAND_ONLY + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256|EXPAND_ONLY", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest6, TestSize.Level0) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA1", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest7, TestSize.Level0) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA384", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest8, TestSize.Level0) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA512", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest9, TestSize.Level0) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SM3", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTest10, TestSize.Level0) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA224", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(g_keyData)), + .len = strlen(g_keyData)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError1, TestSize.Level1) +{ + // mode is EXPAND_ONLY, salt data is nullptr + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256|EXPAND_ONLY", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob info = {.data = nullptr, .len = 0}; + HcfBlob key = {.data = nullptr, .len = 0}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError2, TestSize.Level1) +{ + // mode is EXTRACT_ONLY, salt data is nullptr + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256|EXTRACT_ONLY", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = nullptr, .len = 0}; + HcfBlob key = {.data = nullptr, .len = 0}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError3, TestSize.Level1) +{ + // mode is default, data is nullptr + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = nullptr, .len = 0}; + HcfBlob key = {.data = nullptr, .len = 0}; + HcfBlob info = {.data = nullptr, .len = 0}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError4, TestSize.Level1) +{ + // mode is default, key data is nullptr + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[OUT_PUT_MAX_LENGTH] = {0}; + HcfBlob output = {.data = out, .len = OUT_PUT_NORMAL_LENGTH}; + HcfBlob salt = {.data = reinterpret_cast(const_cast(g_saltData)), + .len = strlen(g_saltData)}; + HcfBlob key = {.data = nullptr, .len = 0}; + HcfBlob info = {.data = reinterpret_cast(const_cast(g_infoData)), + .len = strlen(g_infoData)}; + HcfHkdfParamsSpec params = { + .base.algName = g_hkdfName, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError5, TestSize.Level1) +{ + // use basic params + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + HcfKdfParamsSpec params = { + .algName = g_hkdfName, + }; + ret = generator->generateSecret(generator, ¶ms); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError6, TestSize.Level1) +{ + // use nullptr params + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + ret = generator->generateSecret(generator, nullptr); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError7, TestSize.Level1) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|abcd", &generator); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError8, TestSize.Level1) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("ABCD|SM3", &generator); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError9, TestSize.Level1) +{ + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate(nullptr, &generator); + EXPECT_NE(ret, HCF_SUCCESS); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestError10, TestSize.Level1) +{ + HcfResult ret = HcfKdfCreate(nullptr, nullptr); + EXPECT_NE(ret, HCF_SUCCESS); +} +} \ No newline at end of file