]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: wp512 - Use API partial block handling
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 20 Jun 2025 12:15:03 +0000 (20:15 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Mon, 23 Jun 2025 08:56:56 +0000 (16:56 +0800)
Use the Crypto API partial block handling.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Milan Broz <gmazyland@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/wp512.c

index 41f13d49033390653c15d79c742ccfe7bbc1a5c8..229b189a79889f3a6b0f374c947e7e6ce125070f 100644 (file)
  */
 #include <crypto/internal/hash.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/mm.h>
-#include <asm/byteorder.h>
-#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/unaligned.h>
 
 #define WP512_DIGEST_SIZE 64
 #define WP384_DIGEST_SIZE 48
@@ -37,9 +37,6 @@
 
 struct wp512_ctx {
        u8  bitLength[WP512_LENGTHBYTES];
-       u8  buffer[WP512_BLOCK_SIZE];
-       int bufferBits;
-       int bufferPos;
        u64 hash[WP512_DIGEST_SIZE/8];
 };
 
@@ -779,16 +776,16 @@ static const u64 rc[WHIRLPOOL_ROUNDS] = {
  * The core Whirlpool transform.
  */
 
-static __no_kmsan_checks void wp512_process_buffer(struct wp512_ctx *wctx) {
+static __no_kmsan_checks void wp512_process_buffer(struct wp512_ctx *wctx,
+                                                  const u8 *buffer) {
        int i, r;
        u64 K[8];        /* the round key */
        u64 block[8];    /* mu(buffer) */
        u64 state[8];    /* the cipher state */
        u64 L[8];
-       const __be64 *buffer = (const __be64 *)wctx->buffer;
 
        for (i = 0; i < 8; i++)
-               block[i] = be64_to_cpu(buffer[i]);
+               block[i] = get_unaligned_be64(buffer + i * 8);
 
        state[0] = block[0] ^ (K[0] = wctx->hash[0]);
        state[1] = block[1] ^ (K[1] = wctx->hash[1]);
@@ -991,8 +988,6 @@ static int wp512_init(struct shash_desc *desc) {
        int i;
 
        memset(wctx->bitLength, 0, 32);
-       wctx->bufferBits = wctx->bufferPos = 0;
-       wctx->buffer[0] = 0;
        for (i = 0; i < 8; i++) {
                wctx->hash[i] = 0L;
        }
@@ -1000,84 +995,54 @@ static int wp512_init(struct shash_desc *desc) {
        return 0;
 }
 
-static int wp512_update(struct shash_desc *desc, const u8 *source,
-                        unsigned int len)
+static void wp512_add_length(u8 *bitLength, u64 value)
 {
-       struct wp512_ctx *wctx = shash_desc_ctx(desc);
-       int sourcePos    = 0;
-       unsigned int bits_len = len * 8; // convert to number of bits
-       int sourceGap    = (8 - ((int)bits_len & 7)) & 7;
-       int bufferRem    = wctx->bufferBits & 7;
+       u32 carry;
        int i;
-       u32 b, carry;
-       u8 *buffer       = wctx->buffer;
-       u8 *bitLength    = wctx->bitLength;
-       int bufferBits   = wctx->bufferBits;
-       int bufferPos    = wctx->bufferPos;
 
-       u64 value = bits_len;
        for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) {
                carry += bitLength[i] + ((u32)value & 0xff);
                bitLength[i] = (u8)carry;
                carry >>= 8;
                value >>= 8;
        }
-       while (bits_len > 8) {
-               b = ((source[sourcePos] << sourceGap) & 0xff) |
-               ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap));
-               buffer[bufferPos++] |= (u8)(b >> bufferRem);
-               bufferBits += 8 - bufferRem;
-               if (bufferBits == WP512_BLOCK_SIZE * 8) {
-                       wp512_process_buffer(wctx);
-                       bufferBits = bufferPos = 0;
-               }
-               buffer[bufferPos] = b << (8 - bufferRem);
-               bufferBits += bufferRem;
-               bits_len -= 8;
-               sourcePos++;
-       }
-       if (bits_len > 0) {
-               b = (source[sourcePos] << sourceGap) & 0xff;
-               buffer[bufferPos] |= b >> bufferRem;
-       } else {
-               b = 0;
-       }
-       if (bufferRem + bits_len < 8) {
-               bufferBits += bits_len;
-       } else {
-               bufferPos++;
-               bufferBits += 8 - bufferRem;
-               bits_len -= 8 - bufferRem;
-               if (bufferBits == WP512_BLOCK_SIZE * 8) {
-                       wp512_process_buffer(wctx);
-                       bufferBits = bufferPos = 0;
-               }
-               buffer[bufferPos] = b << (8 - bufferRem);
-               bufferBits += (int)bits_len;
-       }
+}
 
-       wctx->bufferBits   = bufferBits;
-       wctx->bufferPos    = bufferPos;
+static int wp512_update(struct shash_desc *desc, const u8 *source,
+                        unsigned int len)
+{
+       struct wp512_ctx *wctx = shash_desc_ctx(desc);
+       unsigned int remain = len % WP512_BLOCK_SIZE;
+       u64 bits_len = (len - remain) * 8ull;
+       u8 *bitLength    = wctx->bitLength;
 
-       return 0;
+       wp512_add_length(bitLength, bits_len);
+       do {
+               wp512_process_buffer(wctx, source);
+               source += WP512_BLOCK_SIZE;
+               bits_len -= WP512_BLOCK_SIZE * 8;
+       } while (bits_len);
+
+       return remain;
 }
 
-static int wp512_final(struct shash_desc *desc, u8 *out)
+static int wp512_finup(struct shash_desc *desc, const u8 *src,
+                      unsigned int bufferPos, u8 *out)
 {
        struct wp512_ctx *wctx = shash_desc_ctx(desc);
        int i;
-       u8 *buffer      = wctx->buffer;
        u8 *bitLength   = wctx->bitLength;
-       int bufferBits  = wctx->bufferBits;
-       int bufferPos   = wctx->bufferPos;
        __be64 *digest  = (__be64 *)out;
+       u8 buffer[WP512_BLOCK_SIZE];
 
-       buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
+       wp512_add_length(bitLength, bufferPos * 8);
+       memcpy(buffer, src, bufferPos);
+       buffer[bufferPos] = 0x80U;
        bufferPos++;
        if (bufferPos > WP512_BLOCK_SIZE - WP512_LENGTHBYTES) {
                if (bufferPos < WP512_BLOCK_SIZE)
                        memset(&buffer[bufferPos], 0, WP512_BLOCK_SIZE - bufferPos);
-               wp512_process_buffer(wctx);
+               wp512_process_buffer(wctx, buffer);
                bufferPos = 0;
        }
        if (bufferPos < WP512_BLOCK_SIZE - WP512_LENGTHBYTES)
@@ -1086,31 +1051,32 @@ static int wp512_final(struct shash_desc *desc, u8 *out)
        bufferPos = WP512_BLOCK_SIZE - WP512_LENGTHBYTES;
        memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES],
                   bitLength, WP512_LENGTHBYTES);
-       wp512_process_buffer(wctx);
+       wp512_process_buffer(wctx, buffer);
+       memzero_explicit(buffer, sizeof(buffer));
        for (i = 0; i < WP512_DIGEST_SIZE/8; i++)
                digest[i] = cpu_to_be64(wctx->hash[i]);
-       wctx->bufferBits   = bufferBits;
-       wctx->bufferPos    = bufferPos;
 
        return 0;
 }
 
-static int wp384_final(struct shash_desc *desc, u8 *out)
+static int wp384_finup(struct shash_desc *desc, const u8 *src,
+                      unsigned int len, u8 *out)
 {
        u8 D[64];
 
-       wp512_final(desc, D);
+       wp512_finup(desc, src, len, D);
        memcpy(out, D, WP384_DIGEST_SIZE);
        memzero_explicit(D, WP512_DIGEST_SIZE);
 
        return 0;
 }
 
-static int wp256_final(struct shash_desc *desc, u8 *out)
+static int wp256_finup(struct shash_desc *desc, const u8 *src,
+                      unsigned int len, u8 *out)
 {
        u8 D[64];
 
-       wp512_final(desc, D);
+       wp512_finup(desc, src, len, D);
        memcpy(out, D, WP256_DIGEST_SIZE);
        memzero_explicit(D, WP512_DIGEST_SIZE);
 
@@ -1121,11 +1087,12 @@ static struct shash_alg wp_algs[3] = { {
        .digestsize     =       WP512_DIGEST_SIZE,
        .init           =       wp512_init,
        .update         =       wp512_update,
-       .final          =       wp512_final,
+       .finup          =       wp512_finup,
        .descsize       =       sizeof(struct wp512_ctx),
        .base           =       {
                .cra_name        =      "wp512",
                .cra_driver_name =      "wp512-generic",
+               .cra_flags       =      CRYPTO_AHASH_ALG_BLOCK_ONLY,
                .cra_blocksize   =      WP512_BLOCK_SIZE,
                .cra_module      =      THIS_MODULE,
        }
@@ -1133,11 +1100,12 @@ static struct shash_alg wp_algs[3] = { {
        .digestsize     =       WP384_DIGEST_SIZE,
        .init           =       wp512_init,
        .update         =       wp512_update,
-       .final          =       wp384_final,
+       .finup          =       wp384_finup,
        .descsize       =       sizeof(struct wp512_ctx),
        .base           =       {
                .cra_name        =      "wp384",
                .cra_driver_name =      "wp384-generic",
+               .cra_flags       =      CRYPTO_AHASH_ALG_BLOCK_ONLY,
                .cra_blocksize   =      WP512_BLOCK_SIZE,
                .cra_module      =      THIS_MODULE,
        }
@@ -1145,11 +1113,12 @@ static struct shash_alg wp_algs[3] = { {
        .digestsize     =       WP256_DIGEST_SIZE,
        .init           =       wp512_init,
        .update         =       wp512_update,
-       .final          =       wp256_final,
+       .finup          =       wp256_finup,
        .descsize       =       sizeof(struct wp512_ctx),
        .base           =       {
                .cra_name        =      "wp256",
                .cra_driver_name =      "wp256-generic",
+               .cra_flags       =      CRYPTO_AHASH_ALG_BLOCK_ONLY,
                .cra_blocksize   =      WP512_BLOCK_SIZE,
                .cra_module      =      THIS_MODULE,
        }