crypto: wp512 - Use API partial block handling

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>
This commit is contained in:
Herbert Xu 2025-06-20 20:15:03 +08:00
parent df29f60369
commit 20d71750cc

View File

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