UADK hardware requires middle GCM packets to be 16-byte aligned. Buffer the sub-block remainder and process it with AES-CTR through the default provider, then fold the result back into the GCM stream. Rework the first/update/final flow and add ctr_iv_inc/reset_ctx helpers to support this. Signed-off-by: Weili Qian <qianweili@huawei.com> --- src/uadk_prov_aead.c | 524 ++++++++++++++++++++++++------------------- 1 file changed, 290 insertions(+), 234 deletions(-) diff --git a/src/uadk_prov_aead.c b/src/uadk_prov_aead.c index bb5f6a4..ad990c2 100644 --- a/src/uadk_prov_aead.c +++ b/src/uadk_prov_aead.c @@ -58,6 +58,15 @@ #define UADK_AEAD_DEF_CTXS 2 #define UADK_AEAD_OP_NUM 1 +#define AES_CTR_IV_LEN 16 +#define GCM_IV_DEFAULT_SIZE 12 +#define AES_GCM_COUNTER_SIZE 4 + +#define AES_BLOCK_OFFSET 4 +#define AES_CTR_COUNTER_SIZE 8 +#define BYTE_TO_BITS 8 +#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1)) + struct aead_prov { int pid; }; @@ -99,6 +108,9 @@ struct aead_priv_ctx { int stream_switch_flag; /* soft calculation switch flag for stream mode */ EVP_CIPHER_CTX *sw_ctx; EVP_CIPHER *sw_aead; + unsigned char partial_data[AES_BLOCK_SIZE]; + OSSL_LIB_CTX *libctx; + size_t partial_len; }; struct aead_info { @@ -160,13 +172,13 @@ static int uadk_create_aead_soft_ctx(struct aead_priv_ctx *priv) switch (priv->nid) { case NID_aes_128_gcm: - priv->sw_aead = EVP_CIPHER_fetch(NULL, "AES-128-GCM", "provider=default"); + priv->sw_aead = EVP_CIPHER_fetch(priv->libctx, "AES-128-GCM", "provider=default"); break; case NID_aes_192_gcm: - priv->sw_aead = EVP_CIPHER_fetch(NULL, "AES-192-GCM", "provider=default"); + priv->sw_aead = EVP_CIPHER_fetch(priv->libctx, "AES-192-GCM", "provider=default"); break; case NID_aes_256_gcm: - priv->sw_aead = EVP_CIPHER_fetch(NULL, "AES-256-GCM", "provider=default"); + priv->sw_aead = EVP_CIPHER_fetch(priv->libctx, "AES-256-GCM", "provider=default"); break; default: break; @@ -192,8 +204,7 @@ free: return UADK_AEAD_FAIL; } -static int uadk_prov_aead_soft_init(struct aead_priv_ctx *priv, const unsigned char *key, - const unsigned char *iv, const OSSL_PARAM *params) +static int uadk_prov_aead_soft_init(struct aead_priv_ctx *priv) { int ret; @@ -201,9 +212,11 @@ static int uadk_prov_aead_soft_init(struct aead_priv_ctx *priv, const unsigned c return UADK_AEAD_FAIL; if (priv->req.op_type == WD_CIPHER_ENCRYPTION_DIGEST) - ret = EVP_EncryptInit_ex2(priv->sw_ctx, priv->sw_aead, key, iv, params); + ret = EVP_EncryptInit_ex2(priv->sw_ctx, priv->sw_aead, + priv->key, priv->iv, NULL); else - ret = EVP_DecryptInit_ex2(priv->sw_ctx, priv->sw_aead, key, iv, params); + ret = EVP_DecryptInit_ex2(priv->sw_ctx, priv->sw_aead, + priv->key, priv->iv, NULL); if (!ret) { UADK_ERR("aead soft init error!\n"); @@ -238,12 +251,21 @@ static int uadk_aead_soft_update(struct aead_priv_ctx *priv, unsigned char *out, return UADK_AEAD_SUCCESS; } +static void uadk_prov_aead_reset_ctx(struct aead_priv_ctx *priv) +{ + priv->stream_switch_flag = 0; + priv->req.assoc_bytes = 0; + priv->partial_len = 0; + priv->mode = UNINIT_MODE; + priv->req.msg_state = AEAD_MSG_INVALID; +} + static int uadk_aead_soft_final(struct aead_priv_ctx *priv, unsigned char *digest, size_t *outl) { int ret, outsize = 0; if (!priv->sw_aead) - goto error; + return UADK_OSSL_FAIL; if (priv->req.op_type == WD_CIPHER_ENCRYPTION_DIGEST) { ret = EVP_EncryptFinal_ex(priv->sw_ctx, digest, &outsize); @@ -252,8 +274,8 @@ static int uadk_aead_soft_final(struct aead_priv_ctx *priv, unsigned char *diges ret = EVP_CIPHER_CTX_ctrl(priv->sw_ctx, EVP_CTRL_GCM_GET_TAG, priv->taglen, priv->buf); - if (!ret) - goto error; + if (ret == UADK_AEAD_SUCCESS) + priv->tag_set = SET_TAG; } else { ret = EVP_CIPHER_CTX_ctrl(priv->sw_ctx, EVP_CTRL_GCM_SET_TAG, priv->taglen, priv->buf); @@ -261,18 +283,14 @@ static int uadk_aead_soft_final(struct aead_priv_ctx *priv, unsigned char *diges goto error; ret = EVP_DecryptFinal_ex(priv->sw_ctx, digest, &outsize); - if (!ret) - goto error; } - *outl = 0; - priv->stream_switch_flag = 0; - - return UADK_AEAD_SUCCESS; - error: - UADK_ERR("aead soft final failed.\n"); - return UADK_AEAD_FAIL; + if (!ret) + UADK_ERR("aead soft final failed.\n"); + *outl = 0; + uadk_prov_aead_reset_ctx(priv); + return ret; } static int uadk_prov_aead_dev_init(struct aead_priv_ctx *priv) @@ -330,11 +348,15 @@ static int uadk_prov_aead_ctx_init(struct aead_priv_ctx *priv) priv->req.iv_bytes = priv->ivlen; priv->req.iv = priv->iv; + /* Initialize the counter value for CTR (Counter) mode encryption. */ + memset(priv->iv + GCM_IV_DEFAULT_SIZE, 0, AES_GCM_COUNTER_SIZE); + priv->iv[AES_CTR_IV_LEN - 1] = 0x2; + priv->req.out_bytes = 0; priv->req.mac = priv->buf; - priv->req.mac_bytes = priv->taglen; + priv->req.mac_bytes = AES_GCM_TAG_LEN; - ret = wd_aead_set_authsize(priv->sess, priv->taglen); + ret = wd_aead_set_authsize(priv->sess, AES_GCM_TAG_LEN); if (ret) { UADK_ERR("uadk failed to set authsize!\n"); return UADK_AEAD_FAIL; @@ -365,125 +387,41 @@ static void *uadk_prov_aead_cb(struct wd_aead_req *req, void *data) return NULL; } -static int do_aes_gcm_prepare(struct aead_priv_ctx *priv) -{ - if (priv->mode == UNINIT_MODE) { - if (ASYNC_get_current_job()) - priv->mode = ASYNC_MODE; - else - priv->mode = SYNC_MODE; - } - - if (!priv->enc && priv->tag_set == READ_TAG) { - if (likely(priv->taglen == AES_GCM_TAG_LEN)) { - memcpy(priv->req.mac, priv->buf, AES_GCM_TAG_LEN); - priv->tag_set = SET_TAG; - } else { - UADK_ERR("invalid: aead gcm mac length only support 16B.\n"); - return UADK_AEAD_FAIL; - } - } - - return UADK_AEAD_SUCCESS; -} - -static int uadk_do_aead_sync_inner(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen, - enum wd_aead_msg_state state) +static int uadk_do_aead_sync_inner(struct aead_priv_ctx *priv) { int ret; - if ((state == AEAD_MSG_BLOCK || state == AEAD_MSG_END) - && !priv->enc && priv->tag_set != SET_TAG) { - UADK_ERR("The tag for synchronous decryption is not set.\n"); - return UADK_AEAD_FAIL; - } - - priv->req.msg_state = state; - priv->req.src = (unsigned char *)in; - priv->req.dst = out; - priv->req.in_bytes = inlen; - priv->req.state = 0; ret = wd_do_aead_sync(priv->sess, &priv->req); if (unlikely(ret < 0 || priv->req.state)) { - UADK_ERR("do aead task failed, msg state: %u, ret: %d, state: %u!\n", - state, ret, priv->req.state); + UADK_ERR("do aead sync task failed, ret: %d, state: %u!\n", + ret, priv->req.state); return UADK_AEAD_FAIL; } return UADK_AEAD_SUCCESS; } -static int uadk_do_aead_sync(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen) -{ - size_t nbytes, tail, processing_len, max_mid_len; - const unsigned char *in_block = in; - unsigned char *out_block = out; - int ret; - - tail = inlen % AES_BLOCK_SIZE; - nbytes = inlen - tail; - max_mid_len = AEAD_BLOCK_SIZE - priv->req.assoc_bytes; - - /* If the data length is not 16-byte aligned, it is split according to the protocol. */ - while (nbytes > 0) { - processing_len = nbytes > max_mid_len ? max_mid_len : nbytes; - processing_len -= (processing_len % AES_BLOCK_SIZE); - - ret = uadk_do_aead_sync_inner(priv, out_block, in_block, - processing_len, AEAD_MSG_MIDDLE); - if (ret < 0) - return UADK_AEAD_FAIL; - nbytes -= processing_len; - in_block = in_block + processing_len; - out_block = out_block + processing_len; - } - - if (tail) { - ret = uadk_do_aead_sync_inner(priv, out_block, in_block, tail, AEAD_MSG_END); - if (ret < 0) - return UADK_AEAD_FAIL; - } - - return UADK_AEAD_SUCCESS; -} - -static int uadk_do_aead_async_inner(struct aead_priv_ctx *priv, struct async_op *op, - unsigned char *out, const unsigned char *in, size_t inlen) +static int uadk_do_aead_async_inner(struct aead_priv_ctx *priv) { struct uadk_e_cb_info cb_param; + struct async_op op; int cnt = 0; int ret; - if ((priv->req.msg_state == AEAD_MSG_BLOCK || priv->req.msg_state == AEAD_MSG_END) - && !priv->enc && priv->tag_set != SET_TAG) { - UADK_ERR("The tag for asynchronous decryption is not set.\n"); - return UADK_AEAD_FAIL; - } - - if (unlikely(priv->req.assoc_bytes + inlen > AEAD_BLOCK_SIZE)) { - UADK_ERR("aead input data length is too long!\n"); + ret = async_setup_async_event_notification(&op); + if (unlikely(!ret)) { + UADK_ERR("failed to setup async event notification.\n"); return UADK_AEAD_FAIL; } - cb_param.op = op; + cb_param.op = &op; cb_param.priv = &priv->req; priv->req.cb = uadk_prov_aead_cb; priv->req.cb_param = &cb_param; - priv->req.state = POLL_ERROR; - priv->req.src = (unsigned char *)in; - priv->req.dst = out; - priv->req.in_bytes = inlen; - if (unlikely(!priv->sess)) { - UADK_ERR("uadk session is NULL!\n"); - return UADK_AEAD_FAIL; - } - - ret = async_get_free_task(&op->idx); + ret = async_get_free_task(&op.idx); if (unlikely(!ret)) - return UADK_AEAD_FAIL; + goto free_notification; do { ret = wd_do_aead_async(priv->sess, &priv->req); @@ -495,172 +433,295 @@ static int uadk_do_aead_async_inner(struct aead_priv_ctx *priv, struct async_op else continue; - async_free_poll_task(op->idx, 0); - return UADK_AEAD_FAIL; + async_free_poll_task(op.idx, 0); + goto free_notification; } } while (ret == -EBUSY); - ret = async_pause_job(priv, op, ASYNC_TASK_AEAD); + ret = async_pause_job(priv, &op, ASYNC_TASK_AEAD); if (unlikely(!ret || priv->req.state)) { UADK_ERR("do aead async job failed, ret: %d, state: %u!\n", ret, priv->req.state); - return UADK_AEAD_FAIL; + goto free_notification; } - return ret; + return UADK_AEAD_SUCCESS; + +free_notification: + (void)async_clear_async_event_notification(); + return UADK_AEAD_FAIL; +} + +static int uadk_do_aes_gcm_inner(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen, + enum wd_aead_msg_state state) +{ + priv->req.msg_state = state; + priv->req.src = (unsigned char *)in; + priv->req.dst = out; + priv->req.in_bytes = inlen; + priv->req.state = POLL_ERROR; + + if (priv->mode == ASYNC_MODE) + return uadk_do_aead_async_inner(priv); + + return uadk_do_aead_sync_inner(priv); } static int uadk_prov_do_aes_gcm_first(struct aead_priv_ctx *priv, unsigned char *out, size_t *outl, const unsigned char *in, size_t inlen) { - struct async_op op; int ret; if (inlen > MAX_AAD_LEN || !inlen) - goto soft; - - priv->req.assoc_bytes = inlen; + return SWITCH_TO_SOFT; - if (priv->mode == ASYNC_MODE) { - ret = async_setup_async_event_notification(&op); - if (unlikely(!ret)) { - UADK_ERR("failed to setup async event notification.\n"); - goto soft; - } + ret = uadk_prov_aead_ctx_init(priv); + if (ret != UADK_AEAD_SUCCESS) + return UADK_AEAD_FAIL; - priv->req.msg_state = AEAD_MSG_FIRST; - ret = uadk_do_aead_async_inner(priv, &op, out, in, inlen); - if (unlikely(ret < 0)) { - UADK_ERR("aead async first failed, switch to soft.\n"); - goto free_notification; - } + if (ASYNC_get_current_job()) + priv->mode = ASYNC_MODE; + else + priv->mode = SYNC_MODE; - return UADK_AEAD_SUCCESS; + priv->req.assoc_bytes = inlen; + ret = uadk_do_aes_gcm_inner(priv, out, in, inlen, AEAD_MSG_FIRST); + if (ret == UADK_AEAD_FAIL) { + priv->req.msg_state = AEAD_MSG_INVALID; + priv->req.assoc_bytes = 0; + UADK_ERR("aead failed to update aad, switch to soft.\n"); + return SWITCH_TO_SOFT; } - ret = uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_FIRST); - if (unlikely(ret < 0)) - goto soft; - *outl = 0; return UADK_AEAD_SUCCESS; +} -free_notification: - (void)async_clear_async_event_notification(); -soft: - UADK_ERR("aead failed to update aad, switch to soft.\n"); - return SWITCH_TO_SOFT; +/* + * Increment counter (128-bit int) by software, + * in CTR mode, the last 8 bytes are the counter. + */ +static void ctr_iv_inc(__u8 *counter, __u32 len) +{ + __u32 n = AES_CTR_COUNTER_SIZE; + __u32 c = len; + + do { + --n; + c += counter[n]; + counter[n] = (__u8)c; + c >>= BYTE_TO_BITS; + } while (n); } -static int uadk_do_aead_async(struct aead_priv_ctx *priv, unsigned char *out, - const unsigned char *in, size_t inlen) +static int uadk_prov_process_partial_data(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen, + size_t *processed_len) { - size_t nbytes, tail, processing_len, max_mid_len; - const unsigned char *in_block = in; - unsigned char *out_block = out; - struct async_op op; + size_t processing_len = AES_BLOCK_SIZE - priv->partial_len; + unsigned char block_out[AES_BLOCK_SIZE]; int ret; - ret = async_setup_async_event_notification(&op); - if (unlikely(!ret)) { - UADK_ERR("failed to setup async event notification.\n"); + if (!priv->partial_len) + return UADK_AEAD_SUCCESS; + + /* If input can't complete the partial block, switch to soft */ + if (inlen < processing_len) + return SWITCH_TO_SOFT; + + memcpy(priv->partial_data + priv->partial_len, in, processing_len); + ret = uadk_do_aes_gcm_inner(priv, block_out, priv->partial_data, + AES_BLOCK_SIZE, AEAD_MSG_MIDDLE); + if (unlikely(ret == UADK_AEAD_FAIL)) { + UADK_ERR("failed to process partial block.\n"); return UADK_AEAD_FAIL; } - tail = inlen % AES_BLOCK_SIZE; - nbytes = inlen - tail; - max_mid_len = AEAD_BLOCK_SIZE - priv->req.assoc_bytes; + memcpy(out, block_out + priv->partial_len, processing_len); + priv->partial_len = 0; + ctr_iv_inc(priv->iv + AES_CTR_COUNTER_SIZE, 1); + *processed_len = processing_len; - /* Middle packets processing */ - while (nbytes > 0) { - processing_len = nbytes > max_mid_len ? max_mid_len : nbytes; - processing_len -= (processing_len % AES_BLOCK_SIZE); + return UADK_AEAD_SUCCESS; +} - priv->req.msg_state = AEAD_MSG_MIDDLE; - ret = uadk_do_aead_async_inner(priv, &op, out_block, in_block, - processing_len); - if (unlikely(ret < 0)) { - UADK_ERR("aead async middle failed!\n"); - goto free_notification; - } - nbytes -= processing_len; - in_block = in_block + processing_len; - out_block = out_block + processing_len; +/* Process last incomplete block, encrypt/decrypt using OpenSSL software implementation */ +static int uadk_prov_process_tail_data(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + unsigned char block_out[AES_BLOCK_SIZE]; + EVP_CIPHER *cipher = NULL; + int ret = UADK_AEAD_FAIL; + EVP_CIPHER_CTX *ctx; + int outsize = 0; + + if (!inlen) + return UADK_AEAD_SUCCESS; + + /* Buffer the tail data */ + memcpy(priv->partial_data + priv->partial_len, in, inlen); + + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) + return UADK_AEAD_FAIL; + + switch (priv->nid) { + case NID_aes_128_gcm: + cipher = EVP_CIPHER_fetch(priv->libctx, "AES-128-CTR", "provider=default"); + break; + case NID_aes_192_gcm: + cipher = EVP_CIPHER_fetch(priv->libctx, "AES-192-CTR", "provider=default"); + break; + case NID_aes_256_gcm: + cipher = EVP_CIPHER_fetch(priv->libctx, "AES-256-CTR", "provider=default"); + break; + default: + break; } + if (!cipher) + goto free_ctx; - /* Tail packet processing */ - if (tail) { - priv->req.msg_state = AEAD_MSG_END; - ret = uadk_do_aead_async_inner(priv, &op, out_block, in_block, tail); - if (unlikely(ret < 0)) { - UADK_ERR("aead async tail failed!\n"); - goto free_notification; + ret = EVP_CipherInit_ex2(ctx, cipher, priv->key, priv->iv, priv->enc, NULL); + if (!ret) + goto free_cipher; + + ret = EVP_CipherUpdate(ctx, block_out, &outsize, priv->partial_data, + priv->partial_len + inlen); + if (!ret) + goto free_cipher; + + ret = EVP_CipherFinal_ex(ctx, block_out + priv->partial_len + inlen, &outsize); + if (!ret) + goto free_cipher; + + memcpy(out, block_out + priv->partial_len, inlen); + priv->partial_len += inlen; + +free_cipher: + EVP_CIPHER_free(cipher); +free_ctx: + EVP_CIPHER_CTX_free(ctx); + return ret; +} + +/* Process complete blocks in bulk */ +static int uadk_process_complete_blocks(struct aead_priv_ctx *priv, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t max_mid_len = AEAD_BLOCK_SIZE - priv->req.assoc_bytes; + size_t remain_len = len; + size_t chunk; + int ret; + + while (remain_len > 0) { + chunk = (remain_len > max_mid_len) ? max_mid_len : remain_len; + chunk = ALIGN_DOWN(chunk, AES_BLOCK_SIZE); + + ret = uadk_do_aes_gcm_inner(priv, out, in, chunk, AEAD_MSG_MIDDLE); + if (unlikely(ret == UADK_AEAD_FAIL)) { + UADK_ERR("failed to process complete block.\n"); + return UADK_AEAD_FAIL; } - } - return UADK_AEAD_SUCCESS; + remain_len -= chunk; + out += chunk; + in += chunk; + } -free_notification: - (void)async_clear_async_event_notification(); + ctr_iv_inc(priv->iv + AES_CTR_COUNTER_SIZE, len >> AES_BLOCK_OFFSET); - return UADK_AEAD_FAIL; + return UADK_AEAD_SUCCESS; } +/* + * The uadk does not support the scenario where the length of the intermediate + * packet is not 16-byte aligned. To avoid task failures, AES-CTR is used for + * encryption and decryption, and the data and the next task are combined to make the + * length 16-byte aligned. Then, the uadk calculates the hash value. However, it is + * recommended that the packet length be aligned to ensure that the performance is not + * affected by this problem. + */ static int uadk_prov_do_aes_gcm_update(struct aead_priv_ctx *priv, unsigned char *out, size_t *outl, const unsigned char *in, size_t inlen) { - if (priv->stream_switch_flag == UADK_DO_SOFT) + size_t remain_len = inlen; + size_t processed_len = 0; + int ret; + + if (!priv->req.assoc_bytes) return SWITCH_TO_SOFT; *outl = inlen; + /* Process buffered partial data */ + ret = uadk_prov_process_partial_data(priv, out, in, remain_len, &processed_len); + if (ret == SWITCH_TO_SOFT) + goto soft_fallback; + else if (ret < 0) + return UADK_AEAD_FAIL; - if (priv->mode == ASYNC_MODE) - return uadk_do_aead_async(priv, out, in, inlen); + out += processed_len; + in += processed_len; + remain_len -= processed_len; - return uadk_do_aead_sync(priv, out, in, inlen); + if (remain_len >= AES_BLOCK_SIZE) { + processed_len = ALIGN_DOWN(remain_len, AES_BLOCK_SIZE); + ret = uadk_process_complete_blocks(priv, out, in, processed_len); + if (ret != UADK_AEAD_SUCCESS) + return UADK_AEAD_FAIL; + remain_len -= processed_len; + out += processed_len; + in += processed_len; + } + +soft_fallback: + return uadk_prov_process_tail_data(priv, out, in, remain_len); } static int uadk_prov_do_aes_gcm_final(struct aead_priv_ctx *priv, unsigned char *out, size_t *outl, const unsigned char *in, size_t inlen) { - struct async_op op; + unsigned char block_out[AES_BLOCK_SIZE]; int ret; - if (!priv->req.assoc_bytes || priv->req.msg_state == AEAD_MSG_END) - goto out; + if (!priv->req.assoc_bytes) + return SWITCH_TO_SOFT; - if (priv->mode == ASYNC_MODE) { - ret = async_setup_async_event_notification(&op); - if (unlikely(!ret)) { - UADK_ERR("failed to setup async event notification.\n"); - return UADK_AEAD_FAIL; + if (!priv->enc) { + if (priv->tag_set != READ_TAG) { + UADK_ERR("decrypt tag not set.\n"); + ret = UADK_OSSL_FAIL; + goto out; } - priv->req.msg_state = AEAD_MSG_END; - ret = uadk_do_aead_async_inner(priv, &op, out, in, inlen); - if (unlikely(ret < 0)) { - UADK_ERR("aead async final failed!\n"); - (void)async_clear_async_event_notification(); - return UADK_AEAD_FAIL; + if (priv->taglen != AES_GCM_TAG_LEN) { + ret = wd_aead_set_authsize(priv->sess, priv->taglen); + if (ret) { + ret = UADK_OSSL_FAIL; + goto out; + } } + } + if (priv->partial_len) + ret = uadk_do_aes_gcm_inner(priv, block_out, priv->partial_data, + priv->partial_len, AEAD_MSG_END); + else + ret = uadk_do_aes_gcm_inner(priv, out, in, inlen, AEAD_MSG_END); + if (unlikely(ret == UADK_AEAD_FAIL)) { + UADK_ERR("uadk_prov_do_aes_gcm_final failed.\n"); goto out; } - ret = uadk_do_aead_sync_inner(priv, out, in, inlen, AEAD_MSG_END); - if (unlikely(ret < 0)) - return UADK_AEAD_FAIL; - -out: if (priv->enc) - memcpy(priv->buf, priv->req.mac, priv->taglen); - else - priv->tag_set = INIT_TAG; + priv->tag_set = SET_TAG; - priv->mode = UNINIT_MODE; +out: + uadk_prov_aead_reset_ctx(priv); *outl = 0; - return UADK_AEAD_SUCCESS; + + return ret; } static int uadk_prov_sw_aes_gcm(struct aead_priv_ctx *priv, unsigned char *out, @@ -669,7 +730,7 @@ static int uadk_prov_sw_aes_gcm(struct aead_priv_ctx *priv, unsigned char *out, int ret; if (priv->stream_switch_flag != UADK_DO_SOFT) { - ret = uadk_prov_aead_soft_init(priv, priv->key, priv->iv, NULL); + ret = uadk_prov_aead_soft_init(priv); if (ret <= 0) return UADK_OSSL_FAIL; } @@ -688,14 +749,6 @@ static int uadk_prov_do_aes_gcm(struct aead_priv_ctx *priv, unsigned char *out, if (priv->stream_switch_flag == UADK_DO_SOFT || !priv->sess) return uadk_prov_sw_aes_gcm(priv, out, outl, in, inlen); - ret = uadk_prov_aead_ctx_init(priv); - if (ret != UADK_AEAD_SUCCESS) - return UADK_AEAD_FAIL; - - ret = do_aes_gcm_prepare(priv); - if (unlikely(ret < 0)) - return UADK_AEAD_FAIL; - if (in) { if (!out) ret = uadk_prov_do_aes_gcm_first(priv, out, outl, in, inlen); @@ -736,10 +789,10 @@ static int uadk_prov_aead_cipher(void *vctx, unsigned char *out, size_t *outl, struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; int ret; - if (!vctx || !out || !outl) + if (!vctx || !outl) return UADK_OSSL_FAIL; - if (outsize < inl) { + if (out && outsize < inl) { UADK_ERR("invalid: aead cipher outsize is too small.\n"); return UADK_OSSL_FAIL; } @@ -760,10 +813,15 @@ static int uadk_prov_aead_stream_update(void *vctx, unsigned char *out, struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; int ret; - if (!vctx) + if (!vctx || !outl) return UADK_OSSL_FAIL; - if (outsize < inl) { + if (!inl) { + *outl = 0; + return UADK_AEAD_SUCCESS; + } + + if (out && outsize < inl) { UADK_ERR("invalid: input param outsize is too small.\n"); return UADK_OSSL_FAIL; } @@ -783,7 +841,7 @@ static int uadk_prov_aead_stream_final(void *vctx, unsigned char *out, struct aead_priv_ctx *priv = (struct aead_priv_ctx *)vctx; int ret; - if (!vctx || !out || !outl) + if (!vctx || !outl) return UADK_OSSL_FAIL; ret = uadk_prov_do_aes_gcm(priv, out, outl, NULL, 0); @@ -887,11 +945,6 @@ static int uadk_prov_aead_init(struct aead_priv_ctx *priv, const unsigned char * { int ret; - if (ivlen > MAX_IV_LEN || keylen > MAX_KEY_LEN) { - UADK_ERR("invalid keylen or ivlen.\n"); - return UADK_OSSL_FAIL; - } - /* will free in freectx */ ret = uadk_prov_aead_alloc_sess(priv); if (ret == UADK_OSSL_FAIL) @@ -909,6 +962,8 @@ static int uadk_prov_aead_init(struct aead_priv_ctx *priv, const unsigned char * } priv->stream_switch_flag = 0; + priv->tag_set = INIT_TAG; + priv->partial_len = 0; priv->req.msg_state = AEAD_MSG_INVALID; return uadk_prov_aead_set_ctx_params(priv, params); @@ -1004,7 +1059,7 @@ static int uadk_prov_aead_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return UADK_OSSL_FAIL; } if (sz == 0 || sz > priv->ivlen) { - UADK_ERR("invalid sz or ivlen.\n"); + UADK_ERR("invalid ivlen %zu.\n", sz); return UADK_OSSL_FAIL; } priv->ivlen = sz; @@ -1092,7 +1147,7 @@ static int uadk_prov_aead_get_ctx_params(void *vctx, OSSL_PARAM params[]) size_t sz = p->data_size; if (sz == 0 || sz > EVP_GCM_TLS_TAG_LEN || !priv->enc - || priv->taglen == UNINITIALISED_SIZET) { + || priv->tag_set != SET_TAG) { UADK_ERR("invalid size enc or taglen.\n"); return UADK_OSSL_FAIL; } @@ -1263,6 +1318,7 @@ static void *uadk_##nm##_newctx(void *provctx) \ ctx->nid = e_nid; \ ctx->taglen = tag_len; \ strncpy(ctx->alg_name, #algnm, ALG_NAME_SIZE - 1); \ + ctx->libctx = prov_libctx_of(provctx); \ \ if (uadk_get_sw_offload_state()) \ uadk_create_aead_soft_ctx(ctx); \ -- 2.53.0.windows.2