diff --git a/common/inc/params_parser.h b/common/inc/params_parser.h index d51625a2be67463518f7118580fd01afd9eb114b..9d05e10fe869dc1e606cc785bfc7281af552e861 100644 --- a/common/inc/params_parser.h +++ b/common/inc/params_parser.h @@ -49,6 +49,8 @@ typedef enum { HCF_ALG_DH, HCF_ALG_HKDF, HCF_ALG_SCRYPT, + HCF_ALG_CHACHA20, + HCF_ALG_CHACHA20_POLY1305, } HcfAlgValue; typedef enum { @@ -63,6 +65,7 @@ typedef enum { HCF_ALG_SM4_128, HCF_ALG_DES_64, HCF_ALG_3DES_192, + HCF_ALG_CHACHA20_256, HCF_ALG_MODE_NONE, HCF_ALG_MODE_ECB, @@ -76,6 +79,7 @@ typedef enum { HCF_ALG_MODE_CFB128, HCF_ALG_MODE_CCM, HCF_ALG_MODE_GCM, + HCF_ALG_MODE_POLY1305, HCF_ALG_NOPADDING, HCF_ALG_PADDING_PKCS5, @@ -132,6 +136,7 @@ typedef enum { HCF_ALG_ECC_BRAINPOOL_DEFAULT, HCF_ALG_X25519_DEFAULT, HCF_ALG_DH_DEFAULT, + HCF_ALG_CHACHA20_DEFAULT, // key derivation function, PBKDF2 HCF_ALG_PBKDF2_DEFAULT, diff --git a/common/src/params_parser.c b/common/src/params_parser.c index 07da92623143f0e72dc5db88eb652a7696d79bbf..e318667b08de3bb839e0ab4887e5805eb400619c 100644 --- a/common/src/params_parser.c +++ b/common/src/params_parser.c @@ -33,6 +33,7 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"SM4_128", HCF_ALG_KEY_TYPE, HCF_ALG_SM4_128}, {"3DES192", HCF_ALG_KEY_TYPE, HCF_ALG_3DES_192}, {"DES64", HCF_ALG_KEY_TYPE, HCF_ALG_DES_64}, + {"ChaCha20", HCF_ALG_KEY_TYPE, HCF_ALG_CHACHA20_256}, {"ECB", HCF_ALG_MODE, HCF_ALG_MODE_ECB}, {"CBC", HCF_ALG_MODE, HCF_ALG_MODE_CBC}, @@ -45,6 +46,7 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"CFB128", HCF_ALG_MODE, HCF_ALG_MODE_CFB128}, {"CCM", HCF_ALG_MODE, HCF_ALG_MODE_CCM}, {"GCM", HCF_ALG_MODE, HCF_ALG_MODE_GCM}, + {"Poly1305", HCF_ALG_MODE, HCF_ALG_MODE_POLY1305}, {"NoPadding", HCF_ALG_PADDING_TYPE, HCF_ALG_NOPADDING}, {"PKCS5", HCF_ALG_PADDING_TYPE, HCF_ALG_PADDING_PKCS5}, @@ -120,6 +122,7 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"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}, + {"ChaCha20", HCF_ALG_TYPE, HCF_ALG_CHACHA20_DEFAULT}, {"C1C3C2", HCF_ALG_TEXT_FORMAT, HCF_ALG_TEXT_FORMAT_C1C3C2}, {"C1C2C3", HCF_ALG_TEXT_FORMAT, HCF_ALG_TEXT_FORMAT_C1C2C3}, diff --git a/frameworks/crypto_operation/cipher.c b/frameworks/crypto_operation/cipher.c index 9e7e063e6fd297928e73134c511893192a4af85f..c66ebe7b3530d91596acad6695a0795959f9a197 100644 --- a/frameworks/crypto_operation/cipher.c +++ b/frameworks/crypto_operation/cipher.c @@ -25,6 +25,7 @@ #include "cipher_rsa_openssl.h" #include "cipher_sm2_openssl.h" #include "sm4_openssl.h" +#include "chacha20_openssl.h" #include "utils.h" typedef HcfResult (*HcfCipherGeneratorSpiCreateFunc)(CipherAttr *, HcfCipherGeneratorSpi **); @@ -50,7 +51,9 @@ static const HcfCipherGenAbility CIPHER_ABILITY_SET[] = { { HCF_ALG_AES, { HcfCipherAesGeneratorSpiCreate } }, { HCF_ALG_3DES, { HcfCipherDesGeneratorSpiCreate } }, { HCF_ALG_DES, { HcfCipherDesGeneratorSpiCreate } }, - { HCF_ALG_SM4, { HcfCipherSm4GeneratorSpiCreate } } + { HCF_ALG_SM4, { HcfCipherSm4GeneratorSpiCreate } }, + { HCF_ALG_CHACHA20, { HcfCipherChaCha20GeneratorSpiCreate } }, + { HCF_ALG_CHACHA20_POLY1305, { HcfCipherChaCha20GeneratorSpiCreate } } }; static void SetKeyType(HcfAlgParaValue value, void *cipher) @@ -78,6 +81,9 @@ static void SetKeyType(HcfAlgParaValue value, void *cipher) case HCF_ALG_SM2_DEFAULT: cipherAttr->algo = HCF_ALG_SM2; break; + case HCF_ALG_CHACHA20_DEFAULT: + cipherAttr->algo = HCF_ALG_CHACHA20; + break; default: LOGE("Invalid algo %{public}u.", value); break; @@ -117,6 +123,9 @@ static void SetKeyLength(HcfAlgParaValue value, void *cipher) case HCF_ALG_SM2_256: cipherAttr->algo = HCF_ALG_SM2; break; + case HCF_ALG_CHACHA20_256: + cipherAttr->algo = HCF_ALG_CHACHA20; + break; default: LOGE("Invalid algo %{public}u.", value); break; 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 76f8605985e7cf24d0ae417bf5a034682d82afab..d7e36132f663ab7cf22e251924d098373f4cb8f3 100644 --- a/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h +++ b/frameworks/js/napi/crypto/inc/napi_crypto_framework_defines.h @@ -28,6 +28,7 @@ constexpr size_t ARGS_SIZE_THREE = 3; constexpr size_t ARGS_SIZE_FOUR = 4; constexpr size_t GCM_AUTH_TAG_LEN = 16; constexpr size_t CCM_AUTH_TAG_LEN = 12; +constexpr size_t POLY1305_AUTH_TAG_LEN = 16; constexpr int32_t PARAM0 = 0; constexpr int32_t PARAM1 = 1; constexpr int32_t PARAM2 = 2; @@ -62,6 +63,7 @@ const std::string ALGO_PARAMS_OLD = "algoName"; const std::string IV_PARAMS_SPEC = "IvParamsSpec"; const std::string GCM_PARAMS_SPEC = "GcmParamsSpec"; const std::string CCM_PARAMS_SPEC = "CcmParamsSpec"; +const std::string POLY1305_PARAMS_SPEC = "Poly1305ParamsSpec"; const std::string DSA_ASY_KEY_SPEC = "DSA"; const std::string ECC_ASY_KEY_SPEC = "ECC"; diff --git a/frameworks/js/napi/crypto/src/napi_utils.cpp b/frameworks/js/napi/crypto/src/napi_utils.cpp index 88c26b19ba7f8bd7087640a08448b5d3bc9b5294..8e88722e70fd52d3f6544ddfcfaf0eced21e1434 100644 --- a/frameworks/js/napi/crypto/src/napi_utils.cpp +++ b/frameworks/js/napi/crypto/src/napi_utils.cpp @@ -27,6 +27,7 @@ #include "detailed_rsa_key_params.h" #include "detailed_alg_25519_key_params.h" #include "detailed_dh_key_params.h" +#include "detailed_chacha20_params.h" #include "utils.h" #include "pri_key.h" #include "asy_key_generator.h" @@ -375,6 +376,11 @@ static const char *GetCcmParamsSpecType() return CCM_PARAMS_SPEC.c_str(); } +static const char *GetPoly1305ParamsSpecType() +{ + return POLY1305_PARAMS_SPEC.c_str(); +} + static HcfBlob *GetBlobFromParamsSpec(napi_env env, napi_value arg, const string &type) { napi_value data = nullptr; @@ -544,6 +550,61 @@ clearup: return ret; } +static bool GetPoly1305ParamsSpec(napi_env env, napi_value arg, HcfCryptoMode opMode, HcfParamsSpec **paramsSpec) +{ + HcfBlob *iv = nullptr; + HcfBlob *aad = nullptr; + HcfBlob *tag = nullptr; + HcfBlob authTag = {}; + bool ret = false; + + HcfChaCha20ParamsSpec *poly1305ParamsSpec = reinterpret_cast(HcfMalloc(sizeof(HcfChaCha20ParamsSpec), 0)); + if (poly1305ParamsSpec == nullptr) { + LOGE("poly1305ParamsSpec malloc failed!"); + return false; + } + + if (!GetIvAndAadBlob(env, arg, &iv, &aad)) { + LOGE("GetIvAndAadBlob failed!"); + goto clearup; + } + + if (opMode == DECRYPT_MODE) { + tag = GetBlobFromParamsSpec(env, arg, AUTHTAG_PARAMS); + if (tag == nullptr) { + LOGE("get tag failed!"); + goto clearup; + } + } else if (opMode == ENCRYPT_MODE) { + authTag.data = static_cast(HcfMalloc(POLY1305_AUTH_TAG_LEN, 0)); + if (authTag.data == nullptr) { + LOGE("get tag failed!"); + goto clearup; + } + authTag.len = POLY1305_AUTH_TAG_LEN; + } else { + goto clearup; + } + + poly1305ParamsSpec->base.getType = GetPoly1305ParamsSpecType; + poly1305ParamsSpec->iv = *iv; + poly1305ParamsSpec->aad = *aad; + poly1305ParamsSpec->tag = opMode == DECRYPT_MODE ? *tag : authTag; + *paramsSpec = reinterpret_cast(poly1305ParamsSpec); + ret = true; +clearup: + if (!ret) { + HcfBlobDataFree(iv); + HcfBlobDataFree(aad); + HcfBlobDataFree(tag); + HCF_FREE_PTR(poly1305ParamsSpec); + } + HCF_FREE_PTR(iv); + HCF_FREE_PTR(aad); + HCF_FREE_PTR(tag); + return ret; +} + bool GetParamsSpecFromNapiValue(napi_env env, napi_value arg, HcfCryptoMode opMode, HcfParamsSpec **paramsSpec) { napi_value data = nullptr; @@ -574,6 +635,8 @@ bool GetParamsSpecFromNapiValue(napi_env env, napi_value arg, HcfCryptoMode opMo return GetGcmParamsSpec(env, arg, opMode, paramsSpec); } else if (algoName.compare(CCM_PARAMS_SPEC) == 0) { return GetCcmParamsSpec(env, arg, opMode, paramsSpec); + } else if (algoName.compare(POLY1305_PARAMS_SPEC) == 0) { + return GetPoly1305ParamsSpec(env, arg, opMode, paramsSpec); } else { return false; } diff --git a/frameworks/key/sym_key_generator.c b/frameworks/key/sym_key_generator.c index 3d8486d1e085d918f79cb694925cbf3e5a032e39..cdd9a8f1cf7d724560891506e66910e80adbae8d 100644 --- a/frameworks/key/sym_key_generator.c +++ b/frameworks/key/sym_key_generator.c @@ -38,6 +38,8 @@ #define HMAC_KEY_SIZE_SHA512 512 #define HMAC_KEY_SIZE_SM3 256 #define HMAC_KEY_SIZE_MD5 128 +#define CHACHA20_KEY_SIZE_256 256 +#define CHACHA20_POLY1305_KEY_SIZE_256 256 typedef HcfResult (*SymKeyGeneratorSpiCreateFunc)(SymKeyAttr *, HcfSymKeyGeneratorSpi **); @@ -61,7 +63,9 @@ static const SymKeyGenAbility SYMKEY_ABILITY_SET[] = { { HCF_ALG_SM4, { HcfSymKeyGeneratorSpiCreate }}, { HCF_ALG_DES, { HcfSymKeyGeneratorSpiCreate }}, { HCF_ALG_3DES, { HcfSymKeyGeneratorSpiCreate }}, - { HCF_ALG_HMAC, { HcfSymKeyGeneratorSpiCreate }} + { HCF_ALG_HMAC, { HcfSymKeyGeneratorSpiCreate }}, + { HCF_ALG_CHACHA20, { HcfSymKeyGeneratorSpiCreate }}, + { HCF_ALG_CHACHA20_POLY1305, { HcfSymKeyGeneratorSpiCreate }} }; static const SymKeyGenFuncSet *FindAbility(SymKeyAttr *attr) @@ -107,6 +111,10 @@ static void SetKeyLength(HcfAlgParaValue value, void *attr) keyAttr->algo = HCF_ALG_DES; keyAttr->keySize = DES_KEY_SIZE_64; break; + case HCF_ALG_CHACHA20_256: + keyAttr->algo = HCF_ALG_CHACHA20; + keyAttr->keySize = CHACHA20_KEY_SIZE_256; + break; default: break; } @@ -161,6 +169,8 @@ static HcfResult OnSetSymKeyParameter(const HcfParaConfig* config, void *attr) } HcfResult ret = HCF_SUCCESS; LOGD("Set Parameter:%s\n", config->tag); + LOGD("Set Parameter:%d\n", config->paraType); + LOGD("Set Parameter:%d\n", config->paraValue); switch (config->paraType) { case HCF_ALG_KEY_TYPE: SetKeyLength(config->paraValue, attr); diff --git a/interfaces/inner_api/algorithm_parameter/detailed_chacha20_params.h b/interfaces/inner_api/algorithm_parameter/detailed_chacha20_params.h new file mode 100644 index 0000000000000000000000000000000000000000..0e4e761895607b3b63a52af8365286fe0694508f --- /dev/null +++ b/interfaces/inner_api/algorithm_parameter/detailed_chacha20_params.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + #ifndef HCF_DETAILED_CHACHA20_PARAMS_H + #define HCF_DETAILED_CHACHA20_PARAMS_H + + #include + #include "algorithm_parameter.h" + #include "blob.h" + + typedef struct HcfChaCha20ParamsSpec HcfChaCha20ParamsSpec; + + struct HcfChaCha20ParamsSpec { + HcfParamsSpec base; + HcfBlob iv; + HcfBlob aad; + HcfBlob tag; + }; + + #endif // HCF_DETAILED_CHACHA20_PARAMS_H + \ No newline at end of file diff --git a/plugin/openssl_plugin.map b/plugin/openssl_plugin.map index 6a189088690a5257e7320a2f93d604a4c6454c13..4fdde7cae81f49635ee6e5747fd764c4ca1ace7a 100644 --- a/plugin/openssl_plugin.map +++ b/plugin/openssl_plugin.map @@ -16,6 +16,7 @@ HcfCipherRsaCipherSpiCreate; HcfCipherSm2CipherSpiCreate; HcfCipherAesGeneratorSpiCreate; + HcfCipherChaCha20GeneratorSpiCreate; HcfCipherDesGeneratorSpiCreate; HcfCipherSm4GeneratorSpiCreate; HcfAsyKeyGeneratorSpiRsaCreate; diff --git a/plugin/openssl_plugin/common/inc/aes_openssl_common.h b/plugin/openssl_plugin/common/inc/cipher_openssl_common.h similarity index 81% rename from plugin/openssl_plugin/common/inc/aes_openssl_common.h rename to plugin/openssl_plugin/common/inc/cipher_openssl_common.h index 2716e36bffa9f6ec5a17169aac7e484cc74a6871..71ef2a5aea239e9ec63eb8b351a2124d8df6763e 100644 --- a/plugin/openssl_plugin/common/inc/aes_openssl_common.h +++ b/plugin/openssl_plugin/common/inc/cipher_openssl_common.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Huawei Device Co., Ltd. + * Copyright (C) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,15 +13,17 @@ * limitations under the License. */ -#ifndef HCF_AES_OPENSSL_COMMON_H -#define HCF_AES_OPENSSL_COMMON_H +#ifndef HCF_CIPHER_OPENSSL_COMMON_H +#define HCF_CIPHER_OPENSSL_COMMON_H #include #include #include "aes_openssl.h" +#include "chacha20_openssl.h" #include "detailed_iv_params.h" #include "detailed_ccm_params.h" -#include "detailed_gcm_params.h" +#include "detailed_gcm_params.h" +#include "detailed_chacha20_params.h" typedef struct { EVP_CIPHER_CTX *ctx; @@ -49,6 +51,10 @@ int32_t GetCcmTagLen(HcfParamsSpec *params); void *GetCcmTag(HcfParamsSpec *params); +int32_t GetPoly1305TagLen(HcfParamsSpec *params); + +void *GetPoly1305Tag(HcfParamsSpec *params); + void FreeCipherData(CipherData **data); void FreeRedundantOutput(HcfBlob *blob); diff --git a/plugin/openssl_plugin/common/inc/openssl_adapter.h b/plugin/openssl_plugin/common/inc/openssl_adapter.h index f830458b651c148fc5bff7698b0ba99dd219b8b3..a6a897b8eb2895db3e4d578375b8f796651e18c5 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -308,6 +308,8 @@ const EVP_CIPHER *OpensslEvpDesOfb(void); const EVP_CIPHER *OpensslEvpDesCfb64(void); const EVP_CIPHER *OpensslEvpDesCfb1(void); const EVP_CIPHER *OpensslEvpDesCfb8(void); +const EVP_CIPHER *OpensslEvpChaCha20(void); +const EVP_CIPHER *OpensslEvpChaCha20Poly1305(void); EVP_CIPHER *OpensslEvpCipherFetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties); void OpensslEvpCipherFree(EVP_CIPHER *cipher); EVP_CIPHER_CTX *OpensslEvpCipherCtxNew(void); diff --git a/plugin/openssl_plugin/common/inc/openssl_class.h b/plugin/openssl_plugin/common/inc/openssl_class.h index 1af7c541154f9064fd2a3b6fc63fc8e490fcc2f4..544d5b27bd5a1637d7c14c1e2e50c07c2f35f1dc 100644 --- a/plugin/openssl_plugin/common/inc/openssl_class.h +++ b/plugin/openssl_plugin/common/inc/openssl_class.h @@ -174,5 +174,6 @@ typedef struct { #define OPENSSL_AES_CIPHER_CLASS "OPENSSL.AES.CIPHER" #define OPENSSL_SM4_CIPHER_CLASS "OPENSSL.SM4.CIPHER" #define OPENSSL_SM2_CIPHER_CLASS "OPENSSL.SM2.CIPHER" +#define OPENSSL_CHACHA20_CIPHER_CLASS "OPENSSL.CHACHA20.CIPHER" #endif diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index f4ec918e71f389bc50f8ff5498fefd36844d05f0..e4776af5238f43f7fca05cf84fefd488eb4d0654 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -1255,6 +1255,16 @@ const EVP_CIPHER *OpensslEvpDesCfb8(void) return EVP_des_cfb8(); } +const EVP_CIPHER *OpensslEvpChaCha20(void) +{ + return EVP_chacha20(); +} + +const EVP_CIPHER *OpensslEvpChaCha20Poly1305(void) +{ + return EVP_chacha20_poly1305(); +} + int OpensslSm2CipherTextSize(const EC_KEY *key, const EVP_MD *digest, size_t msgLen, size_t *cipherTextSize) { return ossl_sm2_ciphertext_size(key, digest, msgLen, cipherTextSize); diff --git a/plugin/openssl_plugin/crypto_operation/cipher/inc/chacha20_openssl.h b/plugin/openssl_plugin/crypto_operation/cipher/inc/chacha20_openssl.h new file mode 100644 index 0000000000000000000000000000000000000000..205f641b959a4710f9d7bca5057e1be8644e13d1 --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/inc/chacha20_openssl.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef HCF_CHACHA20_OPENSSL_H +#define HCF_CHACHA20_OPENSSL_H + +#include "cipher_factory_spi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +HcfResult HcfCipherChaCha20GeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_openssl.c index 462c45e8d3ae942c658eb69c9de63350f03dfc1d..713b48a13c43bb9c09cd607356a9b6ad2f20fbcf 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_openssl.c +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_openssl.c @@ -19,7 +19,7 @@ #include "memory.h" #include "result.h" #include "utils.h" -#include "aes_openssl_common.h" +#include "cipher_openssl_common.h" #include "sym_common_defines.h" #include "openssl_adapter.h" #include "openssl_common.h" diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_chacha20_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_chacha20_openssl.c new file mode 100644 index 0000000000000000000000000000000000000000..1744e54c7518050d656a7a5c7552995ffbd968bf --- /dev/null +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_chacha20_openssl.c @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "chacha20_openssl.h" +#include "log.h" +#include "blob.h" +#include "memory.h" +#include "result.h" +#include "utils.h" +#include "securec.h" +#include "sym_common_defines.h" +#include "openssl_adapter.h" +#include "openssl_common.h" +#include "openssl_class.h" +#include "cipher_openssl_common.h" + +typedef struct { + HcfCipherGeneratorSpi base; + CipherAttr attr; + CipherData *cipherData; +} HcfCipherChaCha20GeneratorSpiOpensslImpl; + +#define CHACHA20_KEY_LEN 32 +#define CHACHA20_IV_LEN 16 +#define CHACHA20_POLY1305_IV_LEN 12 +#define CHACHA20_BLOCK_SIZE 16 +#define POLY1305_TAG_SIZE 16 + + +static const char *GetChaCha20GeneratorClass(void) +{ + return OPENSSL_CHACHA20_CIPHER_CLASS; +} + +static const EVP_CIPHER *GetCipherType(HcfCipherChaCha20GeneratorSpiOpensslImpl *cipherImpl, SymKeyImpl *keyImpl) +{ + if (cipherImpl->attr.mode == HCF_ALG_MODE_POLY1305) { + return OpensslEvpChaCha20Poly1305(); + } else { + return OpensslEvpChaCha20(); + } + return NULL; +} + +static HcfResult ValidateCipherInitParams(HcfCipherGeneratorSpi *self, HcfKey *key) +{ + if ((self == NULL) || (key == NULL)) { + LOGE("Invalid input parameter."); + return HCF_INVALID_PARAMS; + } + if (!HcfIsClassMatch((const HcfObjectBase *)self, GetChaCha20GeneratorClass())) { + LOGE("Class is not match."); + return HCF_INVALID_PARAMS; + } + if (!HcfIsClassMatch((const HcfObjectBase *)key, OPENSSL_SYM_KEY_CLASS)) { + LOGE("Class is not match."); + return HCF_INVALID_PARAMS; + } + return HCF_SUCCESS; +} + +static bool IsPoly1305ParamsValid(HcfChaCha20ParamsSpec *params) +{ + if (params == NULL) { + LOGE("params is null!"); + return false; + } + if (params->iv.data == NULL || params->iv.len == 0 || params->iv.len != CHACHA20_POLY1305_IV_LEN) { + LOGE("iv is null or iv len is not equal to CHACHA20_POLY1305_IV_LEN!"); + return false; + } + if (params->tag.data == NULL || params->tag.len == 0) { + LOGE("tag is null!"); + return false; + } + return true; +} + +static HcfResult IsIvParamsValid(HcfIvParamsSpec *params) +{ + if (params == NULL) { + LOGE("params is null!"); + return HCF_INVALID_PARAMS; + } + if ((params->iv.data == NULL) || (params->iv.len != CHACHA20_IV_LEN)) { + LOGE("iv is invalid!"); + return HCF_INVALID_PARAMS; + } + return HCF_SUCCESS; +} + +static HcfResult InitAadAndTagFromPoly1305Params(enum HcfCryptoMode opMode, HcfChaCha20ParamsSpec *params, CipherData *data) +{ + if (!IsPoly1305ParamsValid(params)) { + LOGE("poly1305 params is invalid!"); + return HCF_INVALID_PARAMS; + } + if (params->aad.data != NULL && params->aad.len != 0) { + data->aad = (uint8_t *)HcfMalloc(params->aad.len, 0); + if (data->aad == NULL) { + LOGE("aad malloc failed!"); + return HCF_ERR_MALLOC; + } + (void)memcpy_s(data->aad, params->aad.len, params->aad.data, params->aad.len); + data->aadLen = params->aad.len; + data->aead = true; + } else { + data->aad = NULL; + data->aadLen = 0; + data->aead = false; + } + + data->tagLen = params->tag.len; + if (opMode == ENCRYPT_MODE) { + return HCF_SUCCESS; + } + data->tag = (uint8_t *)HcfMalloc(params->tag.len, 0); + if (data->tag == NULL) { + HcfFree(data->aad); + data->aad = NULL; + LOGE("tag malloc failed!"); + return HCF_ERR_MALLOC; + } + (void)memcpy_s(data->tag, params->tag.len, params->tag.data, params->tag.len); + return HCF_SUCCESS; +} + +static HcfResult InitCipherData(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode, + HcfParamsSpec *params, CipherData **cipherData) +{ + HcfResult ret = HCF_INVALID_PARAMS; + *cipherData = (CipherData *)HcfMalloc(sizeof(CipherData), 0); + if (*cipherData == NULL) { + LOGE("malloc failed."); + return HCF_ERR_MALLOC; + } + HcfCipherChaCha20GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherChaCha20GeneratorSpiOpensslImpl *)self; + HcfAlgParaValue mode = cipherImpl->attr.mode; + (*cipherData)->enc = opMode; + (*cipherData)->ctx = OpensslEvpCipherCtxNew(); + if ((*cipherData)->ctx == NULL) { + HcfPrintOpensslError(); + LOGD("[error] Failed to allocate ctx memroy."); + goto clearup; + } + ret = HCF_SUCCESS; + if (mode == HCF_ALG_MODE_POLY1305) { + ret = InitAadAndTagFromPoly1305Params(opMode, (HcfChaCha20ParamsSpec *)params, *cipherData); + } else { + ret = IsIvParamsValid((HcfIvParamsSpec *)params); + } + if (ret != HCF_SUCCESS) { + LOGE("init cipher data failed!"); + goto clearup; + } + return ret; +clearup: + FreeCipherData(cipherData); + return ret; +} + +static bool SetCipherAttribute(HcfCipherChaCha20GeneratorSpiOpensslImpl *cipherImpl, SymKeyImpl *keyImpl, + int enc, HcfParamsSpec *params) +{ + CipherData *data = cipherImpl->cipherData; + HcfAlgParaValue mode = cipherImpl->attr.mode; + const EVP_CIPHER *cipher = GetCipherType(cipherImpl, keyImpl); + if (cipher == NULL) { + HcfPrintOpensslError(); + LOGE("fetch cipher failed!"); + return false; + } + if (mode != HCF_ALG_MODE_POLY1305) { + if (OpensslEvpCipherInit(data->ctx, cipher, keyImpl->keyMaterial.data, + GetIv(params), enc) != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error] EVP_CipherInit failed!"); + return false; + } + return true; + } + if (OpensslEvpCipherInit(data->ctx, cipher, NULL, NULL, enc) != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error] EVP_CipherInit failed!"); + OpensslEvpCipherFree((EVP_CIPHER *)cipher); + return false; + } + OpensslEvpCipherFree((EVP_CIPHER *)cipher); + if (OpensslEvpCipherCtxCtrl(data->ctx, EVP_CTRL_AEAD_SET_IVLEN, + GetIvLen(params), NULL) != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]EVP_Cipher set iv len failed!"); + return false; + } + if (OpensslEvpCipherInit(data->ctx, NULL, keyImpl->keyMaterial.data, + GetIv(params), enc) != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]EVP_CipherInit failed!"); + return false; + } + return true; +} + +static HcfResult EngineCipherInit(HcfCipherGeneratorSpi *self, enum HcfCryptoMode opMode, + HcfKey *key, HcfParamsSpec *params) +{ + HcfResult ret = ValidateCipherInitParams(self, key); + if (ret != HCF_SUCCESS) { + return ret; + } + HcfCipherChaCha20GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherChaCha20GeneratorSpiOpensslImpl *)self; + SymKeyImpl *keyImpl = (SymKeyImpl *)key; + int32_t enc = (opMode == ENCRYPT_MODE) ? 1 : 0; + cipherImpl->attr.keySize = keyImpl->keyMaterial.len; + HcfResult res = InitCipherData(self, opMode, params, &(cipherImpl->cipherData)); + if (res != HCF_SUCCESS) { + LOGE("InitCipherData failed"); + return res; + } + ret = HCF_ERR_CRYPTO_OPERATION; + if (!SetCipherAttribute(cipherImpl, keyImpl, enc, params)) { + LOGE("Set cipher attribute failed!"); + goto clearup; + } + return HCF_SUCCESS; +clearup: + FreeCipherData(&(cipherImpl->cipherData)); + return ret; +} + +static HcfResult AllocateOutput(HcfBlob *input, HcfBlob *output, bool *isUpdateInput) +{ + uint32_t outLen = CHACHA20_BLOCK_SIZE + CHACHA20_BLOCK_SIZE; + if (HcfIsBlobValid(input)) { + outLen += input->len; + *isUpdateInput = true; + } + output->data = (uint8_t *)HcfMalloc(outLen, 0); + if (output->data == NULL) { + LOGE("malloc output failed!"); + return HCF_ERR_MALLOC; + } + output->len = outLen; + return HCF_SUCCESS; +} + +static HcfResult CommonUpdate(CipherData *data, HcfBlob *input, HcfBlob *output) +{ + int32_t ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len, + input->data, input->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]cipher update failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + return HCF_SUCCESS; +} + +static HcfResult AeadUpdate(CipherData *data, HcfAlgParaValue mode, HcfBlob *input, HcfBlob *output) +{ + LOGD("aad len: %{public}d", data->aadLen); + LOGD("aad data: %{public}s", data->aad); + + int32_t ret = OpensslEvpCipherUpdate(data->ctx, NULL, (int *)&output->len, data->aad, data->aadLen); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]aad cipher update failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len, input->data, input->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]poly1305 cipher update failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + return HCF_SUCCESS; +} + +static HcfResult EngineUpdate(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output) +{ + if ((self == NULL) || (input == NULL) || (output == NULL)) { + LOGE("Invalid input parameter."); + return HCF_INVALID_PARAMS; + } + if (!HcfIsClassMatch((HcfObjectBase *)self, self->base.getClass())) { + LOGE("Class is not match."); + return HCF_INVALID_PARAMS; + } + + HcfCipherChaCha20GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherChaCha20GeneratorSpiOpensslImpl *)self; + CipherData *data = cipherImpl->cipherData; + if (data == NULL) { + LOGE("cipherData is null!"); + return HCF_INVALID_PARAMS; + } + bool isUpdateInput = false; + HcfResult ret = AllocateOutput(input, output, &isUpdateInput); + if (ret != HCF_SUCCESS) { + LOGE("AllocateOutput failed!"); + return ret; + } + if (!data->aead) { + ret = CommonUpdate(data, input, output); + } else { + ret = AeadUpdate(data, cipherImpl->attr.mode, input, output); + } + if (ret != HCF_SUCCESS) { + HcfBlobDataClearAndFree(output); + FreeCipherData(&(cipherImpl->cipherData)); + return ret; + } + data->aead = false; + FreeRedundantOutput(output); + return ret; +} + +static HcfResult CommonDoFinal(CipherData *data, HcfBlob *input, HcfBlob *output) +{ + int32_t ret; + uint32_t len = 0; + bool isUpdateInput = false; + HcfResult res = AllocateOutput(input, output, &isUpdateInput); + if (res != HCF_SUCCESS) { + LOGE("AllocateOutput failed!"); + return res; + } + if (isUpdateInput) { + ret = OpensslEvpCipherUpdate(data->ctx, output->data, (int *)&output->len, input->data, input->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]EVP_CipherUpdate failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + len = output->len; + } + ret = OpensslEvpCipherFinalEx(data->ctx, output->data + len, (int *)&output->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGD("[error]EVP_CipherFinal_ex failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + output->len += len; + return HCF_SUCCESS; +} + +static HcfResult AllocatePoly1305Output(CipherData *data, HcfBlob *input, HcfBlob *output, bool *isUpdateInput) +{ + uint32_t outLen = 0; + if (HcfIsBlobValid(input)) { + outLen += input->len; + *isUpdateInput = true; + } + uint32_t authTagLen = (data->enc == ENCRYPT_MODE) ? POLY1305_TAG_SIZE : 0; + outLen += data->updateLen + authTagLen + CHACHA20_BLOCK_SIZE; + if (outLen == 0) { + LOGE("output size is invaild!"); + return HCF_INVALID_PARAMS; + } + output->data = (uint8_t *)HcfMalloc(outLen, 0); + if (output->data == NULL) { + LOGE("malloc output failed!"); + return HCF_ERR_MALLOC; + } + output->len = outLen; + return HCF_SUCCESS; +} +static HcfResult Poly1305EncryptDoFinal(CipherData *data, HcfBlob *output, uint32_t len) +{ + int32_t ret = OpensslEvpCipherFinalEx(data->ctx, output->data + len, (int *)&output->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGE("EVP_CipherFinal_ex failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + output->len += len; + ret = OpensslEvpCipherCtxCtrl(data->ctx, EVP_CTRL_AEAD_GET_TAG, data->tagLen, + output->data + output->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGE("get AuthTag failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + output->len += data->tagLen; + return HCF_SUCCESS; +} + +static HcfResult Poly1305DecryptDoFinal(CipherData *data, HcfBlob *output, uint32_t len) +{ + if (data->tag == NULL) { + LOGE("poly1305 decrypt has not AuthTag!"); + return HCF_INVALID_PARAMS; + } + int32_t ret = OpensslEvpCipherCtxCtrl(data->ctx, EVP_CTRL_AEAD_SET_TAG, data->tagLen, (void *)data->tag); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGE("poly1305 decrypt set AuthTag failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + ret = OpensslEvpCipherFinalEx(data->ctx, output->data + len, (int *)&output->len); + if (ret != HCF_OPENSSL_SUCCESS) { + HcfPrintOpensslError(); + LOGE("EVP_CipherFinal_ex failed!"); + return HCF_ERR_CRYPTO_OPERATION; + } + output->len = output->len + len; + return HCF_SUCCESS; +} + +static HcfResult Poly1305DoFinal(CipherData *data, HcfBlob *input, HcfBlob *output) +{ + bool isUpdateInput = false; + uint32_t len = 0; + HcfResult res = AllocatePoly1305Output(data, input, output, &isUpdateInput); + if (res != HCF_SUCCESS) { + LOGE("AllocateOutput failed!"); + return res; + } + if (isUpdateInput) { + if (data->aad != NULL && data->aadLen != 0) { + HcfResult result = AeadUpdate(data, HCF_ALG_MODE_POLY1305, input, output); + if (result != HCF_SUCCESS) { + LOGE("AeadUpdate failed!"); + return result; + } + } else { + HcfResult result = CommonUpdate(data, input, output); + if (result != HCF_SUCCESS) { + LOGE("No aad update failed!"); + return result; + } + } + len = output->len; + } + if (data->enc == ENCRYPT_MODE) { + return Poly1305EncryptDoFinal(data, output, len); + } else if (data->enc == DECRYPT_MODE) { + return Poly1305DecryptDoFinal(data, output, len); + } else { + return HCF_INVALID_PARAMS; + } +} + +static HcfResult EngineDoFinal(HcfCipherGeneratorSpi *self, HcfBlob *input, HcfBlob *output) +{ + if ((self == NULL) || (output == NULL)) { /* input maybe is null */ + LOGE("Invalid input parameter!"); + return HCF_INVALID_PARAMS; + } + if (!HcfIsClassMatch((HcfObjectBase *)self, self->base.getClass())) { + LOGE("Class is not match."); + return HCF_INVALID_PARAMS; + } + HcfCipherChaCha20GeneratorSpiOpensslImpl *cipherImpl = (HcfCipherChaCha20GeneratorSpiOpensslImpl *)self; + CipherData *data = cipherImpl->cipherData; + if (data == NULL) { + LOGE("cipherData is null!"); + return HCF_INVALID_PARAMS; + } + HcfResult ret = HCF_ERR_CRYPTO_OPERATION; + if (cipherImpl->attr.mode == HCF_ALG_MODE_POLY1305) { + ret = Poly1305DoFinal(data, input, output); + } else { + ret = CommonDoFinal(data, input, output); + } + FreeCipherData(&(cipherImpl->cipherData)); + if (ret != HCF_SUCCESS) { + HcfBlobDataClearAndFree(output); + } + FreeRedundantOutput(output); + return ret; +} + +static void EngineChaCha20GeneratorDestroy(HcfObjectBase *self) +{ + if (self == NULL) { + return; + } + if (!HcfIsClassMatch(self, GetChaCha20GeneratorClass())) { + LOGE("Class is not match."); + return; + } + + HcfCipherChaCha20GeneratorSpiOpensslImpl *impl = (HcfCipherChaCha20GeneratorSpiOpensslImpl *)self; + FreeCipherData(&(impl->cipherData)); + HcfFree(impl); +} + +static HcfResult GetChaCha20CipherSpecString(HcfCipherGeneratorSpi *self, CipherSpecItem item, char **returnString) +{ + (void)self; + (void)item; + (void)returnString; + return HCF_NOT_SUPPORT; +} + +static HcfResult GetChaCha20CipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob *returnUint8Array) +{ + (void)self; + (void)item; + (void)returnUint8Array; + return HCF_NOT_SUPPORT; +} + +static HcfResult SetChaCha20CipherSpecUint8Array(HcfCipherGeneratorSpi *self, CipherSpecItem item, HcfBlob blob) +{ + (void)self; + (void)item; + (void)blob; + return HCF_NOT_SUPPORT; +} + +HcfResult HcfCipherChaCha20GeneratorSpiCreate(CipherAttr *attr, HcfCipherGeneratorSpi **generator) +{ + if ((attr == NULL) || (generator == NULL)) { + LOGE("Invalid input parameter."); + return HCF_INVALID_PARAMS; + } + HcfCipherChaCha20GeneratorSpiOpensslImpl *returnImpl = (HcfCipherChaCha20GeneratorSpiOpensslImpl *)HcfMalloc( + sizeof(HcfCipherChaCha20GeneratorSpiOpensslImpl), 0); + if (returnImpl == NULL) { + LOGE("Failed to allocate returnImpl memroy."); + return HCF_ERR_MALLOC; + } + (void)memcpy_s(&returnImpl->attr, sizeof(CipherAttr), attr, sizeof(CipherAttr)); + returnImpl->base.init = EngineCipherInit; + returnImpl->base.update = EngineUpdate; + returnImpl->base.doFinal = EngineDoFinal; + returnImpl->base.getCipherSpecString = GetChaCha20CipherSpecString; + returnImpl->base.getCipherSpecUint8Array = GetChaCha20CipherSpecUint8Array; + returnImpl->base.setCipherSpecUint8Array = SetChaCha20CipherSpecUint8Array; + returnImpl->base.base.destroy = EngineChaCha20GeneratorDestroy; + returnImpl->base.base.getClass = GetChaCha20GeneratorClass; + + *generator = (HcfCipherGeneratorSpi *)returnImpl; + return HCF_SUCCESS; +} \ No newline at end of file diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c index 2fd8553fd25e1560ab9d44adbac97c56c20dc42c..e0038c6cafc46ce73095edabfa9523a44a12f4bd 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c @@ -20,7 +20,7 @@ #include "result.h" #include "utils.h" #include "securec.h" -#include "aes_openssl_common.h" +#include "cipher_openssl_common.h" #include "sym_common_defines.h" #include "openssl_adapter.h" #include "openssl_common.h" diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_common.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_openssl_common.c similarity index 82% rename from plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_common.c rename to plugin/openssl_plugin/crypto_operation/cipher/src/cipher_openssl_common.c index fae2f7e5c1559adc1db25afe77fc2dd9c9ae1c3a..97e151de5250f20340d9512c4cb2fd0a7e5fac76 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_aes_common.c +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_openssl_common.c @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "aes_openssl_common.h" +#include "cipher_openssl_common.h" #include "log.h" #include "memory.h" @@ -59,6 +59,26 @@ void *GetCcmTag(HcfParamsSpec *params) return (void *)tag; } +int32_t GetPoly1305TagLen(HcfParamsSpec *params) +{ + if (params == NULL) { + return 0; + } + HcfChaCha20ParamsSpec *spec = (HcfChaCha20ParamsSpec *)params; + size_t tagLen = spec->tag.len; + return (int32_t)tagLen; +} + +void *GetPoly1305Tag(HcfParamsSpec *params) +{ + if (params == NULL) { + return NULL; + } + HcfChaCha20ParamsSpec *spec = (HcfChaCha20ParamsSpec *)params; + uint8_t *tag = spec->tag.data; + return (void *)tag; +} + void FreeCipherData(CipherData **data) { if (data == NULL || *data == NULL) { diff --git a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c index 3b137073aaf26572df4a6d2884afc54e03dc3cfd..6f32704458bc4511f94bf294e7bc487b32fe393f 100644 --- a/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c +++ b/plugin/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c @@ -19,7 +19,7 @@ #include "memory.h" #include "result.h" #include "utils.h" -#include "aes_openssl_common.h" +#include "cipher_openssl_common.h" #include "sym_common_defines.h" #include "openssl_adapter.h" #include "openssl_common.h" diff --git a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c index ab72bfad9ec75fb187f9cec6a56db395931f67a4..2a6271aa965bea08495288cdd41a7016279ac7c7 100644 --- a/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c +++ b/plugin/openssl_plugin/key/sym_key_generator/src/sym_key_openssl.c @@ -30,6 +30,8 @@ #define DES_ALG_NAME "DES" #define TRIPLE_DES_ALG_NAME "3DES" #define HMAC_ALG_NAME "HMAC" +#define CHACHA20_ALG_NAME "ChaCha20" +#define CHACHA20_POLY1305_ALG_NAME "ChaCha20_Poly1305" typedef struct { HcfSymKeyGeneratorSpi base; @@ -240,6 +242,10 @@ static char *GetAlgoNameType(HcfAlgValue type) return TRIPLE_DES_ALG_NAME; case HCF_ALG_HMAC: return HMAC_ALG_NAME; + case HCF_ALG_CHACHA20: + return CHACHA20_ALG_NAME; + case HCF_ALG_CHACHA20_POLY1305: + return CHACHA20_POLY1305_ALG_NAME; default: LOGE("unsupport type!"); break; diff --git a/plugin/plugin.gni b/plugin/plugin.gni index c952c6e247f194b712d8e33716113ab06d54b8b6..4dcefb3e59ab5d393398070de700b8b108820fa6 100644 --- a/plugin/plugin.gni +++ b/plugin/plugin.gni @@ -72,11 +72,12 @@ plugin_cipher_files = [ "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_rsa_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_des_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_aes_openssl.c", - "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_aes_common.c", + "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_openssl_common.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm4_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_crypto_util_openssl.c", "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_sm2_ecdsa_signature_openssl.c", + "${plugin_path}/openssl_plugin/crypto_operation/cipher/src/cipher_chacha20_openssl.c" ] plugin_hmac_files = diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index dc9bfb0e771a23daae63e04980fa6b2a83d61087..13c943da3677648e20032379ccd14c93aeadb75e 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -49,6 +49,7 @@ ohos_unittest("crypto_framework_test") { "src/crypto_brainpool_key_agreement_test.cpp", "src/crypto_brainpool_no_length_sign_test.cpp", "src/crypto_brainpool_no_length_verify_test.cpp", + "src/crypto_chacha20_cipher_test.cpp", "src/crypto_cmac_test.cpp", "src/crypto_common_cov_test.cpp", "src/crypto_dh_asy_key_generator_by_spec_test.cpp", diff --git a/test/unittest/src/crypto_chacha20_cipher_test.cpp b/test/unittest/src/crypto_chacha20_cipher_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..050f829e9f20f92f8fabe45f45319979dd2e2fdc --- /dev/null +++ b/test/unittest/src/crypto_chacha20_cipher_test.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "securec.h" + +#include "sym_key_generator.h" +#include "cipher.h" +#include "log.h" +#include "memory.h" +#include "detailed_iv_params.h" +#include "detailed_chacha20_params.h" +#include "aes_common.h" + +using namespace std; +using namespace testing::ext; + +namespace { + +class CryptoChacha20CipherTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void CryptoChacha20CipherTest::SetUpTestCase() {} +void CryptoChacha20CipherTest::TearDownTestCase() {} + +void CryptoChacha20CipherTest::SetUp() // add init here, this will be called before test. +{ +} + +void CryptoChacha20CipherTest::TearDown() // add destroy here, this will be called when test case done. +{ +} + +static HcfResult GenerateChacha20SymKey(HcfSymKey **key) +{ + HcfSymKeyGenerator *generator = nullptr; + + HcfResult ret = HcfSymKeyGeneratorCreate("ChaCha20", &generator); + if (ret != HCF_SUCCESS) { + LOGE("HcfSymKeyGeneratorCreate failed!"); + return ret; + } + + ret = generator->generateSymKey(generator, key); + if (ret != HCF_SUCCESS) { + LOGE("generateSymKey failed!"); + } + HcfObjDestroy(generator); + return ret; +} + +static int32_t Chacha20Encrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, + uint8_t *cipherText, int *cipherTextLen) +{ + uint8_t plainText[] = "this is test!"; + HcfBlob input = {.data = (uint8_t *)plainText, .len = 13}; + HcfBlob output = {}; + int32_t maxLen = *cipherTextLen; + int32_t ret = cipher->init(cipher, ENCRYPT_MODE, (HcfKey *)key, params); + if (ret != 0) { + LOGE("init failed! %{public}d", ret); + return ret; + } + + ret = cipher->update(cipher, &input, &output); + if (ret != 0) { + LOGE("update failed!"); + return ret; + } + *cipherTextLen = output.len; + if (output.data != nullptr) { + if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { + HcfBlobDataFree(&output); + return -1; + } + HcfBlobDataFree(&output); + } + + ret = cipher->doFinal(cipher, nullptr, &output); + if (ret != 0) { + LOGE("doFinal failed!"); + return ret; + } + if (output.data != nullptr) { + if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) { + HcfBlobDataFree(&output); + return -1; + } + *cipherTextLen += output.len; + HcfBlobDataFree(&output); + } + return 0; +} + +static int32_t Chacha20Decrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, + uint8_t *cipherText, int cipherTextLen) +{ + uint8_t plainText[] = "this is test!"; + HcfBlob input = {.data = (uint8_t *)cipherText, .len = cipherTextLen}; + HcfBlob output = {}; + int32_t maxLen = cipherTextLen; + int32_t ret = cipher->init(cipher, DECRYPT_MODE, (HcfKey *)key, params); + if (ret != 0) { + LOGE("init failed! %{public}d", ret); + return ret; + } + + ret = cipher->update(cipher, &input, &output); + if (ret != 0) { + LOGE("update failed!"); + return ret; + } + cipherTextLen = output.len; + if (output.data != nullptr) { + if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { + HcfBlobDataFree(&output); + return -1; + } + HcfBlobDataFree(&output); + } + + ret = cipher->doFinal(cipher, nullptr, &output); + if (ret != 0) { + LOGE("doFinal failed!"); + return ret; + } + if (output.data != nullptr) { + if (memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len) != EOK) { + HcfBlobDataFree(&output); + return -1; + } + cipherTextLen += output.len; + HcfBlobDataFree(&output); + } + + if (cipherTextLen != sizeof(plainText) - 1) { + return -1; + } + return memcmp(cipherText, plainText, cipherTextLen); +} + +HWTEST_F(CryptoChacha20CipherTest, CryptoChacha20CipherTest001, TestSize.Level0) +{ + uint8_t cipherText[128] = {0}; + int cipherTextLen = 128; + + HcfCipher *cipher = nullptr; + HcfSymKey *key = nullptr; + + int ret = GenerateChacha20SymKey(&key); + ASSERT_EQ(ret, 0); + + ret = HcfCipherCreate("ChaCha20", &cipher); + ASSERT_EQ(ret, 0); + + ret = Chacha20Encrypt(cipher, key, nullptr, cipherText, &cipherTextLen); + ASSERT_NE(ret, 0); + + HcfObjDestroy((HcfObjectBase *)key); + HcfObjDestroy((HcfObjectBase *)cipher); +} + +HWTEST_F(CryptoChacha20CipherTest, CryptoChacha20CipherTest002, TestSize.Level0) +{ + uint8_t cipherText[128] = {0}; + int cipherTextLen = 128; + + HcfCipher *cipher = nullptr; + HcfSymKey *key = nullptr; + + uint8_t iv[16] = {0}; + HcfIvParamsSpec ivSpec = {}; + ivSpec.iv.data = iv; + ivSpec.iv.len = 16; + + int ret = GenerateChacha20SymKey(&key); + ASSERT_EQ(ret, 0); + + ret = HcfCipherCreate("ChaCha20", &cipher); + ASSERT_EQ(ret, 0); + + ret = Chacha20Encrypt(cipher, key, (HcfParamsSpec *)&ivSpec, cipherText, &cipherTextLen); + ASSERT_EQ(ret, 0); + + ret = Chacha20Decrypt(cipher, key, (HcfParamsSpec *)&ivSpec, cipherText, cipherTextLen); + ASSERT_EQ(ret, 0); + + HcfObjDestroy((HcfObjectBase *)key); + HcfObjDestroy((HcfObjectBase *)cipher); +} + +HWTEST_F(CryptoChacha20CipherTest, CryptoChacha20CipherTest003, TestSize.Level0) +{ + uint8_t cipherText[128] = {0}; + int cipherTextLen = 128; + + HcfCipher *cipher = nullptr; + HcfSymKey *key = nullptr; + + uint8_t aad[8] = {0}; + uint8_t tag[16] = {0}; + uint8_t iv[12] = {0}; // openssl only support nonce 12 bytes, tag 16bytes + + HcfChaCha20ParamsSpec spec = {}; + spec.aad.data = aad; + spec.aad.len = sizeof(aad); + spec.tag.data = tag; + spec.tag.len = sizeof(tag); + spec.iv.data = iv; + spec.iv.len = sizeof(iv); + + int ret = GenerateChacha20SymKey(&key); + ASSERT_EQ(ret, 0); + + ret = HcfCipherCreate("ChaCha20|Poly1305", &cipher); + ASSERT_EQ(ret, 0); + + ret = Chacha20Encrypt(cipher, key, (HcfParamsSpec *)&spec, cipherText, &cipherTextLen); + ASSERT_EQ(ret, 0); + + (void)memcpy_s(spec.tag.data, 16, cipherText + cipherTextLen - 16, 16); + PrintfHex("chacha20 tag", spec.tag.data, spec.tag.len); + cipherTextLen -= 16; + + ret = Chacha20Decrypt(cipher, key, (HcfParamsSpec *)&spec, cipherText, cipherTextLen); + ASSERT_EQ(ret, 0); + + HcfObjDestroy((HcfObjectBase *)key); + HcfObjDestroy((HcfObjectBase *)cipher); +} + +HWTEST_F(CryptoChacha20CipherTest, CryptoChacha20CipherTest004, TestSize.Level0) +{ + uint8_t cipherText[128] = {0}; + int cipherTextLen = 128; + + HcfCipher *cipher = nullptr; + HcfSymKey *key = nullptr; + + uint8_t aad[8] = {0}; + uint8_t tag[16] = {0}; + uint8_t iv[16] = {0}; + + HcfChaCha20ParamsSpec spec = {}; + spec.aad.data = aad; + spec.aad.len = sizeof(aad); + spec.tag.data = tag; + spec.tag.len = sizeof(tag); + spec.iv.data = iv; + spec.iv.len = sizeof(iv); + + int ret = GenerateChacha20SymKey(&key); + ASSERT_EQ(ret, 0); + + ret = HcfCipherCreate("ChaCha20|Poly1305", &cipher); + ASSERT_EQ(ret, 0); + + ret = Chacha20Encrypt(cipher, key, (HcfParamsSpec *)&spec, cipherText, &cipherTextLen); + ASSERT_EQ(ret, HCF_INVALID_PARAMS); + + HcfObjDestroy((HcfObjectBase *)key); + HcfObjDestroy((HcfObjectBase *)cipher); +} +} + + \ No newline at end of file diff --git a/test/unittest/src/openssl_adapter_mock.c b/test/unittest/src/openssl_adapter_mock.c index 3d18180a19e56d09c65756510646c713a9db7b5a..d592a993d690a4f569dc76ce5123e17635f4dbeb 100644 --- a/test/unittest/src/openssl_adapter_mock.c +++ b/test/unittest/src/openssl_adapter_mock.c @@ -2324,3 +2324,13 @@ int OpensslEvpEncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, { return EVP_EncryptInit(ctx, cipher, key, iv); } + +const EVP_CIPHER *OpensslEvpChaCha20(void) +{ + return EVP_chacha20(); +} + +const EVP_CIPHER *OpensslEvpChaCha20Poly1305(void) +{ + return EVP_chacha20_poly1305(); +}