]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
crypto: s390/sha1 - Use API partial block handling
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 18 Apr 2025 02:59:34 +0000 (10:59 +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/s390/crypto/sha.h
arch/s390/crypto/sha1_s390.c
arch/s390/crypto/sha_common.c

index 2bb22db54c31a28dc11f31071927fde031d43f5b..b8aeb51b2f3d1de229fe9e5b1c04245965f4feaf 100644 (file)
 #ifndef _CRYPTO_ARCH_S390_SHA_H
 #define _CRYPTO_ARCH_S390_SHA_H
 
-#include <linux/crypto.h>
-#include <crypto/sha1.h>
-#include <crypto/sha2.h>
 #include <crypto/sha3.h>
+#include <linux/types.h>
 
 /* must be big enough for the largest SHA variant */
 #define SHA3_STATE_SIZE                        200
 #define CPACF_MAX_PARMBLOCK_SIZE       SHA3_STATE_SIZE
 #define SHA_MAX_BLOCK_SIZE             SHA3_224_BLOCK_SIZE
+#define S390_SHA_CTX_SIZE              offsetof(struct s390_sha_ctx, buf)
 
 struct s390_sha_ctx {
        u64 count;              /* message length in bytes */
        u32 state[CPACF_MAX_PARMBLOCK_SIZE / sizeof(u32)];
-       u8 buf[SHA_MAX_BLOCK_SIZE];
        int func;               /* KIMD function to use */
-       int first_message_part;
+       bool first_message_part;
+       u8 buf[SHA_MAX_BLOCK_SIZE];
 };
 
 struct shash_desc;
 
 int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len);
+int s390_sha_update_blocks(struct shash_desc *desc, const u8 *data,
+                          unsigned int len);
 int s390_sha_final(struct shash_desc *desc, u8 *out);
+int s390_sha_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
+                  u8 *out);
 
 #endif
index bc3a22704e09304bd2e227b4b0e0129d6be4a71c..d229cbd2ba229d4c8685fb9675f7ecd8abd5d5e3 100644 (file)
  *   Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
  *   Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
  */
+#include <asm/cpacf.h>
 #include <crypto/internal/hash.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/cpufeature.h>
 #include <crypto/sha1.h>
-#include <asm/cpacf.h>
+#include <linux/cpufeature.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 
 #include "sha.h"
 
@@ -49,7 +49,6 @@ static int s390_sha1_export(struct shash_desc *desc, void *out)
 
        octx->count = sctx->count;
        memcpy(octx->state, sctx->state, sizeof(octx->state));
-       memcpy(octx->buffer, sctx->buf, sizeof(octx->buffer));
        return 0;
 }
 
@@ -60,7 +59,6 @@ static int s390_sha1_import(struct shash_desc *desc, const void *in)
 
        sctx->count = ictx->count;
        memcpy(sctx->state, ictx->state, sizeof(ictx->state));
-       memcpy(sctx->buf, ictx->buffer, sizeof(ictx->buffer));
        sctx->func = CPACF_KIMD_SHA_1;
        return 0;
 }
@@ -68,16 +66,18 @@ static int s390_sha1_import(struct shash_desc *desc, const void *in)
 static struct shash_alg alg = {
        .digestsize     =       SHA1_DIGEST_SIZE,
        .init           =       s390_sha1_init,
-       .update         =       s390_sha_update,
-       .final          =       s390_sha_final,
+       .update         =       s390_sha_update_blocks,
+       .finup          =       s390_sha_finup,
        .export         =       s390_sha1_export,
        .import         =       s390_sha1_import,
-       .descsize       =       sizeof(struct s390_sha_ctx),
-       .statesize      =       sizeof(struct sha1_state),
+       .descsize       =       S390_SHA_CTX_SIZE,
+       .statesize      =       SHA1_STATE_SIZE,
        .base           =       {
                .cra_name       =       "sha1",
                .cra_driver_name=       "sha1-s390",
                .cra_priority   =       300,
+               .cra_flags      =       CRYPTO_AHASH_ALG_BLOCK_ONLY |
+                                       CRYPTO_AHASH_ALG_FINUP_MAX,
                .cra_blocksize  =       SHA1_BLOCK_SIZE,
                .cra_module     =       THIS_MODULE,
        }
index 961d7d522af157cda3ee489d338eef516f6d5979..013bb37ad3efbd2d88f1ff0cf9d9b84cccf76411 100644 (file)
@@ -58,6 +58,27 @@ store:
 }
 EXPORT_SYMBOL_GPL(s390_sha_update);
 
+int s390_sha_update_blocks(struct shash_desc *desc, const u8 *data,
+                          unsigned int len)
+{
+       unsigned int bsize = crypto_shash_blocksize(desc->tfm);
+       struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
+       unsigned int n;
+       int fc;
+
+       fc = ctx->func;
+       if (ctx->first_message_part)
+               fc |= test_facility(86) ? CPACF_KIMD_NIP : 0;
+
+       /* process as many blocks as possible */
+       n = (len / bsize) * bsize;
+       ctx->count += n;
+       cpacf_kimd(fc, ctx->state, data, n);
+       ctx->first_message_part = 0;
+       return len - n;
+}
+EXPORT_SYMBOL_GPL(s390_sha_update_blocks);
+
 static int s390_crypto_shash_parmsize(int func)
 {
        switch (func) {
@@ -132,5 +153,58 @@ int s390_sha_final(struct shash_desc *desc, u8 *out)
 }
 EXPORT_SYMBOL_GPL(s390_sha_final);
 
+int s390_sha_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
+                  u8 *out)
+{
+       struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
+       int mbl_offset, fc;
+       u64 bits;
+
+       ctx->count += len;
+
+       bits = ctx->count * 8;
+       mbl_offset = s390_crypto_shash_parmsize(ctx->func);
+       if (mbl_offset < 0)
+               return -EINVAL;
+
+       mbl_offset = mbl_offset / sizeof(u32);
+
+       /* set total msg bit length (mbl) in CPACF parmblock */
+       switch (ctx->func) {
+       case CPACF_KLMD_SHA_1:
+       case CPACF_KLMD_SHA_256:
+               memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
+               break;
+       case CPACF_KLMD_SHA_512:
+               /*
+                * the SHA512 parmblock has a 128-bit mbl field, clear
+                * high-order u64 field, copy bits to low-order u64 field
+                */
+               memset(ctx->state + mbl_offset, 0x00, sizeof(bits));
+               mbl_offset += sizeof(u64) / sizeof(u32);
+               memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
+               break;
+       case CPACF_KLMD_SHA3_224:
+       case CPACF_KLMD_SHA3_256:
+       case CPACF_KLMD_SHA3_384:
+       case CPACF_KLMD_SHA3_512:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       fc = ctx->func;
+       fc |= test_facility(86) ? CPACF_KLMD_DUFOP : 0;
+       if (ctx->first_message_part)
+               fc |= CPACF_KLMD_NIP;
+       cpacf_klmd(fc, ctx->state, src, len);
+
+       /* copy digest to out */
+       memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(s390_sha_finup);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("s390 SHA cipher common functions");