Re: [PATCH v3 2/2] crypto: hisilicon/sec2 - fix for aead invalid authsize

linwenkai (C)
2024-11-14T12:47:15Z

在 2024/11/10 11:36, Herbert Xu 写道:
> On Sat, Nov 02, 2024 at 10:55:59AM +0800, Chenghai Huang wrote:
>> @@ -2226,15 +2236,15 @@ static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req *sreq)
>> struct device *dev = ctx->dev;
>> int ret;
>>
>> - if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN ||
>> - req->assoclen > SEC_MAX_AAD_LEN)) {
>> - dev_err(dev, "aead input spec error!\n");
>> + /* Hardware does not handle cases where authsize is less than 4 bytes */
>> + if (unlikely(sz < MIN_MAC_LEN)) {
>> + ctx->a_ctx.fallback = true;
> This is broken. sec_aead_spec_check is a per-request function,
> called without any locking. Therefore it must not modify any
> field in the tfm context (at least not without additional locking),
> because multiple requests can be issued on the same tfm at any time.
>
> I suppose for this field in particular you could move it to
> set_authsize and there it would be safe to change the tfm context.
>
> Cheers,

Hi,

I have found another setup for fallback in the sec_aead_param_check
function, so I need to fix it right too.

The orignal code:

static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
{

if (ctx->sec->qm.ver == QM_HW_V2) {
if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
req->cryptlen <= authsize))) {
ctx->a_ctx.fallback = true;
return -EINVAL;
}
}
}

After the modification, I used a temporary variable fallback to save the
state:

static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req
*sreq, bool *fallback)
{

if (ctx->sec->qm.ver == QM_HW_V2) {
if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt &&
req->cryptlen <= authsize))) {
*fallback = true;
return -EINVAL;
}
}
}

Same with  the sec_aead_spec_check function.

static int sec_aead_spec_check(struct sec_ctx *ctx, struct sec_req
*sreq, bool *fallback) {

/* Hardware does not handle cases where authsize is less than 4
bytes */
if (unlikely(sz < MIN_MAC_LEN)) {
*fallback = true;
return -EINVAL;
}

}

Do you think it is a better way?

Thanks,