Skip to content

Commit

Permalink
s390/sha3: Support sha3 performance enhancements
Browse files Browse the repository at this point in the history
On newer machines the SHA3 performance of CPACF instructions KIMD and
KLMD can be enhanced by using additional modifier bits. This allows the
application to omit initializing the ICV, but also affects the internal
processing of the instructions. Performance is mostly gained when
processing short messages.

The new CPACF feature is backwards compatible with older machines, i.e.
the new modifier bits are ignored on older machines. However, to save the
ICV initialization, the application must detect the MSA level and omit
the ICV initialization only if this feature is supported.

Reviewed-by: Holger Dengler <[email protected]>
Signed-off-by: Joerg Schmidbauer <[email protected]>
Signed-off-by: Heiko Carstens <[email protected]>
Signed-off-by: Vasily Gorbik <[email protected]>
  • Loading branch information
jschmidb authored and Vasily Gorbik committed Aug 29, 2024
1 parent 177b621 commit 88c02b3
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 10 deletions.
1 change: 1 addition & 0 deletions arch/s390/crypto/sha.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct s390_sha_ctx {
u32 state[CPACF_MAX_PARMBLOCK_SIZE / sizeof(u32)];
u8 buf[SHA_MAX_BLOCK_SIZE];
int func; /* KIMD function to use */
int first_message_part;
};

struct shash_desc;
Expand Down
8 changes: 6 additions & 2 deletions arch/s390/crypto/sha3_256_s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ static int sha3_256_init(struct shash_desc *desc)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);

memset(sctx->state, 0, sizeof(sctx->state));
if (!test_facility(86)) /* msa 12 */
memset(sctx->state, 0, sizeof(sctx->state));
sctx->count = 0;
sctx->func = CPACF_KIMD_SHA3_256;
sctx->first_message_part = 1;

return 0;
}
Expand Down Expand Up @@ -88,9 +90,11 @@ static int sha3_224_init(struct shash_desc *desc)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);

memset(sctx->state, 0, sizeof(sctx->state));
if (!test_facility(86)) /* msa 12 */
memset(sctx->state, 0, sizeof(sctx->state));
sctx->count = 0;
sctx->func = CPACF_KIMD_SHA3_224;
sctx->first_message_part = 1;

return 0;
}
Expand Down
8 changes: 6 additions & 2 deletions arch/s390/crypto/sha3_512_s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ static int sha3_512_init(struct shash_desc *desc)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);

memset(sctx->state, 0, sizeof(sctx->state));
if (!test_facility(86)) /* msa 12 */
memset(sctx->state, 0, sizeof(sctx->state));
sctx->count = 0;
sctx->func = CPACF_KIMD_SHA3_512;
sctx->first_message_part = 1;

return 0;
}
Expand Down Expand Up @@ -97,9 +99,11 @@ static int sha3_384_init(struct shash_desc *desc)
{
struct s390_sha_ctx *sctx = shash_desc_ctx(desc);

memset(sctx->state, 0, sizeof(sctx->state));
if (!test_facility(86)) /* msa 12 */
memset(sctx->state, 0, sizeof(sctx->state));
sctx->count = 0;
sctx->func = CPACF_KIMD_SHA3_384;
sctx->first_message_part = 1;

return 0;
}
Expand Down
19 changes: 15 additions & 4 deletions arch/s390/crypto/sha_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
unsigned int bsize = crypto_shash_blocksize(desc->tfm);
unsigned int index, n;
int fc;

/* how much is already in the buffer? */
index = ctx->count % bsize;
Expand All @@ -26,10 +27,15 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
if ((index + len) < bsize)
goto store;

fc = ctx->func;
if (ctx->first_message_part)
fc |= test_facility(86) ? CPACF_KIMD_NIP : 0;

/* process one stored block */
if (index) {
memcpy(ctx->buf + index, data, bsize - index);
cpacf_kimd(ctx->func, ctx->state, ctx->buf, bsize);
cpacf_kimd(fc, ctx->state, ctx->buf, bsize);
ctx->first_message_part = 0;
data += bsize - index;
len -= bsize - index;
index = 0;
Expand All @@ -38,7 +44,8 @@ int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
/* process as many blocks as possible */
if (len >= bsize) {
n = (len / bsize) * bsize;
cpacf_kimd(ctx->func, ctx->state, data, n);
cpacf_kimd(fc, ctx->state, data, n);
ctx->first_message_part = 0;
data += n;
len -= n;
}
Expand Down Expand Up @@ -75,7 +82,7 @@ int s390_sha_final(struct shash_desc *desc, u8 *out)
unsigned int bsize = crypto_shash_blocksize(desc->tfm);
u64 bits;
unsigned int n;
int mbl_offset;
int mbl_offset, fc;

n = ctx->count % bsize;
bits = ctx->count * 8;
Expand Down Expand Up @@ -109,7 +116,11 @@ int s390_sha_final(struct shash_desc *desc, u8 *out)
return -EINVAL;
}

cpacf_klmd(ctx->func, ctx->state, ctx->buf, n);
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, ctx->buf, n);

/* copy digest to out */
memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
Expand Down
12 changes: 10 additions & 2 deletions arch/s390/include/asm/cpacf.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@
#define CPACF_KMA_LAAD 0x200 /* Last-AAD */
#define CPACF_KMA_HS 0x400 /* Hash-subkey Supplied */

/*
* Flags for the KIMD/KLMD (COMPUTE INTERMEDIATE/LAST MESSAGE DIGEST)
* instructions
*/
#define CPACF_KIMD_NIP 0x8000
#define CPACF_KLMD_DUFOP 0x4000
#define CPACF_KLMD_NIP 0x8000

typedef struct { unsigned char bytes[16]; } cpacf_mask_t;

/*
Expand Down Expand Up @@ -397,7 +405,7 @@ static inline void cpacf_kimd(unsigned long func, void *param,
asm volatile(
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,0,%[src]\n"
"0: .insn rrf,%[opc] << 16,0,%[src],8,0\n"
" brc 1,0b\n" /* handle partial completion */
: [src] "+&d" (s.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)(param)),
Expand All @@ -422,7 +430,7 @@ static inline void cpacf_klmd(unsigned long func, void *param,
asm volatile(
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,0,%[src]\n"
"0: .insn rrf,%[opc] << 16,0,%[src],8,0\n"
" brc 1,0b\n" /* handle partial completion */
: [src] "+&d" (s.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
Expand Down

0 comments on commit 88c02b3

Please sign in to comment.