diff --git a/common/inc/params_parser.h b/common/inc/params_parser.h index 8fd6422d5e4c9e9e62de31609cace30a69d02f8e..6c6cd188e6a606dba1ba8489080a7a441338398d 100644 --- a/common/inc/params_parser.h +++ b/common/inc/params_parser.h @@ -28,6 +28,7 @@ typedef enum { HCF_ALG_DIGEST, HCF_ALG_MGF1_DIGEST, HCF_ALG_TEXT_FORMAT, + HCF_ALG_VERIFY_TYPE, } HcfAlgParaType; typedef enum { @@ -165,6 +166,8 @@ typedef enum { HCF_OPENSSL_DH_FFDHE_4096, HCF_OPENSSL_DH_FFDHE_6144, HCF_OPENSSL_DH_FFDHE_8192, + + HCF_ALG_VERIFY_RECOVER, } HcfAlgParaValue; typedef struct { @@ -203,6 +206,7 @@ typedef struct { HcfAlgParaValue padding; HcfAlgParaValue md; HcfAlgParaValue mgf1md; + HcfAlgParaValue operation; } HcfSignatureParams; typedef struct { diff --git a/common/src/params_parser.c b/common/src/params_parser.c index ab7f8fe4a0dd9e8510b53c06d4df754b844bfb82..6c18bc7046a5f32a411796fb5ecf971c8e14ea16 100644 --- a/common/src/params_parser.c +++ b/common/src/params_parser.c @@ -133,7 +133,9 @@ static const HcfParaConfig PARAM_CONFIG[] = { {"ECC_BrainPoolP512t1", HCF_ALG_KEY_TYPE, HCF_ALG_ECC_BP512T1}, {"Ed25519", HCF_ALG_KEY_TYPE, HCF_ALG_ED25519_256}, - {"X25519", HCF_ALG_KEY_TYPE, HCF_ALG_X25519_256} + {"X25519", HCF_ALG_KEY_TYPE, HCF_ALG_X25519_256}, + + {"Recover", HCF_ALG_VERIFY_TYPE, HCF_ALG_VERIFY_RECOVER} }; static const HcfAlgMap ALG_MAP[] = { diff --git a/frameworks/crypto_operation/signature.c b/frameworks/crypto_operation/signature.c index da3cac429f92a3c59429127c26a8d1c6610b4677..bb003ea5819e988f4f91cf9b3c67ca3c769e2159 100644 --- a/frameworks/crypto_operation/signature.c +++ b/frameworks/crypto_operation/signature.c @@ -200,6 +200,9 @@ static HcfResult ParseSignatureParams(const HcfParaConfig *config, void *params) case HCF_ALG_MGF1_DIGEST: paramsObj->mgf1md = config->paraValue; break; + case HCF_ALG_VERIFY_TYPE: + paramsObj->operation = config->paraValue; + break; default: ret = HCF_INVALID_PARAMS; break; @@ -466,6 +469,25 @@ static bool VerifyDoFinal(HcfVerify *self, HcfBlob *data, HcfBlob *signatureData return ((HcfVerifyImpl *)self)->spiObj->engineVerify(((HcfVerifyImpl *)self)->spiObj, data, signatureData); } +static HcfResult VerifyRecover(HcfVerify *self, HcfBlob *signatureData, HcfBlob *rawSignatureData) +{ + if (self == NULL) { + LOGE("Invalid input parameter."); + return HCF_INVALID_PARAMS; + } + if (!IsClassMatch((HcfObjectBase *)self, GetVerifyClass())) { + LOGE("Class not match."); + return HCF_INVALID_PARAMS; + } + + if (((HcfVerifyImpl *)self)->spiObj->engineVerifyRecover == NULL) { + LOGE("Not support verify recover operation."); + return HCF_INVALID_PARAMS; + } + + return ((HcfVerifyImpl *)self)->spiObj->engineVerifyRecover(((HcfVerifyImpl *)self)->spiObj, signatureData, rawSignatureData); +} + HcfResult HcfSignCreate(const char *algoName, HcfSign **returnObj) { LOGD("HcfSignCreate start"); @@ -531,6 +553,11 @@ HcfResult HcfVerifyCreate(const char *algoName, HcfVerify **returnObj) return HCF_INVALID_PARAMS; } + if (params.operation == HCF_ALG_VERIFY_RECOVER && params.algo != HCF_ALG_RSA) { + LOGE("Failed to check recover params!"); + return HCF_INVALID_PARAMS; + } + HcfVerifySpiCreateFunc createSpiFunc = FindVerifyAbility(¶ms); if (createSpiFunc == NULL) { return HCF_NOT_SUPPORT; @@ -559,6 +586,7 @@ HcfResult HcfVerifyCreate(const char *algoName, HcfVerify **returnObj) returnVerify->base.init = VerifyInit; returnVerify->base.update = VerifyUpdate; returnVerify->base.verify = VerifyDoFinal; + returnVerify->base.verifyRecover = VerifyRecover; returnVerify->base.setVerifySpecInt = SetVerifySpecInt; returnVerify->base.getVerifySpecInt = GetVerifySpecInt; returnVerify->base.getVerifySpecString = GetVerifySpecString; diff --git a/frameworks/js/napi/crypto/inc/napi_verify.h b/frameworks/js/napi/crypto/inc/napi_verify.h index f7211ab5c9641b15abb10d3b6698f99e61174ae7..2965671e7678299d80f438f35db3b7ad9eab4486 100644 --- a/frameworks/js/napi/crypto/inc/napi_verify.h +++ b/frameworks/js/napi/crypto/inc/napi_verify.h @@ -38,6 +38,8 @@ public: static napi_value JsInit(napi_env env, napi_callback_info info); static napi_value JsUpdate(napi_env env, napi_callback_info info); static napi_value JsVerify(napi_env env, napi_callback_info info); + static napi_value JsVerifyRecover(napi_env env, napi_callback_info info); + static napi_value JsVerifyRecoverSync(napi_env env, napi_callback_info info); static napi_value JsSetVerifySpec(napi_env env, napi_callback_info info); static napi_value JsGetVerifySpec(napi_env env, napi_callback_info info); diff --git a/frameworks/js/napi/crypto/src/napi_verify.cpp b/frameworks/js/napi/crypto/src/napi_verify.cpp index 6f587f84abb37f06a892a35156b9074c17282061..49605888308fc9adf11796be14c2ea730e986ad7 100644 --- a/frameworks/js/napi/crypto/src/napi_verify.cpp +++ b/frameworks/js/napi/crypto/src/napi_verify.cpp @@ -77,6 +77,21 @@ struct VerifyDoFinalCtx { bool isVerifySucc; }; +struct VerifyRecoverCtx { + napi_env env = nullptr; + + napi_deferred deferred = nullptr; + napi_value promise = nullptr; + napi_async_work asyncWork = nullptr; + + HcfVerify *verify = nullptr; + HcfBlob *signatureData = nullptr; + + HcfResult errCode = HCF_SUCCESS; + const char *errMsg = nullptr; + HcfBlob rawSignatureData; +}; + thread_local napi_ref NapiVerify::classRef_ = nullptr; static void FreeVerifyInitCtx(napi_env env, VerifyInitCtx *ctx) @@ -142,6 +157,28 @@ static void FreeVerifyDoFinalCtx(napi_env env, VerifyDoFinalCtx *ctx) HcfFree(ctx); } +static void FreeVerifyRecoverCtx(napi_env env, VerifyRecoverCtx *ctx) +{ + if (ctx == nullptr) { + return; + } + + if (ctx->asyncWork != nullptr) { + napi_delete_async_work(env, ctx->asyncWork); + ctx->asyncWork = nullptr; + } + + if (ctx->rawSignatureData.data != nullptr) { + HcfFree(ctx->rawSignatureData.data); + ctx->rawSignatureData.data = nullptr; + ctx->rawSignatureData.len = 0; + } + + HcfBlobDataFree(ctx->signatureData); + HcfFree(ctx->signatureData); + HcfFree(ctx); +} + static bool BuildVerifyJsInitCtx(napi_env env, napi_callback_info info, VerifyInitCtx *ctx) { napi_value thisVar = nullptr; @@ -369,6 +406,15 @@ static void ReturnDoFinalPromiseResult(napi_env env, VerifyDoFinalCtx *ctx, napi } } +static void ReturnRecoverPromiseResult(napi_env env, VerifyRecoverCtx *ctx, napi_value result) +{ + if (ctx->errCode == HCF_SUCCESS) { + napi_resolve_deferred(env, ctx->deferred, result); + } else { + napi_reject_deferred(env, ctx->deferred, GenerateBusinessError(env, ctx->errCode, ctx->errMsg)); + } +} + static void VerifyJsInitAsyncWorkProcess(napi_env env, void *data) { VerifyInitCtx *ctx = static_cast(data); @@ -444,6 +490,31 @@ static void VerifyJsDoFinalAsyncWorkReturn(napi_env env, napi_status status, voi FreeVerifyDoFinalCtx(env, ctx); } +static void VerifyJsRecoverAsyncWorkProcess(napi_env env, void *data) +{ + VerifyRecoverCtx *ctx = static_cast(data); + + ctx->errCode = ctx->verify->verifyRecover(ctx->verify, ctx->signatureData, &ctx->rawSignatureData); + if (ctx->errCode != HCF_SUCCESS) { + LOGD("[error] verify revover fail."); + ctx->errMsg = "verify revover fail."; + } +} + +static void VerifyJsRecoverAsyncWorkReturn(napi_env env, napi_status status, void *data) +{ + VerifyRecoverCtx *ctx = static_cast(data); + + napi_value dataBlob = nullptr; + if (ctx->errCode == HCF_SUCCESS) { + dataBlob = ConvertBlobToNapiValue(env, &ctx->rawSignatureData); + } + + ReturnRecoverPromiseResult(env, ctx, dataBlob); + + FreeVerifyRecoverCtx(env, ctx); +} + static napi_value NewVerifyJsInitAsyncWork(napi_env env, VerifyInitCtx *ctx) { napi_value resourceName = nullptr; @@ -522,6 +593,28 @@ static napi_value NewVerifyJsDoFinalAsyncWork(napi_env env, VerifyDoFinalCtx *ct } } +static napi_value NewVerifyJsRecoverAsyncWork(napi_env env, VerifyRecoverCtx *ctx) +{ + napi_value resourceName = nullptr; + napi_create_string_utf8(env, "verify", NAPI_AUTO_LENGTH, &resourceName); + + napi_create_async_work( + env, nullptr, resourceName, + [](napi_env env, void *data) { + VerifyJsRecoverAsyncWorkProcess(env, data); + return; + }, + [](napi_env env, napi_status status, void *data) { + VerifyJsRecoverAsyncWorkReturn(env, status, data); + return; + }, + static_cast(ctx), + &ctx->asyncWork); + + napi_queue_async_work(env, ctx->asyncWork); + return ctx->promise; +} + NapiVerify::NapiVerify(HcfVerify *verify) { this->verify_ = verify; @@ -594,6 +687,113 @@ napi_value NapiVerify::JsVerify(napi_env env, napi_callback_info info) return NewVerifyJsDoFinalAsyncWork(env, ctx); } +static bool BuildVerifyJsRecoverCtx(napi_env env, napi_callback_info info, VerifyRecoverCtx *ctx) +{ + napi_value thisVar = nullptr; + size_t expectedArgc = PARAMS_NUM_ONE; + size_t argc = PARAMS_NUM_ONE; + napi_value argv[PARAMS_NUM_ONE] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + if (argc != expectedArgc) { + LOGE("wrong argument num. require %zu arguments. [Argc]: %zu!", expectedArgc, argc); + return false; + } + + NapiVerify *napiVerify = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&napiVerify)); + if (status != napi_ok || napiVerify == nullptr) { + LOGE("failed to unwrap napi verify obj."); + return false; + } + + ctx->verify = napiVerify->GetVerify(); + if (ctx->verify == nullptr) { + LOGE("failed to get verify obj."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "fail to get verify obj.")); + return false; + } + + HcfBlob *signatureData = GetBlobFromNapiDataBlob(env, argv[PARAM0]); + if (signatureData == nullptr) { + LOGE("failed to get signature."); + return false; + } + ctx->signatureData = signatureData; + + napi_create_promise(env, &ctx->deferred, &ctx->promise); + return true; +} + +napi_value NapiVerify::JsVerifyRecover(napi_env env, napi_callback_info info) +{ + VerifyRecoverCtx *ctx = static_cast(HcfMalloc(sizeof(VerifyRecoverCtx), 0)); + if (ctx == nullptr) { + LOGE("create context fail."); + napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail.")); + return nullptr; + } + + if (!BuildVerifyJsRecoverCtx(env, info, ctx)) { + LOGE("build context fail."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail.")); + FreeVerifyRecoverCtx(env, ctx); + return nullptr; + } + + return NewVerifyJsRecoverAsyncWork(env, ctx); +} + +napi_value NapiVerify::JsVerifyRecoverSync(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t expectedArgc = PARAMS_NUM_ONE; + size_t argc = PARAMS_NUM_ONE; + napi_value argv[PARAMS_NUM_ONE] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); + if (argc != expectedArgc) { + LOGE("wrong argument num. require %zu argument. [Argc]: %zu!", expectedArgc, argc); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num.")); + return nullptr; + } + + NapiVerify *napiVerify = nullptr; + napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&napiVerify)); + if (status != napi_ok || napiVerify == nullptr) { + LOGE("failed to unwrap napi verify obj."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi verify obj.")); + return nullptr; + } + + HcfVerify *verify = napiVerify->GetVerify(); + if (verify == nullptr) { + LOGE("failed to get verify obj."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "fail to get verify obj.")); + return nullptr; + } + + HcfBlob *signatureData = GetBlobFromNapiDataBlob(env, argv[PARAM0]); + if (signatureData == nullptr) { + LOGE("failed to get signature data."); + napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get signature data.")); + return nullptr; + } + + HcfBlob rawSignatureData = { .data = nullptr, .len = 0}; + HcfResult res = verify->verifyRecover(verify, signatureData, &rawSignatureData); + HcfBlobDataFree(signatureData); + HcfFree(signatureData); + signatureData = NULL; + if (res != HCF_SUCCESS) { + LOGE("failed to verify recover."); + napi_throw(env, GenerateBusinessError(env, res, "verifyRecover fail.")); + return nullptr; + } + + napi_value instance = ConvertBlobToNapiValue(env, &rawSignatureData); + HcfBlobDataClearAndFree(&rawSignatureData); + return instance; +} + napi_value NapiVerify::VerifyConstructor(napi_env env, napi_callback_info info) { napi_value thisVar = nullptr; @@ -842,6 +1042,8 @@ void NapiVerify::DefineVerifyJSClass(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("init", NapiVerify::JsInit), DECLARE_NAPI_FUNCTION("update", NapiVerify::JsUpdate), DECLARE_NAPI_FUNCTION("verify", NapiVerify::JsVerify), + DECLARE_NAPI_FUNCTION("verifyRecover", NapiVerify::JsVerifyRecover), + DECLARE_NAPI_FUNCTION("verifyRecoverSync", NapiVerify::JsVerifyRecoverSync), DECLARE_NAPI_FUNCTION("setVerifySpec", NapiVerify::JsSetVerifySpec), DECLARE_NAPI_FUNCTION("getVerifySpec", NapiVerify::JsGetVerifySpec), }; diff --git a/frameworks/spi/signature_spi.h b/frameworks/spi/signature_spi.h index 68e4c12bb6a6188a75b3c45f108b4384ccedcb48..61710b544677d59b21558ef729a452ca9715ac37 100644 --- a/frameworks/spi/signature_spi.h +++ b/frameworks/spi/signature_spi.h @@ -58,6 +58,8 @@ struct HcfVerifySpi { bool (*engineVerify)(HcfVerifySpi *self, HcfBlob *data, HcfBlob *signatureData); + HcfResult (*engineVerifyRecover)(HcfVerifySpi *self, HcfBlob *signatureData, HcfBlob *rawSignatureData); + HcfResult (*engineSetVerifySpecInt)(HcfVerifySpi *self, SignSpecItem item, int32_t saltLen); HcfResult (*engineGetVerifySpecString)(HcfVerifySpi *self, SignSpecItem item, char **returnString); diff --git a/interfaces/innerkits/crypto_operation/signature.h b/interfaces/innerkits/crypto_operation/signature.h index 5646261c31208d05967129b38191eccb699d9385..06fabd02f207b76f7fe4ea30ecd6771737a34297 100644 --- a/interfaces/innerkits/crypto_operation/signature.h +++ b/interfaces/innerkits/crypto_operation/signature.h @@ -64,6 +64,8 @@ struct HcfVerify { bool (*verify)(HcfVerify *self, HcfBlob *data, HcfBlob *signatureData); + HcfResult (*verifyRecover)(HcfVerify *self, HcfBlob *signatureData, HcfBlob *rawSignatureData); + const char *(*getAlgoName)(HcfVerify *self); HcfResult (*setVerifySpecInt)(HcfVerify *self, SignSpecItem item, int32_t saltLen); diff --git a/plugin/openssl_plugin/common/inc/openssl_adapter.h b/plugin/openssl_plugin/common/inc/openssl_adapter.h index feeeb5831706dde5f1df46943129e0a093d2e4e8..ae0f4460815e29c96706930a4659154aa48fcc85 100644 --- a/plugin/openssl_plugin/common/inc/openssl_adapter.h +++ b/plugin/openssl_plugin/common/inc/openssl_adapter.h @@ -138,6 +138,10 @@ int Openssl_EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); EVP_PKEY_CTX *Openssl_EVP_PKEY_CTX_new_id(int id, ENGINE *e); int Openssl_EVP_PKEY_base_id(EVP_PKEY *pkey); EVP_PKEY_CTX *Openssl_EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx, const char *name, const char *propquery); +int Openssl_EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); +int Openssl_EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); +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_end(void); OSSL_PARAM Openssl_OSSL_PARAM_construct_uint(const char *key, unsigned int *buf); diff --git a/plugin/openssl_plugin/common/src/openssl_adapter.c b/plugin/openssl_plugin/common/src/openssl_adapter.c index b48c03e03c12b4cc5a2a009a7aaa0a3fef725c95..5de9a33a4ee13f990cf4d348dabafe585d738e08 100644 --- a/plugin/openssl_plugin/common/src/openssl_adapter.c +++ b/plugin/openssl_plugin/common/src/openssl_adapter.c @@ -491,6 +491,21 @@ EVP_PKEY_CTX *Openssl_EVP_PKEY_CTX_new_from_name(OSSL_LIB_CTX *libctx, const cha return EVP_PKEY_CTX_new_from_name(libctx, name, propquery); } +int Openssl_EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) +{ + return EVP_PKEY_verify_recover_init(ctx); +} + +int Openssl_EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) +{ + return EVP_PKEY_CTX_set_signature_md(ctx, md); +} + +int Openssl_EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen, const unsigned char *sig, size_t siglen) +{ + return EVP_PKEY_verify_recover(ctx, rout, routlen, sig, siglen); +} + OSSL_PARAM Openssl_OSSL_PARAM_construct_utf8_string(const char *key, char *buf, size_t bsize) { return OSSL_PARAM_construct_utf8_string(key, buf, bsize); diff --git a/plugin/openssl_plugin/crypto_operation/signature/src/signature_rsa_openssl.c b/plugin/openssl_plugin/crypto_operation/signature/src/signature_rsa_openssl.c index cfe10154c3662a0fb7085b77e68cf5e3f3905cb1..c9442c445edd4b115c5f223559c7bc8506adbe6e 100644 --- a/plugin/openssl_plugin/crypto_operation/signature/src/signature_rsa_openssl.c +++ b/plugin/openssl_plugin/crypto_operation/signature/src/signature_rsa_openssl.c @@ -51,6 +51,8 @@ typedef struct { int32_t saltLen; } HcfSignSpiRsaOpensslImpl; +#define RSA_DIGEST_VERIFY 0 +#define RSA_VERIFY_RECOVER 1 typedef struct { HcfVerifySpi base; @@ -67,6 +69,8 @@ typedef struct { CryptoStatus initFlag; int32_t saltLen; + + int32_t operation; } HcfVerifySpiRsaOpensslImpl; static const char *GetRsaSignClass(void) @@ -111,6 +115,10 @@ static void DestroyRsaVerify(HcfObjectBase *self) HcfVerifySpiRsaOpensslImpl *impl = (HcfVerifySpiRsaOpensslImpl *)self; Openssl_EVP_MD_CTX_free(impl->mdctx); impl->mdctx = NULL; + if (impl->operation == RSA_VERIFY_RECOVER) { + Openssl_EVP_PKEY_CTX_free(impl->ctx); + impl->ctx = NULL; + } HcfFree(impl); impl = NULL; LOGD("DestroyRsaVerify success."); @@ -284,6 +292,58 @@ static HcfResult SetVerifyParams(HcfVerifySpiRsaOpensslImpl *impl, HcfPubKey *pu return HCF_SUCCESS; } +static HcfResult SetVerifyRecoverParams(HcfVerifySpiRsaOpensslImpl *impl, HcfPubKey *publicKey) +{ + EVP_PKEY *dupKey = InitRsaEvpKey((HcfKey *)publicKey, false); + if (dupKey == NULL) { + LOGD("[error] InitRsaEvpKey fail."); + return HCF_ERR_CRYPTO_OPERATION; + } + + EVP_PKEY_CTX *ctx = NULL; + ctx = Openssl_EVP_PKEY_CTX_new_from_pkey(NULL, dupKey, NULL); + if (ctx == NULL) { + LOGD("[error] Openssl_EVP_PKEY_CTX_new_from_pkey fail."); + HcfPrintOpensslError(); + Openssl_EVP_PKEY_free(dupKey); + return HCF_ERR_CRYPTO_OPERATION; + } + + if (Openssl_EVP_PKEY_verify_recover_init(ctx) != HCF_OPENSSL_SUCCESS) { + LOGD("[error] Openssl_EVP_PKEY_verify_recover_init fail"); + HcfPrintOpensslError(); + Openssl_EVP_PKEY_free(dupKey); + Openssl_EVP_PKEY_CTX_free(ctx); + return HCF_ERR_CRYPTO_OPERATION; + } + + int32_t opensslPadding = 0; + (void)GetOpensslPadding(impl->padding, &opensslPadding); + if (Openssl_EVP_PKEY_CTX_set_rsa_padding(ctx, opensslPadding) != HCF_OPENSSL_SUCCESS) { + LOGD("[error] Openssl_EVP_PKEY_CTX_set_rsa_padding fail"); + HcfPrintOpensslError(); + Openssl_EVP_PKEY_free(dupKey); + Openssl_EVP_PKEY_CTX_free(ctx); + return HCF_ERR_CRYPTO_OPERATION; + } + + EVP_MD *opensslAlg = NULL; + (void)GetOpensslDigestAlg(impl->md, &opensslAlg); + if (opensslAlg != NULL) { + if (Openssl_EVP_PKEY_CTX_set_signature_md(ctx, opensslAlg) != HCF_OPENSSL_SUCCESS) { + LOGD("[error] EVP_PKEY_CTX_set_rsa_mgf1_md fail"); + HcfPrintOpensslError(); + Openssl_EVP_PKEY_free(dupKey); + Openssl_EVP_PKEY_CTX_free(ctx); + return HCF_ERR_CRYPTO_OPERATION; + } + } + + impl->ctx = ctx; + Openssl_EVP_PKEY_free(dupKey); + return HCF_SUCCESS; +} + static HcfResult EngineVerifyInit(HcfVerifySpi *self, HcfParamsSpec *params, HcfPubKey *publicKey) { (void)params; @@ -304,10 +364,19 @@ static HcfResult EngineVerifyInit(HcfVerifySpi *self, HcfParamsSpec *params, Hcf LOGE("KeyType dismatch."); return HCF_INVALID_PARAMS; } - if (SetVerifyParams(impl, publicKey) != HCF_SUCCESS) { - LOGD("[error] Verify set padding or md fail"); - return HCF_ERR_CRYPTO_OPERATION; + + if (impl->operation == RSA_DIGEST_VERIFY){ + if (SetVerifyParams(impl, publicKey) != HCF_SUCCESS) { + LOGD("[error] Verify set padding or md fail"); + return HCF_ERR_CRYPTO_OPERATION; + } + } else { + if (SetVerifyRecoverParams(impl, publicKey) != HCF_SUCCESS) { + LOGD("[error] VerifyRecover set padding or md fail"); + return HCF_ERR_CRYPTO_OPERATION; + } } + impl->initFlag = INITIALIZED; return HCF_SUCCESS; } @@ -349,6 +418,12 @@ static HcfResult EngineVerifyUpdate(HcfVerifySpi *self, HcfBlob *data) LOGE("The Sign has not been init"); return HCF_INVALID_PARAMS; } + + if (impl->operation != RSA_DIGEST_VERIFY) { + LOGE("Invalid digest verify operation."); + return HCF_INVALID_PARAMS; + } + if (Openssl_EVP_DigestVerifyUpdate(impl->mdctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) { LOGD("[error] Openssl_EVP_DigestSignUpdate fail"); return HCF_ERR_CRYPTO_OPERATION; @@ -423,6 +498,12 @@ static bool EngineVerify(HcfVerifySpi *self, HcfBlob *data, HcfBlob *signatureDa LOGE("The Sign has not been init"); return false; } + + if (impl->operation != RSA_DIGEST_VERIFY) { + LOGE("Invalid digest verify operation."); + return HCF_INVALID_PARAMS; + } + if (data != NULL && data->data != NULL) { if (Openssl_EVP_DigestVerifyUpdate(impl->mdctx, data->data, data->len) != HCF_OPENSSL_SUCCESS) { LOGD("[error] Openssl_EVP_DigestVerifyUpdate fail"); @@ -436,6 +517,56 @@ static bool EngineVerify(HcfVerifySpi *self, HcfBlob *data, HcfBlob *signatureDa return true; } +static HcfResult EngineVerifyRecover(HcfVerifySpi *self, HcfBlob *signatureData, HcfBlob *rawSignatureData) +{ + if (self == NULL || signatureData == NULL || signatureData->data == NULL || rawSignatureData == NULL) { + LOGE("Invalid input params"); + return HCF_INVALID_PARAMS; + } + if (!IsClassMatch((HcfObjectBase *)self, OPENSSL_RSA_VERIFY_CLASS)) { + LOGE("Class not match."); + return HCF_INVALID_PARAMS; + } + + HcfVerifySpiRsaOpensslImpl *impl = (HcfVerifySpiRsaOpensslImpl *)self; + if (impl->initFlag != INITIALIZED) { + LOGE("The Sign has not been init."); + return HCF_INVALID_PARAMS; + } + + if (impl->operation != RSA_VERIFY_RECOVER) { + LOGE("Invalid verify recover operation."); + return HCF_INVALID_PARAMS; + } + + uint32_t bufLen = 0; + if (Openssl_EVP_PKEY_verify_recover(impl->ctx, NULL, &bufLen, signatureData->data, signatureData->len) + != HCF_OPENSSL_SUCCESS) { + LOGE("[error] Openssl_EVP_PKEY_verify_recover get len fail."); + HcfPrintOpensslError(); + return HCF_ERR_CRYPTO_OPERATION; + } + + uint8_t *buf = (uint8_t *)HcfMalloc(bufLen, 0); + if (buf == NULL) { + LOGE("[error] HcfMalloc fail"); + return HCF_ERR_MALLOC; + } + + if (Openssl_EVP_PKEY_verify_recover(impl->ctx, buf, &bufLen, signatureData->data, signatureData->len) + != HCF_OPENSSL_SUCCESS) { + LOGE("[error] Openssl_EVP_PKEY_verify_recover fail."); + HcfPrintOpensslError(); + HcfFree(buf); + buf = NULL; + return HCF_ERR_CRYPTO_OPERATION; + } + + rawSignatureData->data = buf; + rawSignatureData->len = bufLen; + return HCF_SUCCESS; +} + static HcfResult CheckSignatureParams(HcfSignatureParams *params) { int32_t opensslPadding = 0; @@ -735,15 +866,36 @@ HcfResult HcfSignSpiRsaCreate(HcfSignatureParams *params, HcfSignSpi **returnObj return HCF_SUCCESS; } +static HcfResult CheckVerifyRecoverParams(HcfSignatureParams *params) +{ + int32_t opensslPadding = 0; + if (GetOpensslPadding(params->padding, &opensslPadding) != HCF_SUCCESS) { + LOGE("getpadding fail."); + return HCF_INVALID_PARAMS; + } + if (opensslPadding != RSA_PKCS1_PADDING && opensslPadding != RSA_NO_PADDING) { + LOGE("VerifyRecover cannot use that padding mode"); + return HCF_INVALID_PARAMS; + } + return HCF_SUCCESS; +} + HcfResult HcfVerifySpiRsaCreate(HcfSignatureParams *params, HcfVerifySpi **returnObj) { if (params == NULL || returnObj == NULL) { LOGE("Invalid input parameter."); return HCF_INVALID_PARAMS; } - if (CheckSignatureParams(params) != HCF_SUCCESS) { - return HCF_INVALID_PARAMS; + if (params->operation != HCF_ALG_VERIFY_RECOVER) { + if (CheckSignatureParams(params) != HCF_SUCCESS) { + return HCF_INVALID_PARAMS; + } + } else { + if (CheckVerifyRecoverParams(params) != HCF_SUCCESS) { + return HCF_INVALID_PARAMS; + } } + HcfVerifySpiRsaOpensslImpl *returnImpl = (HcfVerifySpiRsaOpensslImpl *)HcfMalloc( sizeof(HcfVerifySpiRsaOpensslImpl), 0); if (returnImpl == NULL) { @@ -755,16 +907,22 @@ HcfResult HcfVerifySpiRsaCreate(HcfSignatureParams *params, HcfVerifySpi **retur returnImpl->base.engineInit = EngineVerifyInit; returnImpl->base.engineUpdate = EngineVerifyUpdate; returnImpl->base.engineVerify = EngineVerify; + returnImpl->base.engineVerifyRecover = EngineVerifyRecover; returnImpl->base.engineSetVerifySpecInt = EngineSetVerifySpecInt; returnImpl->base.engineGetVerifySpecInt = EngineGetVerifySpecInt; returnImpl->base.engineGetVerifySpecString = EngineGetVerifySpecString; returnImpl->base.engineSetVerifySpecUint8Array = EngineSetVerifySpecUint8Array; returnImpl->md = params->md; returnImpl->padding = params->padding; - returnImpl->mgf1md = params->mgf1md; - returnImpl->mdctx = EVP_MD_CTX_create(); + if (params->operation != HCF_ALG_VERIFY_RECOVER) { + returnImpl->mgf1md = params->mgf1md; + returnImpl->mdctx = EVP_MD_CTX_create(); + returnImpl->saltLen = PSS_SALTLEN_INVALID_INIT; + returnImpl->operation = RSA_DIGEST_VERIFY; + } else { + returnImpl->operation = RSA_VERIFY_RECOVER; + } returnImpl->initFlag = UNINITIALIZED; - returnImpl->saltLen = PSS_SALTLEN_INVALID_INIT; *returnObj = (HcfVerifySpi *)returnImpl; return HCF_SUCCESS; }