From 5a08ffc31baeea045da8e4fa788da901acb7e731 Mon Sep 17 00:00:00 2001 From: lcc Date: Sun, 7 Apr 2024 11:53:16 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E7=AE=97=E6=B3=95=E5=BA=93=E9=80=82?= =?UTF-8?q?=E9=85=8D=E5=B1=82=E3=80=91=E5=B0=81=E8=A3=85Openssl=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=90=91=E4=B8=8A=E6=8F=90?= =?UTF-8?q?=E4=BE=9BHKDF=E5=AF=86=E9=92=A5=E6=B4=BE=E7=94=9F=E7=AE=97?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lcc --- common/inc/params_parser.h | 9 + common/src/params_parser.c | 4 + frameworks/crypto_operation/kdf.c | 15 +- .../inc/napi_crypto_framework_defines.h | 10 +- frameworks/js/napi/crypto/src/napi_kdf.cpp | 101 +++- .../detailed_hkdf_params.h | 32 + .../common/inc/openssl_adapter.h | 11 + .../common/src/openssl_adapter.c | 32 + .../crypto_operation/kdf/inc/hkdf_openssl.h | 31 + .../crypto_operation/kdf/src/hkdf_openssl.c | 330 +++++++++++ plugin/plugin.gni | 1 + test/unittest/BUILD.gn | 1 + test/unittest/src/crypto_hkdf_test.cpp | 546 ++++++++++++++++++ 13 files changed, 1107 insertions(+), 16 deletions(-) create mode 100644 interfaces/innerkits/algorithm_parameter/detailed_hkdf_params.h create mode 100644 plugin/openssl_plugin/crypto_operation/kdf/inc/hkdf_openssl.h create mode 100644 plugin/openssl_plugin/crypto_operation/kdf/src/hkdf_openssl.c create mode 100644 test/unittest/src/crypto_hkdf_test.cpp diff --git a/common/inc/params_parser.h b/common/inc/params_parser.h index ce89d46..6e333c6 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 3f34c58..bccee48 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 fe95cf5..b6fe9b2 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 56df370..ca0a427 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 2d1626c..d503540 100644 --- a/frameworks/js/napi/crypto/src/napi_kdf.cpp +++ b/frameworks/js/napi/crypto/src/napi_kdf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Huawei Device Co., Ltd. + * Copyright (C) 2023-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 @@ -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("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/interfaces/innerkits/algorithm_parameter/detailed_hkdf_params.h b/interfaces/innerkits/algorithm_parameter/detailed_hkdf_params.h new file mode 100644 index 0000000..f6600b8 --- /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 45e592d..b074dc0 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include @@ -145,6 +148,7 @@ int Openssl_EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); int Openssl_EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen, const unsigned char *sig, size_t siglen); OSSL_PARAM Openssl_OSSL_PARAM_construct_utf8_string(const char *key, char *buf, size_t bsize); +OSSL_PARAM Openssl_OSSL_PARAM_construct_octet_string(const char *key, void *buf, size_t bsize); OSSL_PARAM Openssl_OSSL_PARAM_construct_end(void); OSSL_PARAM Openssl_OSSL_PARAM_construct_uint(const char *key, unsigned int *buf); OSSL_PARAM Openssl_OSSL_PARAM_construct_int(const char *key, int *buf); @@ -320,6 +324,13 @@ 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); +EVP_KDF *Openssl_EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, + const char *properties); +EVP_KDF_CTX *Openssl_EVP_KDF_CTX_new(EVP_KDF *kdf); +void Openssl_EVP_KDF_free(EVP_KDF *kdf); +void Openssl_EVP_KDF_CTX_free(EVP_KDF_CTX *ctx); +int Openssl_EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, + const OSSL_PARAM params[]); // 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 ec7477c..0fde8dc 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -516,6 +516,11 @@ OSSL_PARAM Openssl_OSSL_PARAM_construct_utf8_string(const char *key, char *buf, return OSSL_PARAM_construct_utf8_string(key, buf, bsize); } +OSSL_PARAM Openssl_OSSL_PARAM_construct_octet_string(const char *key, void *buf, size_t bsize) +{ + return OSSL_PARAM_construct_octet_string(key, buf, bsize); +} + OSSL_PARAM Openssl_OSSL_PARAM_construct_end(void) { return OSSL_PARAM_construct_end(); @@ -1443,4 +1448,31 @@ 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); +} + +EVP_KDF *Openssl_EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, + const char *properties) +{ + return EVP_KDF_fetch(libctx, algorithm, properties); +} + +EVP_KDF_CTX *Openssl_EVP_KDF_CTX_new(EVP_KDF *kdf) +{ + return EVP_KDF_CTX_new(kdf); +} + +void Openssl_EVP_KDF_free(EVP_KDF *kdf) +{ + return EVP_KDF_free(kdf); +} + +void Openssl_EVP_KDF_CTX_free(EVP_KDF_CTX *ctx) +{ + return EVP_KDF_CTX_free(ctx); +} + +int Openssl_EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen, + const OSSL_PARAM params[]) +{ + return EVP_KDF_derive(ctx, key, keylen, params); } \ No newline at end of file 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 0000000..edc5d52 --- /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 0000000..efbfca8 --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/kdf/src/hkdf_openssl.c @@ -0,0 +1,330 @@ +/* + * 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 "openssl/kdf.h" +#include "detailed_hkdf_params.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; + int digestAlg; + int mode; + HcfHkdfData *kdfData; +} OpensslHkdfSpiImpl; + +static const char *EngineGetKdfClass(void) +{ + return "OpensslHkdf"; +} + +static void HcfClearAndFree(unsigned char *buf, int bufLen) +{ + // when buf == null, bufLen must be 0; in check func, bufLen >= 0 + if (buf == NULL) { + return; + } + (void)memset_s(buf, bufLen, 0, bufLen); + HcfFree(buf); +} + +static void FreeHkdfData(HcfHkdfData **data) +{ + if (data == NULL || *data == NULL) { + return; + } + HcfClearAndFree((*data)->out, (*data)->outLen); + HcfClearAndFree((*data)->salt, (*data)->saltLen); + HcfClearAndFree((*data)->info, (*data)->infoLen); + HcfClearAndFree((*data)->key, (*data)->keyLen); + (void)memset_s(*data, sizeof(HcfHkdfData), 0, sizeof(HcfHkdfData)); + 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)); + 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->key.data == NULL && params->key.len == 0) { + LOGE("check params failed, key is NULL"); + return false; + } + if (params->output.data == NULL || params->output.len == 0) { + LOGE("check params failed, output data is NULL"); + 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 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 int 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 bool GetHkdfInfoFromSpec(OpensslHkdfSpiImpl *self, HcfHkdfData *data, HcfHkdfParamsSpec *params) +{ + if (self->mode == HCF_ALG_MODE_EXTRACT_ONLY) { + LOGD("EXTRACT_ONLY mode does not require info"); + return true; + } + + if (params->info.len == 0) { + LOGD("info can be empty."); + return true; + } + + 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 bool GetHkdfSaltFromSpec(OpensslHkdfSpiImpl *self, HcfHkdfData *data, HcfHkdfParamsSpec *params) +{ + if (self->mode == HCF_ALG_MODE_EXPAND_ONLY) { + LOGD("EXPAND_ONLY mode does not require salt"); + return true; + } + + if (params->salt.len == 0) { + LOGD("salt can be empty."); + return true; + } + + 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 HcfResult InitHkdfData(OpensslHkdfSpiImpl *self, HcfHkdfParamsSpec *params) +{ + LOGD("MODE IS %d", self->mode); + 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(self, data, params)) { + LOGE("salt malloc failed!"); + break; + } + if (!GetHkdfInfoFromSpec(self, 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 char *SwitchMd(OpensslHkdfSpiImpl *self) +{ + switch (self->digestAlg) { + case HCF_OPENSSL_DIGEST_NONE: + return ""; + case HCF_OPENSSL_DIGEST_MD5: + return "MD5"; + case HCF_OPENSSL_DIGEST_SM3: + return "SM3"; + case HCF_OPENSSL_DIGEST_SHA1: + return "SHA1"; + case HCF_OPENSSL_DIGEST_SHA224: + return "SHA224"; + case HCF_OPENSSL_DIGEST_SHA256: + return "SHA256"; + case HCF_OPENSSL_DIGEST_SHA384: + return "SHA384"; + case HCF_OPENSSL_DIGEST_SHA512: + return "SHA512"; + default: + return ""; + } +} + +static HcfResult OpensslHkdf(OpensslHkdfSpiImpl *self, HcfBlob *output) +{ + EVP_KDF *kdf = NULL; + EVP_KDF_CTX *kctx = NULL; + // need set 6 params + OSSL_PARAM params[6] = {}; + OSSL_PARAM *p = params; + + kdf = Openssl_EVP_KDF_fetch(NULL, "HKDF", NULL); + if (kdf == NULL) { + LOGE("kdf fetch failed"); + return HCF_ERR_CRYPTO_OPERATION; + } + + kctx = Openssl_EVP_KDF_CTX_new(kdf); + Openssl_EVP_KDF_free(kdf); + if (kctx == NULL) { + LOGE("kdf ctx new failed"); + return HCF_ERR_CRYPTO_OPERATION; + } + + int mode = GetHkdfMode(self); + char *digest = SwitchMd(self); + *p++ = Openssl_OSSL_PARAM_construct_utf8_string("digest", digest, 0); + *p++ = Openssl_OSSL_PARAM_construct_octet_string("key", self->kdfData->key, self->kdfData->keyLen); + *p++ = Openssl_OSSL_PARAM_construct_octet_string("info", self->kdfData->info, self->kdfData->infoLen); + *p++ = Openssl_OSSL_PARAM_construct_octet_string("salt", self->kdfData->salt, self->kdfData->saltLen); + *p++ = Openssl_OSSL_PARAM_construct_int("mode", &mode); + *p = Openssl_OSSL_PARAM_construct_end(); + if (Openssl_EVP_KDF_derive(kctx, output->data, output->len, params) <= 0) { + HcfPrintOpensslError(); + LOGE("EVP_KDF_derive failed"); + Openssl_EVP_KDF_CTX_free(kctx); + return HCF_ERR_CRYPTO_OPERATION; + } + Openssl_EVP_KDF_CTX_free(kctx); + 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; + } + 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 = params->md; + returnSpiImpl->mode = params->mode; + *spiObj = (HcfKdfSpi *)returnSpiImpl; + return HCF_SUCCESS; +} diff --git a/plugin/plugin.gni b/plugin/plugin.gni index 45f1610..8a18e7f 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/BUILD.gn b/test/unittest/BUILD.gn index 096e8bf..eda60bc 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -66,6 +66,7 @@ ohos_unittest("crypto_framework_test") { "src/crypto_ed25519_asy_key_generator_test.cpp", "src/crypto_ed25519_sign_test.cpp", "src/crypto_ed25519_verify_test.cpp", + "src/crypto_hkdf_test.cpp", "src/crypto_mac_test.cpp", "src/crypto_md_sm3_test.cpp", "src/crypto_md_test.cpp", diff --git a/test/unittest/src/crypto_hkdf_test.cpp b/test/unittest/src/crypto_hkdf_test.cpp new file mode 100644 index 0000000..5cac541 --- /dev/null +++ b/test/unittest/src/crypto_hkdf_test.cpp @@ -0,0 +1,546 @@ +/* + * 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 *KEY_DATA = "012345678901234567890123456789"; +static const char *INFO_DATA = "infostring"; +static const char *SALT_DATA = "saltstring"; + + +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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = nullptr, .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + + HcfHkdfParamsSpec params1 = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = reinterpret_cast(const_cast(KEY_DATA)), + .len = strlen(KEY_DATA)}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .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 = "HKDF", }, + .key = key, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(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 = "HKDF", }, + .key = key, + .salt = salt, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(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 = "HKDF", }, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(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(SALT_DATA)), + .len = strlen(SALT_DATA)}; + HcfBlob key = {.data = nullptr, .len = 0}; + HcfBlob info = {.data = reinterpret_cast(const_cast(INFO_DATA)), + .len = strlen(INFO_DATA)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(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 = "HKDF", + }; + 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); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestVectors1, TestSize.Level1) +{ + uint8_t keyData[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; + uint8_t infoData[] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 }; + uint8_t saltData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c }; + uint8_t expectSecret[] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, + 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, + 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, + 0x65 }; + + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[42] = {0}; + HcfBlob output = {.data = out, .len = 42}; + HcfBlob salt = {.data = saltData, .len = sizeof(saltData)}; + HcfBlob key = {.data = keyData, .len = sizeof(keyData)}; + HcfBlob info = {.data = infoData, .len = sizeof(infoData)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + EXPECT_EQ(memcmp(params.output.data, expectSecret, sizeof(expectSecret)), 0); + HcfObjDestroy(generator); +} + +HWTEST_F(CryptoHkdfTest, CryptoHkdfTestVectors2, TestSize.Level1) +{ + uint8_t keyData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, + 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, + 0x4d, 0x4e, 0x4f }; + uint8_t infoData[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, + 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, + 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, + 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, + 0xfd, 0xfe, 0xff }; + uint8_t saltData[] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, + 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, + 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, + 0xad, 0xae, 0xaf }; + uint8_t expectSecret[] = { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, + 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, + 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, + 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, + 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, + 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87 }; + + HcfKdf *generator = nullptr; + HcfResult ret = HcfKdfCreate("HKDF|SHA256|EXTRACT_AND_EXPAND", &generator); + EXPECT_EQ(ret, HCF_SUCCESS); + uint8_t out[82] = {0}; + HcfBlob output = {.data = out, .len = 82}; + HcfBlob salt = {.data = saltData, .len = sizeof(saltData)}; + HcfBlob key = {.data = keyData, .len = sizeof(keyData)}; + HcfBlob info = {.data = infoData, .len = sizeof(infoData)}; + HcfHkdfParamsSpec params = { + .base = { .algName = "HKDF", }, + .key = key, + .salt = salt, + .info = info, + .output = output, + }; + ret = generator->generateSecret(generator, &(params.base)); + EXPECT_EQ(ret, HCF_SUCCESS); + EXPECT_EQ(memcmp(params.output.data, expectSecret, sizeof(expectSecret)), 0); + HcfObjDestroy(generator); +} +} -- Gitee