Skip to content

Commit 666300d

Browse files
holger-denglerhcahca
authored andcommitted
s390/crypto: Add hardware acceleration for full AES-XTS mode
Extend the existing paes cipher to exploit the full AES-XTS hardware acceleration introduced with message-security assist extension 10. The full AES-XTS mode requires a protected key of type PKEY_KEYTYPE_AES_XTS_128 or PKEY_KEYTYPE_AES_XTS_256. Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Holger Dengler <dengler@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent f4d3cf6 commit 666300d

File tree

2 files changed

+106
-5
lines changed

2 files changed

+106
-5
lines changed

arch/s390/crypto/paes_s390.c

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#define PAES_MIN_KEYSIZE 16
3838
#define PAES_MAX_KEYSIZE MAXEP11AESKEYBLOBSIZE
3939
#define PAES_256_PROTKEY_SIZE (32 + 32) /* key + verification pattern */
40+
#define PXTS_256_PROTKEY_SIZE (32 + 32 + 32) /* k1 + k2 + verification pattern */
4041

4142
static u8 *ctrblk;
4243
static DEFINE_MUTEX(ctrblk_lock);
@@ -46,7 +47,7 @@ static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
4647
struct paes_protkey {
4748
u32 type;
4849
u32 len;
49-
u8 protkey[PAES_256_PROTKEY_SIZE];
50+
u8 protkey[PXTS_256_PROTKEY_SIZE];
5051
};
5152

5253
struct key_blob {
@@ -159,6 +160,7 @@ static inline void _free_kb_keybuf(struct key_blob *kb)
159160
kfree_sensitive(kb->key);
160161
kb->key = NULL;
161162
}
163+
memzero_explicit(kb->keybuf, sizeof(kb->keybuf));
162164
}
163165

164166
struct s390_paes_ctx {
@@ -491,6 +493,11 @@ static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx)
491493
if (pk0.type != pk1.type)
492494
return -EINVAL;
493495
break;
496+
case PKEY_KEYTYPE_AES_XTS_128:
497+
case PKEY_KEYTYPE_AES_XTS_256:
498+
/* single key */
499+
pk1.type = 0;
500+
break;
494501
default:
495502
/* unsupported protected keytype */
496503
return -EINVAL;
@@ -514,9 +521,23 @@ static inline int __xts_paes_set_key(struct s390_pxts_ctx *ctx)
514521
return rc;
515522

516523
/* Pick the correct function code based on the protected key type */
517-
fc = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PXTS_128 :
518-
(ctx->pk[0].type == PKEY_KEYTYPE_AES_256) ?
519-
CPACF_KM_PXTS_256 : 0;
524+
switch (ctx->pk[0].type) {
525+
case PKEY_KEYTYPE_AES_128:
526+
fc = CPACF_KM_PXTS_128;
527+
break;
528+
case PKEY_KEYTYPE_AES_256:
529+
fc = CPACF_KM_PXTS_256;
530+
break;
531+
case PKEY_KEYTYPE_AES_XTS_128:
532+
fc = CPACF_KM_PXTS_128_FULL;
533+
break;
534+
case PKEY_KEYTYPE_AES_XTS_256:
535+
fc = CPACF_KM_PXTS_256_FULL;
536+
break;
537+
default:
538+
fc = 0;
539+
break;
540+
}
520541

521542
/* Check if the function code is available */
522543
ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0;
@@ -545,6 +566,13 @@ static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
545566
if (rc)
546567
return rc;
547568

569+
/*
570+
* It is not possible on a single protected key (e.g. full AES-XTS) to
571+
* check, if k1 and k2 are the same.
572+
*/
573+
if (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128 ||
574+
ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_256)
575+
return 0;
548576
/*
549577
* xts_verify_key verifies the key length is not odd and makes
550578
* sure that the two keys are not the same. This can be done
@@ -557,7 +585,61 @@ static int xts_paes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
557585
return xts_verify_key(tfm, ckey, 2*ckey_len);
558586
}
559587

560-
static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
588+
static int paes_xts_crypt_full(struct skcipher_request *req,
589+
unsigned long modifier)
590+
{
591+
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
592+
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
593+
unsigned int keylen, offset, nbytes, n, k;
594+
struct {
595+
u8 key[64];
596+
u8 tweak[16];
597+
u8 nap[16];
598+
u8 wkvp[32];
599+
} fxts_param = {
600+
.nap = {0},
601+
};
602+
struct skcipher_walk walk;
603+
int rc;
604+
605+
rc = skcipher_walk_virt(&walk, req, false);
606+
if (rc)
607+
return rc;
608+
609+
keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128) ? 32 : 64;
610+
offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_XTS_128) ? 32 : 0;
611+
612+
spin_lock_bh(&ctx->pk_lock);
613+
memcpy(fxts_param.key + offset, ctx->pk[0].protkey, keylen);
614+
memcpy(fxts_param.wkvp, ctx->pk[0].protkey + keylen,
615+
sizeof(fxts_param.wkvp));
616+
spin_unlock_bh(&ctx->pk_lock);
617+
memcpy(fxts_param.tweak, walk.iv, sizeof(fxts_param.tweak));
618+
fxts_param.nap[0] = 0x01; /* initial alpha power (1, little-endian) */
619+
620+
while ((nbytes = walk.nbytes) != 0) {
621+
/* only use complete blocks */
622+
n = nbytes & ~(AES_BLOCK_SIZE - 1);
623+
k = cpacf_km(ctx->fc | modifier, fxts_param.key + offset,
624+
walk.dst.virt.addr, walk.src.virt.addr, n);
625+
if (k)
626+
rc = skcipher_walk_done(&walk, nbytes - k);
627+
if (k < n) {
628+
if (__xts_paes_convert_key(ctx))
629+
return skcipher_walk_done(&walk, -EIO);
630+
spin_lock_bh(&ctx->pk_lock);
631+
memcpy(fxts_param.key + offset, ctx->pk[0].protkey,
632+
keylen);
633+
memcpy(fxts_param.wkvp, ctx->pk[0].protkey + keylen,
634+
sizeof(fxts_param.wkvp));
635+
spin_unlock_bh(&ctx->pk_lock);
636+
}
637+
}
638+
639+
return rc;
640+
}
641+
642+
static int paes_xts_crypt(struct skcipher_request *req, unsigned long modifier)
561643
{
562644
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
563645
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
@@ -612,6 +694,23 @@ static int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
612694
return rc;
613695
}
614696

697+
static inline int xts_paes_crypt(struct skcipher_request *req, unsigned long modifier)
698+
{
699+
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
700+
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
701+
702+
switch (ctx->fc) {
703+
case CPACF_KM_PXTS_128:
704+
case CPACF_KM_PXTS_256:
705+
return paes_xts_crypt(req, modifier);
706+
case CPACF_KM_PXTS_128_FULL:
707+
case CPACF_KM_PXTS_256_FULL:
708+
return paes_xts_crypt_full(req, modifier);
709+
default:
710+
return -EINVAL;
711+
}
712+
}
713+
615714
static int xts_paes_encrypt(struct skcipher_request *req)
616715
{
617716
return xts_paes_crypt(req, 0);

arch/s390/include/asm/cpacf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
#define CPACF_KM_PXTS_256 0x3c
5757
#define CPACF_KM_XTS_128_FULL 0x52
5858
#define CPACF_KM_XTS_256_FULL 0x54
59+
#define CPACF_KM_PXTS_128_FULL 0x5a
60+
#define CPACF_KM_PXTS_256_FULL 0x5c
5961

6062
/*
6163
* Function codes for the KMC (CIPHER MESSAGE WITH CHAINING)

0 commit comments

Comments
 (0)