summaryrefslogtreecommitdiffstats
path: root/arch/s390/crypto/sha_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/crypto/sha_common.c')
-rw-r--r--arch/s390/crypto/sha_common.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c
index 686fe7aa192f..961d7d522af1 100644
--- a/arch/s390/crypto/sha_common.c
+++ b/arch/s390/crypto/sha_common.c
@@ -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;
@@ -26,10 +27,16 @@ 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;
+ fc &= ~CPACF_KIMD_NIP;
data += bsize - index;
len -= bsize - index;
index = 0;
@@ -38,7 +45,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;
}
@@ -75,7 +83,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;
@@ -109,7 +117,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));