From: Zhushuai Yin <yinzhushuai@huawei.com> BN_bn2binpad() can return negative on failure, but the RSA private decrypt and public verify paths only checked for zero (!len), causing a negative length to be treated as success and leading to buffer overread and incorrect results. DH_set0_key() return values were unchecked, leaking BN objects on failure. The SM2 pkey registration compared ret against zero instead of UADK_E_SUCCESS, mismatching the function's actual success code. In the async cipher and digest paths, the callback did not propagate hardware req->state, and the async pause_job error branch fell through to free_cb_param without distinguishing a pause_job failure (which leaks the poll task slot allocated by async_get_free_task) from a hardware error reported via req->state. Check BN_bn2binpad() return for <= 0 in RSA decrypt/verify and fall back to soft on failure. Check DH_set0_key() return and free the orphaned BN on failure. Compare against UADK_E_SUCCESS in SM2 pkey registration. Propagate req->state in cipher and digest callbacks, check state in sync paths, and free the poll task slot via async_free_poll_task() when async_pause_job returns zero before jumping to the cleanup label. Signed-off-by: Zhushuai Yin <yinzhushuai@huawei.com> --- src/uadk_cipher.c | 13 ++++++++++++- src/uadk_dh.c | 23 +++++++++++++++++------ src/uadk_digest.c | 22 ++++++++++++++++++---- src/uadk_pkey.c | 2 +- src/uadk_rsa.c | 6 +++--- 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/uadk_cipher.c b/src/uadk_cipher.c index bbe6e19..8e738e1 100644 --- a/src/uadk_cipher.c +++ b/src/uadk_cipher.c @@ -551,6 +551,7 @@ static int uadk_e_cipher_cleanup(EVP_CIPHER_CTX *ctx) static void *uadk_e_cipher_cb(struct wd_cipher_req *req, void *data) { struct uadk_e_cb_info *cb_param; + struct cipher_priv_ctx *priv; struct async_op *op; if (!req) @@ -560,6 +561,10 @@ static void *uadk_e_cipher_cb(struct wd_cipher_req *req, void *data) if (!cb_param) return NULL; + priv = cb_param->priv; + if (priv) + priv->req.state = req->state; + op = cb_param->op; if (op && op->job && !op->done) { op->done = 1; @@ -575,7 +580,7 @@ static int do_cipher_sync(struct cipher_priv_ctx *priv) int ret; ret = wd_do_cipher_sync(priv->sess, &priv->req); - if (ret) + if (ret || priv->req.state) return 0; return 1; @@ -621,6 +626,12 @@ static int do_cipher_async(struct cipher_priv_ctx *priv, struct async_op *op) } while (ret == -EBUSY); ret = async_pause_job(priv, op, ASYNC_TASK_CIPHER); + if (!ret || priv->req.state) { + if (!ret) + async_free_poll_task(op->idx, 0); + ret = 0; + goto free_cb_param; + } free_cb_param: free(cb_param); diff --git a/src/uadk_dh.c b/src/uadk_dh.c index be3b41c..dc8db21 100644 --- a/src/uadk_dh.c +++ b/src/uadk_dh.c @@ -813,12 +813,23 @@ static int dh_soft_set_pkey(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) const BIGNUM *old_pub = DH_get0_pub_key(dh); const BIGNUM *old_priv = DH_get0_priv_key(dh); - if (old_pub != pub_key && old_priv != priv_key) - DH_set0_key(dh, pub_key, priv_key); - else if (old_pub != pub_key) - DH_set0_key(dh, pub_key, NULL); - else if (old_priv != priv_key) - DH_set0_key(dh, NULL, priv_key); + if (old_pub != pub_key && old_priv != priv_key) { + if (!DH_set0_key(dh, pub_key, priv_key)) { + BN_free(pub_key); + BN_free(priv_key); + return UADK_E_FAIL; + } + } else if (old_pub != pub_key) { + if (!DH_set0_key(dh, pub_key, NULL)) { + BN_free(pub_key); + return UADK_E_FAIL; + } + } else if (old_priv != priv_key) { + if (!DH_set0_key(dh, NULL, priv_key)) { + BN_free(priv_key); + return UADK_E_FAIL; + } + } return UADK_E_SUCCESS; } diff --git a/src/uadk_digest.c b/src/uadk_digest.c index 72d96b3..2721ff1 100644 --- a/src/uadk_digest.c +++ b/src/uadk_digest.c @@ -50,7 +50,8 @@ #define MAX_DIGEST_LENGTH 64 #define DIGEST_BLOCK_SIZE (512 * 1024) -/* copied form openssl/include/internal/sm3.h +/* + * copied form openssl/include/internal/sm3.h * OpenSSL 3.0 has no <openssl/sm3.h> */ # define SM3_DIGEST_LENGTH 32 @@ -189,7 +190,8 @@ static EVP_MD *uadk_sha256; static EVP_MD *uadk_sha384; static EVP_MD *uadk_sha512; -/* OpenSSL 3.0 has no app_datasize, need set manually, +/* + * OpenSSL 3.0 has no app_datasize, need set manually, * check crypto/evp/legacy_md5.c: md5_md as example. */ #define SET_APP_DATASIZE(ctx_type) \ @@ -800,6 +802,7 @@ static void *uadk_e_digest_cb(void *data) { struct wd_digest_req *req = (struct wd_digest_req *)data; struct uadk_e_cb_info *cb_param; + struct digest_priv_ctx *priv; struct async_op *op; if (!req) @@ -809,6 +812,10 @@ static void *uadk_e_digest_cb(void *data) if (!cb_param) return NULL; + priv = cb_param->priv; + if (priv) + priv->req.state = req->state; + op = cb_param->op; if (op && op->job && !op->done) { op->done = 1; @@ -824,7 +831,7 @@ static int do_digest_sync(struct digest_priv_ctx *priv) int ret; ret = wd_do_digest_sync(priv->sess, &priv->req); - if (ret) { + if (ret || priv->req.state) { fprintf(stderr, "do sec digest sync failed, switch to soft digest.\n"); return 0; } @@ -873,6 +880,12 @@ static int do_digest_async(struct digest_priv_ctx *priv, struct async_op *op) } while (ret == -EBUSY); ret = async_pause_job(priv, op, ASYNC_TASK_DIGEST); + if (!ret || priv->req.state) { + if (!ret) + async_free_poll_task(op->idx, 0); + ret = 0; + goto free_cb_param; + } free_cb_param: free(cb_param); @@ -1034,7 +1047,8 @@ static int uadk_e_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) if (t->state != SEC_DIGEST_INIT) { t->is_stream_copy = true; - /* Length that the hardware has processed should be equal to + /* + * Length that the hardware has processed should be equal to * total input data length minus software cache data length. */ t->req.long_data_len = t->total_data_len - t->last_update_bufflen; diff --git a/src/uadk_pkey.c b/src/uadk_pkey.c index 9bb6a80..e6592e3 100644 --- a/src/uadk_pkey.c +++ b/src/uadk_pkey.c @@ -657,7 +657,7 @@ static int get_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, switch (nid) { case EVP_PKEY_SM2: ret = uadk_sm2_create_pmeth(&pkey_meth); - if (!ret) { + if (ret != UADK_E_SUCCESS) { fprintf(stderr, "failed to register sm2 pmeth.\n"); return 0; } diff --git a/src/uadk_rsa.c b/src/uadk_rsa.c index e718853..8e5a3f1 100644 --- a/src/uadk_rsa.c +++ b/src/uadk_rsa.c @@ -1518,7 +1518,7 @@ static int uadk_e_rsa_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb) } ret = rsa_primes_gen(bits, e, bn_param->p, bn_param->q, cb); - if (!ret) { + if (ret != UADK_E_SUCCESS) { ret = UADK_DO_SOFT; goto free_sess; } @@ -1717,7 +1717,7 @@ static int uadk_e_rsa_private_decrypt(int flen, const unsigned char *from, } len = BN_bn2binpad(dec_bn, from_buf, num_bytes); - if (!len) { + if (len <= 0) { ret = UADK_DO_SOFT; goto free_dec_bn; } @@ -1916,7 +1916,7 @@ static int uadk_e_rsa_public_verify(int flen, const unsigned char *from, } len = BN_bn2binpad(verify_bn, from_buf, num_bytes); - if (!len) { + if (len <= 0) { ret = UADK_DO_SOFT; goto free_verify_bn; } -- 2.43.0