From 8c4f478b1e8965e592467be92d042c8b00c8c426 Mon Sep 17 00:00:00 2001 From: Zhiqi Song Date: Sat, 22 Oct 2022 15:14:03 +0800 Subject: sm2: bugfix about segfault in sm2 ctrl function When there is no available instance of hpre device, the sm2_init() in uadk_engine will failed, the setting of sched_init() will failed, so sched_init() will be NULL. If the sm2_ctrl() function still call the sm2_update_sess() in this situation, and make wd_ecc_alloc_sess() to call sched_init(), there will be a segfault. The solution is to modify the status field of sm2_ctx, make the variable 'init_status' to indicate the status of init operation: 'CTX_UNINIT' indicates the init operation has not been performed, 'CTX_INIT_SUCC' indicates the init operation has been succeeded, 'CTX_INIT_FAIL' indicates the init operation has been failed. The sm2_update_sess() will only be called if the 'init_status' is 'CTX_INIT_SUCC'. Then there will be no segfault. And when there is no available instance, it should switch to openssl software method, so modify some return values to help finish this process. Signed-off-by: Zhiqi Song --- src/uadk_sm2.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/uadk_sm2.c b/src/uadk_sm2.c index fcca9f2..8a9adca 100644 --- a/src/uadk_sm2.c +++ b/src/uadk_sm2.c @@ -25,6 +25,12 @@ #include "uadk.h" #include "uadk_pkey.h" +enum { + CTX_INIT_FAIL = -1, + CTX_UNINIT, + CTX_INIT_SUCC +}; + typedef struct { /* Key and paramgen group */ EC_GROUP *gen_group; @@ -43,7 +49,7 @@ struct sm2_ctx { const BIGNUM *prikey; const EC_POINT *pubkey; BIGNUM *order; - bool is_init; + int init_status; }; typedef struct sm2_ciphertext { @@ -165,6 +171,7 @@ static int sm2_update_sess(struct sm2_ctx *smctx) memset(&setup, 0, sizeof(setup)); setup.alg = "sm2"; + if (smctx->ctx.md) { setup.hash.cb = compute_hash; setup.hash.usr = (void *)smctx->ctx.md; @@ -189,6 +196,7 @@ static int sm2_update_sess(struct sm2_ctx *smctx) if (smctx->sess) wd_ecc_free_sess(smctx->sess); + smctx->sess = sess; smctx->prikey = NULL; smctx->pubkey = NULL; @@ -636,7 +644,7 @@ static int sm2_sign_check(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, if (!smctx || !smctx->sess) { fprintf(stderr, "smctx or sess NULL\n"); - return -EINVAL; + return UADK_DO_SOFT; } if (sig_sz <= 0) { @@ -676,7 +684,7 @@ static int sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, if (ret) goto do_soft; - if (!smctx->is_init) { + if (smctx->init_status != CTX_INIT_SUCC) { ret = UADK_DO_SOFT; goto do_soft; } @@ -744,6 +752,13 @@ static int sm2_verify_check(EVP_PKEY_CTX *ctx, const unsigned char *tbs, size_t tbslen) { + struct sm2_ctx *smctx = EVP_PKEY_CTX_get_data(ctx); + + if (!smctx || !smctx->sess) { + fprintf(stderr, "smctx or sess NULL\n"); + return UADK_DO_SOFT; + } + if (tbslen > SM2_KEY_BYTES) return UADK_DO_SOFT; @@ -772,7 +787,7 @@ static int sm2_verify(EVP_PKEY_CTX *ctx, if (ret) goto do_soft; - if (!smctx->is_init) { + if (smctx->init_status != CTX_INIT_SUCC) { ret = UADK_DO_SOFT; goto do_soft; } @@ -853,7 +868,7 @@ static int sm2_encrypt_check(EVP_PKEY_CTX *ctx, if (!smctx || !smctx->sess) { fprintf(stderr, "smctx or sess NULL\n"); - return 0; + return UADK_DO_SOFT; } md = (smctx->ctx.md == NULL) ? EVP_sm3() : smctx->ctx.md; @@ -897,7 +912,7 @@ static int sm2_encrypt(EVP_PKEY_CTX *ctx, if (ret) goto do_soft; - if (!smctx->is_init) { + if (smctx->init_status != CTX_INIT_SUCC) { ret = UADK_DO_SOFT; goto do_soft; } @@ -953,7 +968,7 @@ static int sm2_decrypt_check(EVP_PKEY_CTX *ctx, if (!smctx || !smctx->sess) { fprintf(stderr, "smctx or sess NULL\n"); - return -EINVAL; + return UADK_DO_SOFT; } md = (smctx->ctx.md == NULL) ? EVP_sm3() : smctx->ctx.md; @@ -1038,7 +1053,7 @@ static int sm2_decrypt(EVP_PKEY_CTX *ctx, if (ret) goto do_soft; - if (!smctx->is_init) { + if (smctx->init_status != CTX_INIT_SUCC) { ret = UADK_DO_SOFT; goto do_soft; } @@ -1124,18 +1139,18 @@ static int sm2_init(EVP_PKEY_CTX *ctx) ret = uadk_init_ecc(); if (ret) { fprintf(stderr, "failed to uadk_init_ecc, ret = %d\n", ret); - smctx->is_init = false; + smctx->init_status = CTX_INIT_FAIL; goto end; } ret = sm2_update_sess(smctx); if (ret) { fprintf(stderr, "failed to update sess\n"); - smctx->is_init = false; + smctx->init_status = CTX_INIT_FAIL; goto end; } - smctx->is_init = true; + smctx->init_status = CTX_INIT_SUCC; end: EVP_PKEY_CTX_set_data(ctx, smctx); EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0); @@ -1196,8 +1211,13 @@ static int sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) return 1; case EVP_PKEY_CTRL_MD: smctx->ctx.md = p2; - if (sm2_update_sess(smctx)) + if (smctx->init_status != CTX_INIT_SUCC) + return 1; + + if (sm2_update_sess(smctx)) { + fprintf(stderr, "failed to set MD\n"); return 0; + } return 1; case EVP_PKEY_CTRL_GET_MD: *(const EVP_MD **)p2 = smctx->ctx.md; -- 1.8.3.1