crypto: powerpc/ghash - Use API partial block handling
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 18 Apr 2025 02:58:50 +0000 (10:58 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 23 Apr 2025 03:33:47 +0000 (11:33 +0800)
Use the Crypto API partial block handling.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
arch/powerpc/crypto/ghash.c

index 9bb61a843fd3dcab0a12e473f7947cd329d7b842..7308735bdb334e48fe711effe8fc632127f5fdc0 100644 (file)
  */
 
 #include "aesp8-ppc.h"
-#include <asm/simd.h>
 #include <asm/switch_to.h>
 #include <crypto/aes.h>
-#include <crypto/b128ops.h>
+#include <crypto/gf128mul.h>
 #include <crypto/ghash.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/simd.h>
-#include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include <linux/uaccess.h>
 
 void gcm_init_p8(u128 htable[16], const u64 Xi[2]);
@@ -39,15 +38,12 @@ struct p8_ghash_ctx {
 
 struct p8_ghash_desc_ctx {
        u64 shash[2];
-       u8 buffer[GHASH_DIGEST_SIZE];
-       int bytes;
 };
 
 static int p8_ghash_init(struct shash_desc *desc)
 {
        struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 
-       dctx->bytes = 0;
        memset(dctx->shash, 0, GHASH_DIGEST_SIZE);
        return 0;
 }
@@ -74,27 +70,30 @@ static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key,
 }
 
 static inline void __ghash_block(struct p8_ghash_ctx *ctx,
-                                struct p8_ghash_desc_ctx *dctx)
+                                struct p8_ghash_desc_ctx *dctx,
+                                const u8 *src)
 {
        if (crypto_simd_usable()) {
                preempt_disable();
                pagefault_disable();
                enable_kernel_vsx();
-               gcm_ghash_p8(dctx->shash, ctx->htable,
-                               dctx->buffer, GHASH_DIGEST_SIZE);
+               gcm_ghash_p8(dctx->shash, ctx->htable, src, GHASH_BLOCK_SIZE);
                disable_kernel_vsx();
                pagefault_enable();
                preempt_enable();
        } else {
-               crypto_xor((u8 *)dctx->shash, dctx->buffer, GHASH_BLOCK_SIZE);
+               crypto_xor((u8 *)dctx->shash, src, GHASH_BLOCK_SIZE);
                gf128mul_lle((be128 *)dctx->shash, &ctx->key);
        }
 }
 
-static inline void __ghash_blocks(struct p8_ghash_ctx *ctx,
-                                 struct p8_ghash_desc_ctx *dctx,
-                                 const u8 *src, unsigned int srclen)
+static inline int __ghash_blocks(struct p8_ghash_ctx *ctx,
+                                struct p8_ghash_desc_ctx *dctx,
+                                const u8 *src, unsigned int srclen)
 {
+       int remain = srclen - round_down(srclen, GHASH_BLOCK_SIZE);
+
+       srclen -= remain;
        if (crypto_simd_usable()) {
                preempt_disable();
                pagefault_disable();
@@ -105,62 +104,38 @@ static inline void __ghash_blocks(struct p8_ghash_ctx *ctx,
                pagefault_enable();
                preempt_enable();
        } else {
-               while (srclen >= GHASH_BLOCK_SIZE) {
+               do {
                        crypto_xor((u8 *)dctx->shash, src, GHASH_BLOCK_SIZE);
                        gf128mul_lle((be128 *)dctx->shash, &ctx->key);
                        srclen -= GHASH_BLOCK_SIZE;
                        src += GHASH_BLOCK_SIZE;
-               }
+               } while (srclen);
        }
+
+       return remain;
 }
 
 static int p8_ghash_update(struct shash_desc *desc,
                           const u8 *src, unsigned int srclen)
 {
-       unsigned int len;
        struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
        struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 
-       if (dctx->bytes) {
-               if (dctx->bytes + srclen < GHASH_DIGEST_SIZE) {
-                       memcpy(dctx->buffer + dctx->bytes, src,
-                               srclen);
-                       dctx->bytes += srclen;
-                       return 0;
-               }
-               memcpy(dctx->buffer + dctx->bytes, src,
-                       GHASH_DIGEST_SIZE - dctx->bytes);
-
-               __ghash_block(ctx, dctx);
-
-               src += GHASH_DIGEST_SIZE - dctx->bytes;
-               srclen -= GHASH_DIGEST_SIZE - dctx->bytes;
-               dctx->bytes = 0;
-       }
-       len = srclen & ~(GHASH_DIGEST_SIZE - 1);
-       if (len) {
-               __ghash_blocks(ctx, dctx, src, len);
-               src += len;
-               srclen -= len;
-       }
-       if (srclen) {
-               memcpy(dctx->buffer, src, srclen);
-               dctx->bytes = srclen;
-       }
-       return 0;
+       return __ghash_blocks(ctx, dctx, src, srclen);
 }
 
-static int p8_ghash_final(struct shash_desc *desc, u8 *out)
+static int p8_ghash_finup(struct shash_desc *desc, const u8 *src,
+                         unsigned int len, u8 *out)
 {
-       int i;
        struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm));
        struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 
-       if (dctx->bytes) {
-               for (i = dctx->bytes; i < GHASH_DIGEST_SIZE; i++)
-                       dctx->buffer[i] = 0;
-               __ghash_block(ctx, dctx);
-               dctx->bytes = 0;
+       if (len) {
+               u8 buf[GHASH_BLOCK_SIZE] = {};
+
+               memcpy(buf, src, len);
+               __ghash_block(ctx, dctx, buf);
+               memzero_explicit(buf, sizeof(buf));
        }
        memcpy(out, dctx->shash, GHASH_DIGEST_SIZE);
        return 0;
@@ -170,14 +145,14 @@ struct shash_alg p8_ghash_alg = {
        .digestsize = GHASH_DIGEST_SIZE,
        .init = p8_ghash_init,
        .update = p8_ghash_update,
-       .final = p8_ghash_final,
+       .finup = p8_ghash_finup,
        .setkey = p8_ghash_setkey,
-       .descsize = sizeof(struct p8_ghash_desc_ctx)
-               + sizeof(struct ghash_desc_ctx),
+       .descsize = sizeof(struct p8_ghash_desc_ctx),
        .base = {
                 .cra_name = "ghash",
                 .cra_driver_name = "p8_ghash",
                 .cra_priority = 1000,
+                .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY,
                 .cra_blocksize = GHASH_BLOCK_SIZE,
                 .cra_ctxsize = sizeof(struct p8_ghash_ctx),
                 .cra_module = THIS_MODULE,