Skip to content

Commit 0881116

Browse files
committed
crypto: s390/hmac - Use API partial block handling
Use the Crypto API partial block handling. Also switch to the generic export format. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 3bf5337 commit 0881116

File tree

1 file changed

+108
-47
lines changed

1 file changed

+108
-47
lines changed

arch/s390/crypto/hmac_s390.c

Lines changed: 108 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@
99
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1010

1111
#include <asm/cpacf.h>
12-
#include <crypto/sha2.h>
1312
#include <crypto/internal/hash.h>
13+
#include <crypto/hmac.h>
14+
#include <crypto/sha2.h>
1415
#include <linux/cpufeature.h>
16+
#include <linux/errno.h>
17+
#include <linux/kernel.h>
1518
#include <linux/module.h>
19+
#include <linux/string.h>
1620

1721
/*
1822
* KMAC param block layout for sha2 function codes:
@@ -71,7 +75,6 @@ union s390_kmac_gr0 {
7175
struct s390_kmac_sha2_ctx {
7276
u8 param[MAX_DIGEST_SIZE + MAX_IMBL_SIZE + MAX_BLOCK_SIZE];
7377
union s390_kmac_gr0 gr0;
74-
u8 buf[MAX_BLOCK_SIZE];
7578
u64 buflen[2];
7679
};
7780

@@ -95,8 +98,8 @@ static inline void kmac_sha2_set_imbl(u8 *param, u64 buflen_lo,
9598
}
9699
}
97100

98-
static int hash_key(const u8 *in, unsigned int inlen,
99-
u8 *digest, unsigned int digestsize)
101+
static int hash_data(const u8 *in, unsigned int inlen,
102+
u8 *digest, unsigned int digestsize, bool final)
100103
{
101104
unsigned long func;
102105
union {
@@ -123,19 +126,23 @@ static int hash_key(const u8 *in, unsigned int inlen,
123126

124127
switch (digestsize) {
125128
case SHA224_DIGEST_SIZE:
126-
func = CPACF_KLMD_SHA_256;
129+
func = final ? CPACF_KLMD_SHA_256 : CPACF_KIMD_SHA_256;
127130
PARAM_INIT(256, 224, inlen * 8);
131+
if (!final)
132+
digestsize = SHA256_DIGEST_SIZE;
128133
break;
129134
case SHA256_DIGEST_SIZE:
130-
func = CPACF_KLMD_SHA_256;
135+
func = final ? CPACF_KLMD_SHA_256 : CPACF_KIMD_SHA_256;
131136
PARAM_INIT(256, 256, inlen * 8);
132137
break;
133138
case SHA384_DIGEST_SIZE:
134-
func = CPACF_KLMD_SHA_512;
139+
func = final ? CPACF_KLMD_SHA_512 : CPACF_KIMD_SHA_512;
135140
PARAM_INIT(512, 384, inlen * 8);
141+
if (!final)
142+
digestsize = SHA512_DIGEST_SIZE;
136143
break;
137144
case SHA512_DIGEST_SIZE:
138-
func = CPACF_KLMD_SHA_512;
145+
func = final ? CPACF_KLMD_SHA_512 : CPACF_KIMD_SHA_512;
139146
PARAM_INIT(512, 512, inlen * 8);
140147
break;
141148
default:
@@ -151,6 +158,12 @@ static int hash_key(const u8 *in, unsigned int inlen,
151158
return 0;
152159
}
153160

161+
static int hash_key(const u8 *in, unsigned int inlen,
162+
u8 *digest, unsigned int digestsize)
163+
{
164+
return hash_data(in, inlen, digest, digestsize, true);
165+
}
166+
154167
static int s390_hmac_sha2_setkey(struct crypto_shash *tfm,
155168
const u8 *key, unsigned int keylen)
156169
{
@@ -204,50 +217,31 @@ static int s390_hmac_sha2_update(struct shash_desc *desc,
204217
{
205218
struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
206219
unsigned int bs = crypto_shash_blocksize(desc->tfm);
207-
unsigned int offset, n;
220+
unsigned int n = round_down(len, bs);
208221

209-
/* check current buffer */
210-
offset = ctx->buflen[0] % bs;
211-
ctx->buflen[0] += len;
212-
if (ctx->buflen[0] < len)
222+
ctx->buflen[0] += n;
223+
if (ctx->buflen[0] < n)
213224
ctx->buflen[1]++;
214-
if (offset + len < bs)
215-
goto store;
216-
217-
/* process one stored block */
218-
if (offset) {
219-
n = bs - offset;
220-
memcpy(ctx->buf + offset, data, n);
221-
ctx->gr0.iimp = 1;
222-
_cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, bs);
223-
data += n;
224-
len -= n;
225-
offset = 0;
226-
}
227-
/* process as many blocks as possible */
228-
if (len >= bs) {
229-
n = (len / bs) * bs;
230-
ctx->gr0.iimp = 1;
231-
_cpacf_kmac(&ctx->gr0.reg, ctx->param, data, n);
232-
data += n;
233-
len -= n;
234-
}
235-
store:
236-
/* store incomplete block in buffer */
237-
if (len)
238-
memcpy(ctx->buf + offset, data, len);
239225

240-
return 0;
226+
/* process as many blocks as possible */
227+
ctx->gr0.iimp = 1;
228+
_cpacf_kmac(&ctx->gr0.reg, ctx->param, data, n);
229+
return len - n;
241230
}
242231

243-
static int s390_hmac_sha2_final(struct shash_desc *desc, u8 *out)
232+
static int s390_hmac_sha2_finup(struct shash_desc *desc, const u8 *src,
233+
unsigned int len, u8 *out)
244234
{
245235
struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
246236
unsigned int bs = crypto_shash_blocksize(desc->tfm);
247237

238+
ctx->buflen[0] += len;
239+
if (ctx->buflen[0] < len)
240+
ctx->buflen[1]++;
241+
248242
ctx->gr0.iimp = 0;
249243
kmac_sha2_set_imbl(ctx->param, ctx->buflen[0], ctx->buflen[1], bs);
250-
_cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, ctx->buflen[0] % bs);
244+
_cpacf_kmac(&ctx->gr0.reg, ctx->param, src, len);
251245
memcpy(out, ctx->param, crypto_shash_digestsize(desc->tfm));
252246

253247
return 0;
@@ -273,22 +267,89 @@ static int s390_hmac_sha2_digest(struct shash_desc *desc,
273267
return 0;
274268
}
275269

276-
#define S390_HMAC_SHA2_ALG(x) { \
270+
static int s390_hmac_export_zero(struct shash_desc *desc, void *out)
271+
{
272+
struct crypto_shash *tfm = desc->tfm;
273+
u8 ipad[SHA512_BLOCK_SIZE];
274+
struct s390_hmac_ctx *ctx;
275+
unsigned int bs;
276+
int err, i;
277+
278+
ctx = crypto_shash_ctx(tfm);
279+
bs = crypto_shash_blocksize(tfm);
280+
for (i = 0; i < bs; i++)
281+
ipad[i] = ctx->key[i] ^ HMAC_IPAD_VALUE;
282+
283+
err = hash_data(ipad, bs, out, crypto_shash_digestsize(tfm), false);
284+
memzero_explicit(ipad, sizeof(ipad));
285+
return err;
286+
}
287+
288+
static int s390_hmac_export(struct shash_desc *desc, void *out)
289+
{
290+
struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
291+
unsigned int bs = crypto_shash_blocksize(desc->tfm);
292+
unsigned int ds = bs / 2;
293+
union {
294+
u8 *u8;
295+
u64 *u64;
296+
} p = { .u8 = out };
297+
int err = 0;
298+
299+
if (!ctx->gr0.ikp)
300+
err = s390_hmac_export_zero(desc, out);
301+
else
302+
memcpy(p.u8, ctx->param, ds);
303+
p.u8 += ds;
304+
put_unaligned(ctx->buflen[0], p.u64++);
305+
if (ds == SHA512_DIGEST_SIZE)
306+
put_unaligned(ctx->buflen[1], p.u64);
307+
return err;
308+
}
309+
310+
static int s390_hmac_import(struct shash_desc *desc, const void *in)
311+
{
312+
struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
313+
unsigned int bs = crypto_shash_blocksize(desc->tfm);
314+
unsigned int ds = bs / 2;
315+
union {
316+
const u8 *u8;
317+
const u64 *u64;
318+
} p = { .u8 = in };
319+
int err;
320+
321+
err = s390_hmac_sha2_init(desc);
322+
memcpy(ctx->param, p.u8, ds);
323+
p.u8 += ds;
324+
ctx->buflen[0] = get_unaligned(p.u64++);
325+
if (ds == SHA512_DIGEST_SIZE)
326+
ctx->buflen[1] = get_unaligned(p.u64);
327+
if (ctx->buflen[0] | ctx->buflen[1])
328+
ctx->gr0.ikp = 1;
329+
return err;
330+
}
331+
332+
#define S390_HMAC_SHA2_ALG(x, ss) { \
277333
.fc = CPACF_KMAC_HMAC_SHA_##x, \
278334
.alg = { \
279335
.init = s390_hmac_sha2_init, \
280336
.update = s390_hmac_sha2_update, \
281-
.final = s390_hmac_sha2_final, \
337+
.finup = s390_hmac_sha2_finup, \
282338
.digest = s390_hmac_sha2_digest, \
283339
.setkey = s390_hmac_sha2_setkey, \
340+
.export = s390_hmac_export, \
341+
.import = s390_hmac_import, \
284342
.descsize = sizeof(struct s390_kmac_sha2_ctx), \
285343
.halg = { \
344+
.statesize = ss, \
286345
.digestsize = SHA##x##_DIGEST_SIZE, \
287346
.base = { \
288347
.cra_name = "hmac(sha" #x ")", \
289348
.cra_driver_name = "hmac_s390_sha" #x, \
290349
.cra_blocksize = SHA##x##_BLOCK_SIZE, \
291350
.cra_priority = 400, \
351+
.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY | \
352+
CRYPTO_AHASH_ALG_FINUP_MAX, \
292353
.cra_ctxsize = sizeof(struct s390_hmac_ctx), \
293354
.cra_module = THIS_MODULE, \
294355
}, \
@@ -301,10 +362,10 @@ static struct s390_hmac_alg {
301362
unsigned int fc;
302363
struct shash_alg alg;
303364
} s390_hmac_algs[] = {
304-
S390_HMAC_SHA2_ALG(224),
305-
S390_HMAC_SHA2_ALG(256),
306-
S390_HMAC_SHA2_ALG(384),
307-
S390_HMAC_SHA2_ALG(512),
365+
S390_HMAC_SHA2_ALG(224, sizeof(struct crypto_sha256_state)),
366+
S390_HMAC_SHA2_ALG(256, sizeof(struct crypto_sha256_state)),
367+
S390_HMAC_SHA2_ALG(384, SHA512_STATE_SIZE),
368+
S390_HMAC_SHA2_ALG(512, SHA512_STATE_SIZE),
308369
};
309370

310371
static __always_inline void _s390_hmac_algs_unregister(void)

0 commit comments

Comments
 (0)