Hi Nikolay, some more comments from another read through.  Sorry for not
noticing these in v2.

On Wed, May 29, 2019 at 06:48:26PM +0300, Nikolay Borisov wrote:
> +static int xxhash64_update(struct shash_desc *desc, const u8 *data,
> +                      unsigned int length)
> +{
> +     struct xxhash64_desc_ctx *tctx = shash_desc_ctx(desc);

This variable should be named 'dctx' (for desc_ctx), not 'tctx' (for tfm_ctx).

> +
> +     xxh64_update(&tctx->xxhstate, data, length);
> +
> +     return 0;
> +}

xxh64_update() has a return value (0 or -errno) which is not being checked,
which at first glance seems to be a bug.

However, it only returns an error in this case:

        if (input == NULL)
                return -EINVAL;

But data=NULL, length=0 are valid parameters to xxhash64_update(), so if you did
check the return value, xxhash64_update() would break.  So it's fine as-is.

However, if anyone changed xxh64_update() to an error in any other case,
xxhash64_update() would break since it ignores the error.

I suggest avoiding this complexity around error codes by changing xxh64_update()
to return void.  It can be a separate patch.

> +
> +static int xxhash64_final(struct shash_desc *desc, u8 *out)
> +{
> +     struct xxhash64_desc_ctx *ctx = shash_desc_ctx(desc);
> +

For consistency it should be 'dctx' here too.

> +     put_unaligned_le64(xxh64_digest(&ctx->xxhstate), out);
> +
> +     return 0;
> +}
> +

> +static int xxhash64_finup(struct shash_desc *desc, const u8 *data,
> +                     unsigned int len, u8 *out)
> +{
> +     xxhash64_update(desc, data, len);
> +     xxhash64_final(desc, out);
> +
> +     return 0;
> +}
> +
> +static int xxhash64_digest(struct shash_desc *desc, const u8 *data,
> +                      unsigned int length, u8 *out)
> +{
> +     xxhash64_init(desc);
> +     return xxhash64_finup(desc, data, length, out);
> +}
> +

The purpose of the ->finup() and ->digest() methods is to allow the algorithm to
work more efficiently than it could if ->init(), ->update(), and ->final() were
called separately.  So, implementing them on top of xxhash64_init(),
xxhash64_update(), and xxhash64_final() is mostly pointless.

lib/xxhash.c already provides a function xxh64() which does a digest in one
step, so that should be used to implement xxhash64_digest():

static int xxhash64_digest(struct shash_desc *desc, const u8 *data,
                         unsigned int length, u8 *out)
{
        struct xxhash64_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);

        put_unaligned_le64(xxh64(data, length, tctx->seed), out);

        return 0;
}

I suggest just deleting xxhash64_finup().

> +static struct shash_alg alg = {
> +     .digestsize     = XXHASH64_DIGEST_SIZE,
> +     .setkey         = xxhash64_setkey,
> +     .init           = xxhash64_init,
> +     .update         = xxhash64_update,
> +     .final          = xxhash64_final,
> +     .finup          = xxhash64_finup,
> +     .digest         = xxhash64_digest,
> +     .descsize       = sizeof(struct xxhash64_desc_ctx),
> +     .base           = {
> +             .cra_name        = "xxhash64",
> +             .cra_driver_name = "xxhash64-generic",
> +             .cra_priority    = 100,
> +             .cra_flags       = CRYPTO_ALG_OPTIONAL_KEY,
> +             .cra_blocksize   = XXHASH64_BLOCK_SIZE,
> +             .cra_ctxsize     = sizeof(struct xxhash64_tfm_ctx),
> +             .cra_module      = THIS_MODULE,
> +     }
> +};

Note that because .export() and .import() aren't set, if someone calls
crypto_shash_export() and crypto_shash_import() on an xxhash64 descriptor, the
crypto API will export and import the state by memcpy().

That's perfectly fine, but it also means that the xxh64_copy_state() function
won't be called.  Since it exists, one might assume that all state copies go
through that function.  But it's actually pointless as it just does a memcpy, so
I suggest removing it.  (As a separate patch, which you don't necessarily have
to do now.  BTW, another thing that should be cleaned up is the random
unnecessary local variable in xxh32_reset() and xxh64_reset()...)

Thanks,

- Eric

Reply via email to