diff --git a/frameworks/native/BUILD.gn b/frameworks/native/BUILD.gn index 3bf85f5517b226c1b89eeaf301943d5e2e2be34a..3db40d5e0190326d33e11c1180bd66702642f1be 100644 --- a/frameworks/native/BUILD.gn +++ b/frameworks/native/BUILD.gn @@ -49,7 +49,10 @@ ohos_shared_library("ohcrypto") { deps = [ "${framework_path}:crypto_framework_lib" ] - external_deps = [ "hilog:libhilog" ] + external_deps = [ + "hilog:libhilog", + "bounds_checking_function:libsec_shared" + ] subsystem_name = "security" output_extension = "so" diff --git a/frameworks/native/include/native_common.h b/frameworks/native/include/native_common.h index dc4bff0940294491c1fd9f8af5854ba0a7273ade..7bfd68b16acb743b0892990b7f20be1e70b47291 100644 --- a/frameworks/native/include/native_common.h +++ b/frameworks/native/include/native_common.h @@ -24,6 +24,7 @@ extern "C" { #endif OH_Crypto_ErrCode GetOhCryptoErrCode(HcfResult errCode); +OH_Crypto_ErrCode GetOhCryptoErrCodeNew(HcfResult errCode); #ifdef __cplusplus } diff --git a/frameworks/native/src/asym_key.c b/frameworks/native/src/asym_key.c index 5007aa7400aa794cdbfb5510b23a896316320874..9d9732356b83987747c7573cd06ca49d40d683b5 100644 --- a/frameworks/native/src/asym_key.c +++ b/frameworks/native/src/asym_key.c @@ -138,6 +138,14 @@ OH_CryptoPubKey *OH_CryptoKeyPair_GetPubKey(OH_CryptoKeyPair *keyCtx) return (OH_CryptoPubKey *)keyCtx->pubKey; } +OH_CryptoPrivKey *OH_CryptoKeyPair_GetPrivKey(OH_CryptoKeyPair *keyCtx) +{ + if (keyCtx == NULL) { + return NULL; + } + return (OH_CryptoPrivKey *)keyCtx->priKey; +} + OH_Crypto_ErrCode OH_CryptoPubKey_Encode(OH_CryptoPubKey *key, Crypto_EncodingType type, const char *encodingStandard, Crypto_DataBlob *out) { diff --git a/frameworks/native/src/native_common.c b/frameworks/native/src/native_common.c index 65b23823e9b3cba427eee59fa44e820ac540b0f6..7123ccec1f6e9855c9c757f4ce5cddd805575bbc 100644 --- a/frameworks/native/src/native_common.c +++ b/frameworks/native/src/native_common.c @@ -29,4 +29,20 @@ OH_Crypto_ErrCode GetOhCryptoErrCode(HcfResult errCode) default: return CRYPTO_OPERTION_ERROR; } +} + +OH_Crypto_ErrCode GetOhCryptoErrCodeNew(HcfResult errCode) +{ + switch (errCode) { + case HCF_SUCCESS: + return CRYPTO_SUCCESS; + case HCF_INVALID_PARAMS: + return CRYPTO_PARAMETER_CHECK_FAILED; + case HCF_NOT_SUPPORT: + return CRYPTO_NOT_SUPPORTED; + case HCF_ERR_MALLOC: + return CRYPTO_MEMORY_ERROR; + default: + return CRYPTO_OPERTION_ERROR; + } } \ No newline at end of file diff --git a/frameworks/native/src/signature.c b/frameworks/native/src/signature.c index c619321f860e74be2b2a2a6ee871b88e8dd460fc..5d49bd1d363d5b4cfc6f1bf84c49589de0821d6e 100644 --- a/frameworks/native/src/signature.c +++ b/frameworks/native/src/signature.c @@ -14,6 +14,8 @@ */ #include "crypto_signature.h" +#include "sm2_ec_signature_data.h" +#include "securec.h" #include #include #include "signature.h" @@ -46,6 +48,26 @@ struct OH_CryptoVerify { HcfResult (*setVerifySpecUint8Array)(HcfVerify *self, SignSpecItem item, HcfBlob blob); }; +struct OH_CryptoSign { + HcfObjectBase base; + + HcfResult (*init)(HcfSign *self, HcfParamsSpec *params, HcfPriKey *privateKey); + + HcfResult (*update)(HcfSign *self, HcfBlob *data); + + HcfResult (*sign)(HcfSign *self, HcfBlob *data, HcfBlob *returnSignatureData); + + const char *(*getAlgoName)(HcfSign *self); + + HcfResult (*setSignSpecInt)(HcfSign *self, SignSpecItem item, int32_t saltLen); + + HcfResult (*getSignSpecString)(HcfSign *self, SignSpecItem item, char **returnString); + + HcfResult (*getSignSpecInt)(HcfSign *self, SignSpecItem item, int32_t *returnInt); + + HcfResult (*setSignSpecUint8Array)(HcfSign *self, SignSpecItem item, HcfBlob blob); +}; + OH_Crypto_ErrCode OH_CryptoVerify_Create(const char *algoName, OH_CryptoVerify **verify) { if (verify == NULL) { @@ -193,3 +215,281 @@ void OH_CryptoVerify_Destroy(OH_CryptoVerify *ctx) } ctx->base.destroy((HcfObjectBase *)ctx); } + +OH_Crypto_ErrCode OH_CryptoSign_Create(const char *algoName, OH_CryptoSign **sign) +{ + if (sign == NULL) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfResult ret = HcfSignCreate(algoName, (HcfSign **)sign); + return GetOhCryptoErrCodeNew(ret); +} + +OH_Crypto_ErrCode OH_CryptoSign_Init(OH_CryptoSign *ctx, OH_CryptoPrivKey *privKey) +{ + if ((ctx == NULL) || (ctx->init == NULL) || (privKey == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfResult ret = ctx->init((HcfSign *)ctx, NULL, (HcfPriKey *)privKey); + return GetOhCryptoErrCodeNew(ret); +} + +OH_Crypto_ErrCode OH_CryptoSign_Update(OH_CryptoSign *ctx, const Crypto_DataBlob *in) +{ + if ((ctx == NULL) || (ctx->update == NULL) || (in == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfResult ret = ctx->update((HcfSign *)ctx, (HcfBlob *)in); + return GetOhCryptoErrCodeNew(ret); +} + +OH_Crypto_ErrCode OH_CryptoSign_Final(OH_CryptoSign *ctx, const Crypto_DataBlob *in, Crypto_DataBlob *out) +{ + if ((ctx == NULL) || (ctx->sign == NULL) || (out == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfResult ret = ctx->sign((HcfSign *)ctx, (HcfBlob *)in, (HcfBlob *)out); + return GetOhCryptoErrCodeNew(ret); +} + +const char *OH_CryptoSign_GetAlgoName(OH_CryptoSign *ctx) +{ + if ((ctx == NULL) || (ctx->getAlgoName == NULL)) { + return NULL; + } + return ctx->getAlgoName((HcfSign *)ctx); +} + +OH_Crypto_ErrCode OH_CryptoSign_SetParam(OH_CryptoSign *ctx, CryptoSignature_ParamType type, + const Crypto_DataBlob *value) +{ + if ((ctx == NULL) || (value == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfResult ret = HCF_INVALID_PARAMS; + switch (type) { + case CRYPTO_PSS_SALT_LEN_INT: + case CRYPTO_PSS_TRAILER_FIELD_INT: + if ((value->data == NULL) || (value->len != sizeof(int32_t)) || (ctx->setSignSpecInt == NULL)) { + ret = HCF_INVALID_PARAMS; + break; + } + ret = ctx->setSignSpecInt((HcfSign *)ctx, (SignSpecItem)type, *((int32_t *)value->data)); + break; + case CRYPTO_SM2_USER_ID_DATABLOB: + case CRYPTO_PSS_MGF1_NAME_STR: + case CRYPTO_PSS_MGF_NAME_STR: + case CRYPTO_PSS_MD_NAME_STR: + if (ctx->setSignSpecUint8Array == NULL) { + ret = HCF_INVALID_PARAMS; + break; + } + ret = ctx->setSignSpecUint8Array((HcfSign *)ctx, (SignSpecItem)type, *((HcfBlob *)value)); + break; + default: + return CRYPTO_PARAMETER_CHECK_FAILED; + } + return GetOhCryptoErrCodeNew(ret); +} + +OH_Crypto_ErrCode OH_CryptoSign_GetParam(OH_CryptoSign *ctx, CryptoSignature_ParamType type, Crypto_DataBlob *value) +{ + if ((ctx == NULL) || (value == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + int32_t *returnInt = NULL; + char *returnStr = NULL; + HcfResult ret = HCF_INVALID_PARAMS; + switch (type) { + case CRYPTO_PSS_SALT_LEN_INT: + case CRYPTO_PSS_TRAILER_FIELD_INT: + case CRYPTO_SM2_USER_ID_DATABLOB: + if (ctx->getSignSpecInt == NULL) { + ret = HCF_INVALID_PARAMS; + break; + } + returnInt = (int32_t *)HcfMalloc(sizeof(int32_t), 0); + if (returnInt == NULL) { + return CRYPTO_MEMORY_ERROR; + } + ret = ctx->getSignSpecInt((HcfSign *)ctx, (SignSpecItem)type, returnInt); + if (ret != HCF_SUCCESS) { + HcfFree(returnInt); + break; + } + value->data = (uint8_t *)returnInt; + value->len = sizeof(int32_t); + break; + case CRYPTO_PSS_MD_NAME_STR: + case CRYPTO_PSS_MGF_NAME_STR: + case CRYPTO_PSS_MGF1_NAME_STR: + if (ctx->getSignSpecString == NULL) { + ret = HCF_INVALID_PARAMS; + break; + } + ret = ctx->getSignSpecString((HcfSign *)ctx, (SignSpecItem)type, &returnStr); + if (ret != HCF_SUCCESS) { + break; + } + value->data = (uint8_t *)returnStr; + value->len = strlen(returnStr); + break; + default: + return CRYPTO_PARAMETER_CHECK_FAILED; + } + return GetOhCryptoErrCodeNew(ret); +} + +void OH_CryptoSign_Destroy(OH_CryptoSign *ctx) +{ + if (ctx == NULL || ctx->base.destroy == NULL) { + return; + } + ctx->base.destroy((HcfObjectBase *)ctx); +} + +struct OH_CryptoEccSignatureSpec { + HcfBigInteger r; + HcfBigInteger s; +}; + + +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_Create(Crypto_DataBlob *EccSignature, OH_CryptoEccSignatureSpec **spec) +{ + if (spec == NULL) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfResult ret = HCF_INVALID_PARAMS; + if (EccSignature == NULL) { + *spec = (OH_CryptoEccSignatureSpec *)HcfMalloc(sizeof(OH_CryptoEccSignatureSpec), 0); + if (*spec == NULL) { + return CRYPTO_MEMORY_ERROR; + } + return GetOhCryptoErrCodeNew(HCF_SUCCESS); + } + ret = HcfGenEcSignatureSpecByData((HcfBlob *)EccSignature, (Sm2EcSignatureDataSpec **)spec); + return GetOhCryptoErrCodeNew(ret); +} + +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_GetRAndS(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *r, + Crypto_DataBlob *s) +{ + if ((spec == NULL) || (r == NULL) || (s == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + if ((spec->r.data == NULL) || (spec->s.data == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + + // Allocate memory for r->data + r->data = (uint8_t *)HcfMalloc(spec->r.len, 0); + if (r->data == NULL) { + return CRYPTO_MEMORY_ERROR; + } + + // Copy data for r + if (memcpy_s(r->data, spec->r.len, spec->r.data, spec->r.len) != 0) { + HcfFree(r->data); + r->data = NULL; // Ensure pointer is null after freeing + return CRYPTO_MEMORY_ERROR; + } + r->len = (size_t)spec->r.len; + + // Allocate memory for s->data + s->data = (uint8_t *)HcfMalloc(spec->s.len, 0); + if (s->data == NULL) { + HcfFree(r->data); + r->data = NULL; // Ensure pointer is null after freeing + return CRYPTO_MEMORY_ERROR; + } + + // Copy data for s + if (memcpy_s(s->data, spec->s.len, spec->s.data, spec->s.len) != 0) { + HcfFree(r->data); + r->data = NULL; // Ensure pointer is null after freeing + HcfFree(s->data); + s->data = NULL; // Ensure pointer is null after freeing + return CRYPTO_MEMORY_ERROR; + } + s->len = (size_t)spec->s.len; + + return GetOhCryptoErrCodeNew(HCF_SUCCESS); +} + +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_SetRAndS(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *r, + Crypto_DataBlob *s) +{ + if ((spec == NULL) || (r == NULL) || (s == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + if (r->data == NULL || s->data == NULL) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + + // Allocate memory for r->data + spec->r.data = (unsigned char *)HcfMalloc(r->len, 0); + if (spec->r.data == NULL) { + return CRYPTO_MEMORY_ERROR; + } + if (memcpy_s(spec->r.data, r->len, r->data, r->len) != 0) { + HcfFree(spec->r.data); + spec->r.data = NULL; + return CRYPTO_MEMORY_ERROR; + } + spec->r.len = (uint32_t)r->len; + + // Allocate memory for s->data + spec->s.data = (unsigned char *)HcfMalloc(s->len, 0); + if (spec->s.data == NULL) { + HcfFree(spec->r.data); + spec->r.data = NULL; + return CRYPTO_MEMORY_ERROR; + } + if (memcpy_s(spec->s.data, s->len, s->data, s->len) != 0) { + HcfFree(spec->r.data); + HcfFree(spec->s.data); + spec->r.data = NULL; + spec->s.data = NULL; + return CRYPTO_MEMORY_ERROR; + } + spec->s.len = (uint32_t)s->len; + + return GetOhCryptoErrCodeNew(HCF_SUCCESS); +} + +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_Encode(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *out) +{ + if ((spec == NULL) || (out == NULL)) { + return CRYPTO_PARAMETER_CHECK_FAILED; + } + HcfBlob *outBlob = (HcfBlob *)HcfMalloc(sizeof(HcfBlob), 0); + if (outBlob == NULL) { + return CRYPTO_MEMORY_ERROR; + } + + HcfResult ret = HcfGenEcSignatureDataBySpec((Sm2EcSignatureDataSpec *)spec, outBlob); + if (ret != HCF_SUCCESS) { + HcfFree(outBlob); + return GetOhCryptoErrCode(ret); + } + out->data = outBlob->data; + out->len = outBlob->len; + HcfFree(outBlob); + return GetOhCryptoErrCodeNew(HCF_SUCCESS); +} + +void OH_CryptoEccSignatureSpec_Destroy(OH_CryptoEccSignatureSpec *spec) +{ + if (spec == NULL) { + return; + } + if (spec->r.data != NULL) { + HcfFree(spec->r.data); + spec->r.data = NULL; + } + if (spec->s.data != NULL) { + HcfFree(spec->s.data); + spec->s.data = NULL; + } + HcfFree(spec); +} \ No newline at end of file diff --git a/interfaces/kits/native/include/crypto_asym_key.h b/interfaces/kits/native/include/crypto_asym_key.h index ea16609c6b9b43007eb8b6abf5d4f96cf34b55d3..f5be1dab6cd3f910b452081a334cbd9b01cecb0c 100644 --- a/interfaces/kits/native/include/crypto_asym_key.h +++ b/interfaces/kits/native/include/crypto_asym_key.h @@ -56,6 +56,13 @@ typedef struct OH_CryptoKeyPair OH_CryptoKeyPair; */ typedef struct OH_CryptoPubKey OH_CryptoPubKey; +/** + * @brief Define the private Key structure. + * + * @since 12 + */ +typedef struct OH_CryptoPrivKey OH_CryptoPrivKey; + /** * @brief Define the asymmetric key parameter types. * @@ -227,6 +234,15 @@ void OH_CryptoKeyPair_Destroy(OH_CryptoKeyPair *keyCtx); */ OH_CryptoPubKey *OH_CryptoKeyPair_GetPubKey(OH_CryptoKeyPair *keyCtx); +/** + * @brief Get the private key of the key pair. + * + * @param keyCtx Indicates the keyPair context. + * @return Return the private key context from the key pair. + * @since 20 + */ +OH_CryptoPrivKey *OH_CryptoKeyPair_GetPrivKey(OH_CryptoKeyPair *keyCtx); + /** * @brief Encode the public key. * diff --git a/interfaces/kits/native/include/crypto_common.h b/interfaces/kits/native/include/crypto_common.h index 64c0f7af9f6cb4825852ae7bb8f28a9ba6645efc..9da7d4e654d5fe911c3cfdb2be9801fed1a6796f 100644 --- a/interfaces/kits/native/include/crypto_common.h +++ b/interfaces/kits/native/include/crypto_common.h @@ -69,6 +69,8 @@ typedef enum { CRYPTO_NOT_SUPPORTED = 801, /** Indicates the memory error. */ CRYPTO_MEMORY_ERROR = 17620001, + /** Indicates that parameter check failed. */ + CRYPTO_PARAMETER_CHECK_FAILED = 17620003, /** Indicates that crypto operation error. */ CRYPTO_OPERTION_ERROR = 17630001, } OH_Crypto_ErrCode; diff --git a/interfaces/kits/native/include/crypto_signature.h b/interfaces/kits/native/include/crypto_signature.h index eb77a1bf24a0420022c639d9e48682a2fe1f31c6..c16d649319ee1d61d1b55aaf6691e0994e6d8f8f 100644 --- a/interfaces/kits/native/include/crypto_signature.h +++ b/interfaces/kits/native/include/crypto_signature.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Huawei Device Co., Ltd. + * Copyright (C) 2024-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 @@ -28,7 +28,7 @@ * @brief Defines the Signature APIs. * * @library libohcrypto.so - * @kit Crypto Architecture Kit + * @kit CryptoArchitectureKit * @syscap SystemCapability.Security.CryptoFramework * @since 12 */ @@ -71,6 +71,13 @@ typedef enum { */ typedef struct OH_CryptoVerify OH_CryptoVerify; +/** + * @brief Defines the sign structure. + * + * @since 20 + */ +typedef struct OH_CryptoSign OH_CryptoSign; + /** * @brief Create a verify context according to the given algorithm name. * @@ -159,8 +166,8 @@ const char *OH_CryptoVerify_GetAlgoName(OH_CryptoVerify *ctx); * @brief Set the specified parameter to the verify context. * * @param ctx Indicates the verify context. - * @param type Indicates the verify signature_paramType. - * @param value Indicates the verify result. + * @param type Indicates the verify parameter type. + * @param value Indicates the input data. * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. @@ -175,8 +182,8 @@ OH_Crypto_ErrCode OH_CryptoVerify_SetParam(OH_CryptoVerify *ctx, CryptoSignature * @brief Get the specified parameter from the verify context. * * @param ctx Indicates the verify context. - * @param type Indicates the verify signature_paramType. - * @param value Indicates the verify result. + * @param type Indicates the verify parameter type. + * @param value Indicates the output data. * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. @@ -195,9 +202,199 @@ OH_Crypto_ErrCode OH_CryptoVerify_GetParam(OH_CryptoVerify *ctx, CryptoSignature */ void OH_CryptoVerify_Destroy(OH_CryptoVerify *ctx); +/** + * @brief Creates a sign context according to the given algorithm name. + * + * @param algoName Indicates the algorithm name for generating the sign context. e.g. "RSA|PKCS1|SHA384", "ECC|SHA384". + * @param sign Indicates the sign context. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoSign_Create(const char *algoName, OH_CryptoSign **sign); + +/** + * @brief Initializes the sign context. + * + * @param ctx Indicates the sign context. + * @param privKey Indicates the private key. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @see OH_CryptoSign_Update + * @see OH_CryptoSign_Final + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoSign_Init(OH_CryptoSign *ctx, OH_CryptoPrivKey *privKey); + +/** + * @brief Updates the data to be signed. + * + * @param ctx Indicates the sign context. + * @param in Indicates the data to be signed. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @see OH_CryptoSign_Init + * @see OH_CryptoSign_Final + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoSign_Update(OH_CryptoSign *ctx, const Crypto_DataBlob *in); + +/** + * @brief Finalizes the sign operation. + * + * @param ctx Indicates the sign context. + * @param in Indicates the data to be signed, if OH_CryptoSign_Update has been called, this parameter can be NULL. + * @param out Indicates the sign result. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @see OH_CryptoSign_Init + * @see OH_CryptoSign_Update + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoSign_Final(OH_CryptoSign *ctx, const Crypto_DataBlob *in, Crypto_DataBlob *out); + +/** + * @brief Gets the algorithm name of the sign context. + * + * @param ctx Indicates the sign context. + * @return Return signature algorithm name. + * @since 20 + */ +const char *OH_CryptoSign_GetAlgoName(OH_CryptoSign *ctx); + +/** + * @brief Sets the specified parameter to the sign context. + * + * @param ctx Indicates the sign context. + * @param type Indicates the signature parameter type. + * @param value Indicates the input data. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoSign_SetParam(OH_CryptoSign *ctx, CryptoSignature_ParamType type, + const Crypto_DataBlob *value); + +/** + * @brief Gets the specified parameter from the sign context. + * + * @param ctx Indicates the sign context. + * @param type Indicates the signature parameter type. + * @param value Indicates the output data. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoSign_GetParam(OH_CryptoSign *ctx, CryptoSignature_ParamType type, Crypto_DataBlob *value); + +/** + * @brief Destroys the sign context. + * + * @param ctx Indicates the sign context. + * @since 20 + */ +void OH_CryptoSign_Destroy(OH_CryptoSign *ctx); + +/** + * @brief Defines the ECC signature spec. + * + * @since 20 + */ +typedef struct OH_CryptoEccSignatureSpec OH_CryptoEccSignatureSpec; + +/** + * @brief Creates the ECC signature spec, also support SM2 signature. + * + * @param EccSignature Indicates the ECC signature in DER format, if EccSignature parameter is NULL, + * an empty ECC signature spec will be created. + * @param spec Indicates the output ECC signature spec. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_Create(Crypto_DataBlob *EccSignature, + OH_CryptoEccSignatureSpec **spec); + +/** + * @brief Gets the r and s value from the ECC signature spec. + * + * @param spec Indicates the ECC signature spec. + * @param r Indicates the output r value. + * @param s Indicates the output s value. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_GetRAndS(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *r, + Crypto_DataBlob *s); + +/** + * @brief Sets the r and s value to the ECC signature spec. + * + * @param spec Indicates the ECC signature spec. + * @param r Indicates the input r value. + * @param s Indicates the input s value. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_SetRAndS(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *r, + Crypto_DataBlob *s); + +/** + * @brief Encodes the ECC signature spec to signature data in DER format. + * + * @param spec Indicates the ECC signature spec. + * @param out Indicates the output data blob. + * @return {@link OH_Crypto_ErrCode#CRYPTO_SUCCESS} 0 - If the operation is successful. + * {@link OH_Crypto_ErrCode#CRYPTO_INVALID_PARAMS} 401 - If parameter is invalid. + * {@link OH_Crypto_ErrCode#CRYPTO_NOT_SUPPORTED} 801 - If the operation is not supported. + * {@link OH_Crypto_ErrCode#CRYPTO_MEMORY_ERROR} 17620001 - If memory operation failed. + * {@link OH_Crypto_ErrCode#CRYPTO_OPERTION_ERROR} 17630001 - If crypto operation failed. + * @since 20 + */ +OH_Crypto_ErrCode OH_CryptoEccSignatureSpec_Encode(OH_CryptoEccSignatureSpec *spec, Crypto_DataBlob *out); + +/** + * @brief Destroys the ECC signature spec. + * + * @param spec Indicates the ECC signature spec. + * @since 20 + */ +void OH_CryptoEccSignatureSpec_Destroy(OH_CryptoEccSignatureSpec *spec); + + #ifdef __cplusplus } #endif /** @} */ #endif /* CRYPTO_SIGNATURE_H */ + \ No newline at end of file diff --git a/test/unittest/src/native/native_signature_test.cpp b/test/unittest/src/native/native_signature_test.cpp index 9443c127c17de119406c01acd64dab2d86f45fd7..1b40d7c4cd59721f5e30ce162f36699fcd25554e 100644 --- a/test/unittest/src/native/native_signature_test.cpp +++ b/test/unittest/src/native/native_signature_test.cpp @@ -18,6 +18,7 @@ #include "crypto_common.h" #include "crypto_asym_key.h" #include "log.h" +#include "blob.h" #include "memory.h" #include "memory_mock.h" @@ -62,7 +63,7 @@ HWTEST_F(NativeSignatureTest, NativeSignatureTest001, TestSize.Level0) ASSERT_NE(algoName, nullptr); int32_t buf[] = {32}; - Crypto_DataBlob value = { .data = reinterpret_cast(buf), .len = sizeof(buf) }; + Crypto_DataBlob value = {.data = reinterpret_cast(buf), .len = sizeof(buf)}; res = OH_CryptoVerify_SetParam(verify, CRYPTO_PSS_SALT_LEN_INT, &value); EXPECT_EQ(res, CRYPTO_SUCCESS); res = OH_CryptoVerify_Init(verify, pubkey); @@ -97,38 +98,32 @@ HWTEST_F(NativeSignatureTest, NativeSignatureTest003, TestSize.Level0) OH_CryptoVerify *verify = nullptr; uint8_t plainText[] = { - 0xe4, 0x2b, 0xcc, 0x08, 0x11, 0x79, 0x16, 0x1b, 0x35, 0x7f, 0xb3, 0xaf, 0x40, 0x3b, 0x3f, 0x7c - }; + 0xe4, 0x2b, 0xcc, 0x08, 0x11, 0x79, 0x16, 0x1b, 0x35, 0x7f, 0xb3, 0xaf, 0x40, 0x3b, 0x3f, 0x7c}; Crypto_DataBlob msgBlob = { .data = reinterpret_cast(plainText), - .len = sizeof(plainText) - }; + .len = sizeof(plainText)}; uint8_t pubKeyText[] = { 0x30, 0x39, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x22, 0x00, 0x03, 0x4d, 0xe4, 0xbb, 0x11, 0x10, 0x1a, 0xd2, 0x05, 0x74, 0xf1, 0x0b, 0xb4, 0x75, 0x57, 0xf4, 0x3e, 0x55, 0x14, 0x17, 0x05, 0x4a, - 0xb2, 0xfb, 0x8c, 0x84, 0x64, 0x38, 0x02, 0xa0, 0x2a, 0xa6, 0xf0 - }; + 0xb2, 0xfb, 0x8c, 0x84, 0x64, 0x38, 0x02, 0xa0, 0x2a, 0xa6, 0xf0}; Crypto_DataBlob keyBlob = { .data = reinterpret_cast(pubKeyText), - .len = sizeof(pubKeyText) - }; + .len = sizeof(pubKeyText)}; uint8_t signText[] = { 0x30, 0x44, 0x02, 0x20, 0x21, 0x89, 0x99, 0xb1, 0x56, 0x4e, 0x3a, 0x2c, 0x16, 0x08, 0xb5, 0x8a, 0x06, 0x6f, 0x67, 0x47, 0x1b, 0x04, 0x18, 0x7d, 0x53, 0x2d, 0xba, 0x00, 0x38, 0xd9, 0xe3, 0xe7, 0x8c, 0xcf, 0x76, 0x83, 0x02, 0x20, 0x13, 0x54, 0x84, 0x9d, 0x73, 0x40, 0xc3, 0x92, 0x66, 0xdc, 0x3e, 0xc9, 0xf1, 0x4c, 0x33, 0x84, 0x2a, 0x76, 0xaf, 0xc6, 0x61, 0x84, 0x5c, 0xae, 0x4b, 0x0d, - 0x3c, 0xb0, 0xc8, 0x04, 0x89, 0x71 - }; + 0x3c, 0xb0, 0xc8, 0x04, 0x89, 0x71}; Crypto_DataBlob signBlob = { .data = reinterpret_cast(signText), - .len = sizeof(signText) - }; - + .len = sizeof(signText)}; + // keypair ASSERT_EQ(OH_CryptoAsymKeyGenerator_Create((const char *)"ECC256", &keyCtx), CRYPTO_SUCCESS); ASSERT_EQ(OH_CryptoAsymKeyGenerator_Convert(keyCtx, CRYPTO_DER, &keyBlob, nullptr, &keyPair), CRYPTO_SUCCESS); @@ -142,4 +137,221 @@ HWTEST_F(NativeSignatureTest, NativeSignatureTest003, TestSize.Level0) OH_CryptoAsymKeyGenerator_Destroy(keyCtx); OH_CryptoKeyPair_Destroy(keyPair); } + +HWTEST_F(NativeSignatureTest, NativeSignatureTest_Sign001, TestSize.Level0) +{ + OH_CryptoAsymKeyGenerator *generator = nullptr; + OH_Crypto_ErrCode res = OH_CryptoAsymKeyGenerator_Create("RSA2048|PRIMES_2", &generator); + EXPECT_EQ(res, CRYPTO_SUCCESS); + + OH_CryptoKeyPair *keyPair = nullptr; + res = OH_CryptoAsymKeyGenerator_Generate(generator, &keyPair); + EXPECT_EQ(res, CRYPTO_SUCCESS); + + OH_CryptoPrivKey *privKey = OH_CryptoKeyPair_GetPrivKey(keyPair); + ASSERT_NE(privKey, nullptr); + + OH_CryptoSign *sign = nullptr; + res = OH_CryptoSign_Create("RSA2048|PKCS1|SHA256", &sign); + EXPECT_EQ(res, CRYPTO_SUCCESS); + ASSERT_NE(sign, nullptr); + + const char *algoName = OH_CryptoSign_GetAlgoName(sign); + ASSERT_NE(algoName, nullptr); + EXPECT_STREQ(algoName, "RSA2048|PKCS1|SHA256"); + + res = OH_CryptoSign_Init(sign, privKey); + EXPECT_EQ(res, CRYPTO_SUCCESS); + + uint8_t plainText[] = { + 0xe4, 0x2b, 0xcc, 0x08, 0x11, 0x79, 0x16, 0x1b, 0x35, 0x7f, 0xb3, 0xaf, 0x40, 0x3b, 0x3f, 0x7c}; + Crypto_DataBlob msgBlob = { + .data = reinterpret_cast(plainText), + .len = sizeof(plainText)}; + + res = OH_CryptoSign_Update(sign, &msgBlob); + EXPECT_EQ(res, CRYPTO_SUCCESS); + + Crypto_DataBlob signBlob = {.data = nullptr, .len = 0}; + res = OH_CryptoSign_Final(sign, nullptr, &signBlob); + EXPECT_EQ(res, CRYPTO_SUCCESS); + ASSERT_NE(signBlob.data, nullptr); + ASSERT_GT(signBlob.len, 0); + + // Clean up + free(signBlob.data); + OH_CryptoSign_Destroy(sign); + OH_CryptoKeyPair_Destroy(keyPair); + OH_CryptoAsymKeyGenerator_Destroy(generator); +} + +HWTEST_F(NativeSignatureTest, NativeSignatureTest_Sign002, TestSize.Level0) +{ + OH_CryptoSign *sign = nullptr; + OH_Crypto_ErrCode res = OH_CryptoSign_Create("RSA2048|PSS|SHA256|MGF1_SHA256", &sign); + EXPECT_EQ(res, CRYPTO_SUCCESS); + ASSERT_NE(sign, nullptr); + + const char *algoName = OH_CryptoSign_GetAlgoName(sign); + ASSERT_NE(algoName, nullptr); + EXPECT_STREQ(algoName, "RSA2048|PSS|SHA256|MGF1_SHA256"); + + uint8_t buf[] = {32}; + Crypto_DataBlob value = {.data = reinterpret_cast(buf), .len = sizeof(buf)}; + res = OH_CryptoSign_SetParam(sign, CRYPTO_PSS_SALT_LEN_INT, &value); + EXPECT_EQ(res, CRYPTO_PARAMETER_CHECK_FAILED); + + Crypto_DataBlob outValue = {.data = nullptr, .len = 0}; + res = OH_CryptoSign_GetParam(sign, CRYPTO_PSS_SALT_LEN_INT, &outValue); + EXPECT_EQ(res, CRYPTO_PARAMETER_CHECK_FAILED); + + OH_CryptoSign_Destroy(sign); +} + +HWTEST_F(NativeSignatureTest, NativeSignatureTest_Sign003, TestSize.Level0) +{ + OH_CryptoAsymKeyGenerator *keyCtx = nullptr; + OH_CryptoKeyPair *keyPair = nullptr; + OH_CryptoSign *sign = nullptr; + + uint8_t plainText[] = { + 0xe4, 0x2b, 0xcc, 0x08, 0x11, 0x79, 0x16, 0x1b, 0x35, 0x7f, 0xb3, 0xaf, 0x40, 0x3b, 0x3f, 0x7c}; + Crypto_DataBlob msgBlob = { + .data = reinterpret_cast(plainText), + .len = sizeof(plainText)}; + + ASSERT_EQ(OH_CryptoAsymKeyGenerator_Create((const char *)"ECC256", &keyCtx), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoAsymKeyGenerator_Generate(keyCtx, &keyPair), CRYPTO_SUCCESS); + + OH_CryptoPrivKey *privKey = OH_CryptoKeyPair_GetPrivKey(keyPair); + ASSERT_NE(privKey, nullptr); + + ASSERT_EQ(OH_CryptoSign_Create((const char *)"ECC|SHA256", &sign), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoSign_Init(sign, privKey), CRYPTO_SUCCESS); + + ASSERT_EQ(OH_CryptoSign_Update(sign, &msgBlob), CRYPTO_SUCCESS); + + Crypto_DataBlob signBlob = {.data = nullptr, .len = 0}; + ASSERT_EQ(OH_CryptoSign_Final(sign, nullptr, &signBlob), CRYPTO_SUCCESS); + ASSERT_NE(signBlob.data, nullptr); + ASSERT_GT(signBlob.len, 0); + + // Clean up + free(signBlob.data); + OH_CryptoSign_Destroy(sign); + OH_CryptoAsymKeyGenerator_Destroy(keyCtx); + OH_CryptoKeyPair_Destroy(keyPair); +} + +HWTEST_F(NativeSignatureTest, NativeSignatureTest_SignVerify001, TestSize.Level0) +{ + OH_CryptoAsymKeyGenerator *keyCtx = nullptr; + OH_CryptoKeyPair *keyPair = nullptr; + OH_CryptoSign *sign = nullptr; + + uint8_t plainText[] = { + 0xe4, 0x2b, 0xcc, 0x08, 0x11, 0x79, 0x16, 0x1b, 0x35, 0x7f, 0xb3, 0xaf, 0x40, 0x3b, 0x3f, 0x7c}; + Crypto_DataBlob msgBlob = { + .data = reinterpret_cast(plainText), + .len = sizeof(plainText)}; + ASSERT_EQ(OH_CryptoAsymKeyGenerator_Create((const char *)"RSA2048|PRIMES_2", &keyCtx), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoAsymKeyGenerator_Generate(keyCtx, &keyPair), CRYPTO_SUCCESS); + OH_CryptoPrivKey *privKey = OH_CryptoKeyPair_GetPrivKey(keyPair); + ASSERT_NE(privKey, nullptr); + ASSERT_EQ(OH_CryptoSign_Create((const char *)"RSA1024|PSS|SHA256|MGF1_SHA512", &sign), CRYPTO_SUCCESS); + int32_t saltText = 32; + Crypto_DataBlob saltBlob = { + .data = (uint8_t *)&saltText, + .len = sizeof(int32_t) + }; + ASSERT_EQ(OH_CryptoSign_SetParam(sign, CRYPTO_PSS_SALT_LEN_INT, &saltBlob), CRYPTO_SUCCESS); + + Crypto_DataBlob outValue = {.data = nullptr, .len = 0}; + ASSERT_EQ(OH_CryptoSign_GetParam(sign, CRYPTO_PSS_SALT_LEN_INT, &outValue), CRYPTO_SUCCESS); + ASSERT_EQ(outValue.len, sizeof(int32_t)); + ASSERT_EQ(*(int32_t *)outValue.data, saltText); + ASSERT_EQ(OH_CryptoSign_Init(sign, privKey), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoSign_Update(sign, &msgBlob), CRYPTO_SUCCESS); + Crypto_DataBlob signBlob = {.data = nullptr, .len = 0}; + ASSERT_EQ(OH_CryptoSign_Final(sign, nullptr, &signBlob), CRYPTO_SUCCESS); + ASSERT_NE(signBlob.data, nullptr); + ASSERT_GT(signBlob.len, 0); + + OH_CryptoPubKey *pubkey = OH_CryptoKeyPair_GetPubKey(keyPair); + OH_CryptoVerify *verify = nullptr; + OH_Crypto_ErrCode res = OH_CryptoVerify_Create("RSA1024|PSS|SHA256|MGF1_SHA512", &verify); + ASSERT_EQ(res, CRYPTO_SUCCESS); + const char *algoName = OH_CryptoVerify_GetAlgoName(verify); + ASSERT_NE(algoName, nullptr); + int32_t buf[] = {32}; + Crypto_DataBlob value = {.data = reinterpret_cast(buf), .len = sizeof(buf)}; + res = OH_CryptoVerify_SetParam(verify, CRYPTO_PSS_SALT_LEN_INT, &value); + ASSERT_EQ(res, CRYPTO_SUCCESS); + res = OH_CryptoVerify_Init(verify, pubkey); + ASSERT_EQ(res, CRYPTO_SUCCESS); + bool result = OH_CryptoVerify_Final(verify, &msgBlob, &signBlob); + ASSERT_EQ(result, 1); + HcfBlobDataClearAndFree((HcfBlob *)&signBlob); + OH_CryptoVerify_Destroy(verify); + OH_CryptoSign_Destroy(sign); + OH_CryptoKeyPair_Destroy(keyPair); + OH_CryptoAsymKeyGenerator_Destroy(keyCtx); +} + +HWTEST_F(NativeSignatureTest, NativeSignatureTest_DerToRS001, TestSize.Level0) +{ + OH_CryptoAsymKeyGenerator *keyCtx = nullptr; + OH_CryptoKeyPair *keyPair = nullptr; + OH_CryptoSign *sign = nullptr; + + uint8_t plainText[] = { + 0xe4, 0x2b, 0xcc, 0x08, 0x11, 0x79, 0x16, 0x1b, 0x35, 0x7f, 0xb3, 0xaf, 0x40, 0x3b, 0x3f, 0x7c}; + Crypto_DataBlob msgBlob = { + .data = reinterpret_cast(plainText), + .len = sizeof(plainText)}; + + ASSERT_EQ(OH_CryptoAsymKeyGenerator_Create((const char *)"SM2_256", &keyCtx), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoAsymKeyGenerator_Generate(keyCtx, &keyPair), CRYPTO_SUCCESS); + + OH_CryptoPrivKey *privKey = OH_CryptoKeyPair_GetPrivKey(keyPair); + ASSERT_NE(privKey, nullptr); + + ASSERT_EQ(OH_CryptoSign_Create((const char *)"SM2|SM3", &sign), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoSign_Init(sign, privKey), CRYPTO_SUCCESS); + + ASSERT_EQ(OH_CryptoSign_Update(sign, &msgBlob), CRYPTO_SUCCESS); + + Crypto_DataBlob signBlob = {.data = nullptr, .len = 0}; + ASSERT_EQ(OH_CryptoSign_Final(sign, nullptr, &signBlob), CRYPTO_SUCCESS); + ASSERT_NE(signBlob.data, nullptr); + ASSERT_GT(signBlob.len, 0); + + OH_CryptoEccSignatureSpec *eccSignSpec = nullptr; + ASSERT_EQ(OH_CryptoEccSignatureSpec_Create(&signBlob, &eccSignSpec), CRYPTO_SUCCESS); + ASSERT_NE(eccSignSpec, nullptr); + Crypto_DataBlob r = {.data = nullptr, .len = 0}; + Crypto_DataBlob s = {.data = nullptr, .len = 0}; + ASSERT_EQ(OH_CryptoEccSignatureSpec_GetRAndS(eccSignSpec, &r, &s), CRYPTO_SUCCESS); + ASSERT_NE(r.data, nullptr); + ASSERT_NE(s.data, nullptr); + OH_CryptoEccSignatureSpec_Destroy(eccSignSpec); + OH_CryptoEccSignatureSpec *eccSignSpec1 = nullptr; + Crypto_DataBlob signBlob1 = {.data = nullptr, .len = 0}; + ASSERT_EQ(OH_CryptoEccSignatureSpec_Create(nullptr, &eccSignSpec1), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoEccSignatureSpec_SetRAndS(eccSignSpec1, &r, &s), CRYPTO_SUCCESS); + ASSERT_EQ(OH_CryptoEccSignatureSpec_Encode(eccSignSpec1, &signBlob1), CRYPTO_SUCCESS); + ASSERT_NE(signBlob1.data, nullptr); + ASSERT_GT(signBlob1.len, 0); + + + // Clean up + HcfBlobDataClearAndFree((HcfBlob *)&signBlob); + HcfBlobDataClearAndFree((HcfBlob *)&signBlob1); + HcfBlobDataClearAndFree((HcfBlob *)&r); + HcfBlobDataClearAndFree((HcfBlob *)&s); + OH_CryptoSign_Destroy(sign); + OH_CryptoEccSignatureSpec_Destroy(eccSignSpec1); + OH_CryptoAsymKeyGenerator_Destroy(keyCtx); + OH_CryptoKeyPair_Destroy(keyPair); +} } \ No newline at end of file