mirror of
https://github.com/torvalds/linux.git
synced 2025-04-09 14:45:27 +00:00
s390/crypto: Add hardware acceleration for full AES-XTS mode
Add new cipher exploiting the full AES-XTS hardware acceleration introduced with message-security assist extension 10. The full AES-XTS cipher is registered as preferred cipher in addition to the discrete AES-XTS variant. Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Holger Dengler <dengler@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
4f7a31a7ef
commit
80625b6703
@ -51,8 +51,13 @@ struct s390_aes_ctx {
|
||||
};
|
||||
|
||||
struct s390_xts_ctx {
|
||||
u8 key[32];
|
||||
u8 pcc_key[32];
|
||||
union {
|
||||
u8 keys[64];
|
||||
struct {
|
||||
u8 key[32];
|
||||
u8 pcc_key[32];
|
||||
};
|
||||
};
|
||||
int key_len;
|
||||
unsigned long fc;
|
||||
struct crypto_skcipher *fallback;
|
||||
@ -526,6 +531,108 @@ static struct skcipher_alg xts_aes_alg = {
|
||||
.decrypt = xts_aes_decrypt,
|
||||
};
|
||||
|
||||
static int fullxts_aes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct s390_xts_ctx *xts_ctx = crypto_skcipher_ctx(tfm);
|
||||
unsigned long fc;
|
||||
int err;
|
||||
|
||||
err = xts_fallback_setkey(tfm, in_key, key_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Pick the correct function code based on the key length */
|
||||
fc = (key_len == 32) ? CPACF_KM_XTS_128_FULL :
|
||||
(key_len == 64) ? CPACF_KM_XTS_256_FULL : 0;
|
||||
|
||||
/* Check if the function code is available */
|
||||
xts_ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0;
|
||||
if (!xts_ctx->fc)
|
||||
return 0;
|
||||
|
||||
/* Store double-key */
|
||||
memcpy(xts_ctx->keys, in_key, key_len);
|
||||
xts_ctx->key_len = key_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fullxts_aes_crypt(struct skcipher_request *req, unsigned long modifier)
|
||||
{
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
struct s390_xts_ctx *xts_ctx = crypto_skcipher_ctx(tfm);
|
||||
unsigned int offset, nbytes, n;
|
||||
struct skcipher_walk walk;
|
||||
int ret;
|
||||
struct {
|
||||
__u8 key[64];
|
||||
__u8 tweak[16];
|
||||
__u8 nap[16];
|
||||
} fxts_param = {
|
||||
.nap = {0},
|
||||
};
|
||||
|
||||
if (req->cryptlen < AES_BLOCK_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (unlikely(!xts_ctx->fc || (req->cryptlen % AES_BLOCK_SIZE) != 0)) {
|
||||
struct skcipher_request *subreq = skcipher_request_ctx(req);
|
||||
|
||||
*subreq = *req;
|
||||
skcipher_request_set_tfm(subreq, xts_ctx->fallback);
|
||||
return (modifier & CPACF_DECRYPT) ?
|
||||
crypto_skcipher_decrypt(subreq) :
|
||||
crypto_skcipher_encrypt(subreq);
|
||||
}
|
||||
|
||||
ret = skcipher_walk_virt(&walk, req, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
offset = xts_ctx->key_len & 0x20;
|
||||
memcpy(fxts_param.key + offset, xts_ctx->keys, xts_ctx->key_len);
|
||||
memcpy(fxts_param.tweak, req->iv, AES_BLOCK_SIZE);
|
||||
fxts_param.nap[0] = 0x01; /* initial alpha power (1, little-endian) */
|
||||
|
||||
while ((nbytes = walk.nbytes) != 0) {
|
||||
/* only use complete blocks */
|
||||
n = nbytes & ~(AES_BLOCK_SIZE - 1);
|
||||
cpacf_km(xts_ctx->fc | modifier, fxts_param.key + offset,
|
||||
walk.dst.virt.addr, walk.src.virt.addr, n);
|
||||
ret = skcipher_walk_done(&walk, nbytes - n);
|
||||
}
|
||||
memzero_explicit(&fxts_param, sizeof(fxts_param));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fullxts_aes_encrypt(struct skcipher_request *req)
|
||||
{
|
||||
return fullxts_aes_crypt(req, 0);
|
||||
}
|
||||
|
||||
static int fullxts_aes_decrypt(struct skcipher_request *req)
|
||||
{
|
||||
return fullxts_aes_crypt(req, CPACF_DECRYPT);
|
||||
}
|
||||
|
||||
static struct skcipher_alg fullxts_aes_alg = {
|
||||
.base.cra_name = "xts(aes)",
|
||||
.base.cra_driver_name = "full-xts-aes-s390",
|
||||
.base.cra_priority = 403, /* aes-xts-s390 + 1 */
|
||||
.base.cra_flags = CRYPTO_ALG_NEED_FALLBACK,
|
||||
.base.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.base.cra_ctxsize = sizeof(struct s390_xts_ctx),
|
||||
.base.cra_module = THIS_MODULE,
|
||||
.init = xts_fallback_init,
|
||||
.exit = xts_fallback_exit,
|
||||
.min_keysize = 2 * AES_MIN_KEY_SIZE,
|
||||
.max_keysize = 2 * AES_MAX_KEY_SIZE,
|
||||
.ivsize = AES_BLOCK_SIZE,
|
||||
.setkey = fullxts_aes_set_key,
|
||||
.encrypt = fullxts_aes_encrypt,
|
||||
.decrypt = fullxts_aes_decrypt,
|
||||
};
|
||||
|
||||
static int ctr_aes_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
@ -955,7 +1062,7 @@ static struct aead_alg gcm_aes_aead = {
|
||||
};
|
||||
|
||||
static struct crypto_alg *aes_s390_alg;
|
||||
static struct skcipher_alg *aes_s390_skcipher_algs[4];
|
||||
static struct skcipher_alg *aes_s390_skcipher_algs[5];
|
||||
static int aes_s390_skciphers_num;
|
||||
static struct aead_alg *aes_s390_aead_alg;
|
||||
|
||||
@ -1012,6 +1119,13 @@ static int __init aes_s390_init(void)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (cpacf_test_func(&km_functions, CPACF_KM_XTS_128_FULL) ||
|
||||
cpacf_test_func(&km_functions, CPACF_KM_XTS_256_FULL)) {
|
||||
ret = aes_s390_register_skcipher(&fullxts_aes_alg);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (cpacf_test_func(&km_functions, CPACF_KM_XTS_128) ||
|
||||
cpacf_test_func(&km_functions, CPACF_KM_XTS_256)) {
|
||||
ret = aes_s390_register_skcipher(&xts_aes_alg);
|
||||
|
@ -54,6 +54,8 @@
|
||||
#define CPACF_KM_XTS_256 0x34
|
||||
#define CPACF_KM_PXTS_128 0x3a
|
||||
#define CPACF_KM_PXTS_256 0x3c
|
||||
#define CPACF_KM_XTS_128_FULL 0x52
|
||||
#define CPACF_KM_XTS_256_FULL 0x54
|
||||
|
||||
/*
|
||||
* Function codes for the KMC (CIPHER MESSAGE WITH CHAINING)
|
||||
|
Loading…
x
Reference in New Issue
Block a user