1 // SPDX-License-Identifier: GPL-2.0-only
3 * AES CBC routines supporting VMX instructions on the Power 8
5 * Copyright (C) 2015 International Business Machines Inc.
7 * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>
11 #include <asm/switch_to.h>
12 #include <crypto/aes.h>
13 #include <crypto/internal/simd.h>
14 #include <crypto/internal/skcipher.h>
16 #include "aesp8-ppc.h"
18 struct p8_aes_cbc_ctx
{
19 struct crypto_skcipher
*fallback
;
20 struct aes_key enc_key
;
21 struct aes_key dec_key
;
24 static int p8_aes_cbc_init(struct crypto_skcipher
*tfm
)
26 struct p8_aes_cbc_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
27 struct crypto_skcipher
*fallback
;
29 fallback
= crypto_alloc_skcipher("cbc(aes)", 0,
30 CRYPTO_ALG_NEED_FALLBACK
|
32 if (IS_ERR(fallback
)) {
33 pr_err("Failed to allocate cbc(aes) fallback: %ld\n",
35 return PTR_ERR(fallback
);
38 crypto_skcipher_set_reqsize(tfm
, sizeof(struct skcipher_request
) +
39 crypto_skcipher_reqsize(fallback
));
40 ctx
->fallback
= fallback
;
44 static void p8_aes_cbc_exit(struct crypto_skcipher
*tfm
)
46 struct p8_aes_cbc_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
48 crypto_free_skcipher(ctx
->fallback
);
51 static int p8_aes_cbc_setkey(struct crypto_skcipher
*tfm
, const u8
*key
,
54 struct p8_aes_cbc_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
60 ret
= aes_p8_set_encrypt_key(key
, keylen
* 8, &ctx
->enc_key
);
61 ret
|= aes_p8_set_decrypt_key(key
, keylen
* 8, &ctx
->dec_key
);
66 ret
|= crypto_skcipher_setkey(ctx
->fallback
, key
, keylen
);
68 return ret
? -EINVAL
: 0;
71 static int p8_aes_cbc_crypt(struct skcipher_request
*req
, int enc
)
73 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
74 const struct p8_aes_cbc_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
75 struct skcipher_walk walk
;
79 if (!crypto_simd_usable()) {
80 struct skcipher_request
*subreq
= skcipher_request_ctx(req
);
83 skcipher_request_set_tfm(subreq
, ctx
->fallback
);
84 return enc
? crypto_skcipher_encrypt(subreq
) :
85 crypto_skcipher_decrypt(subreq
);
88 ret
= skcipher_walk_virt(&walk
, req
, false);
89 while ((nbytes
= walk
.nbytes
) != 0) {
93 aes_p8_cbc_encrypt(walk
.src
.virt
.addr
,
95 round_down(nbytes
, AES_BLOCK_SIZE
),
96 enc
? &ctx
->enc_key
: &ctx
->dec_key
,
102 ret
= skcipher_walk_done(&walk
, nbytes
% AES_BLOCK_SIZE
);
107 static int p8_aes_cbc_encrypt(struct skcipher_request
*req
)
109 return p8_aes_cbc_crypt(req
, 1);
112 static int p8_aes_cbc_decrypt(struct skcipher_request
*req
)
114 return p8_aes_cbc_crypt(req
, 0);
117 struct skcipher_alg p8_aes_cbc_alg
= {
118 .base
.cra_name
= "cbc(aes)",
119 .base
.cra_driver_name
= "p8_aes_cbc",
120 .base
.cra_module
= THIS_MODULE
,
121 .base
.cra_priority
= 2000,
122 .base
.cra_flags
= CRYPTO_ALG_NEED_FALLBACK
,
123 .base
.cra_blocksize
= AES_BLOCK_SIZE
,
124 .base
.cra_ctxsize
= sizeof(struct p8_aes_cbc_ctx
),
125 .setkey
= p8_aes_cbc_setkey
,
126 .encrypt
= p8_aes_cbc_encrypt
,
127 .decrypt
= p8_aes_cbc_decrypt
,
128 .init
= p8_aes_cbc_init
,
129 .exit
= p8_aes_cbc_exit
,
130 .min_keysize
= AES_MIN_KEY_SIZE
,
131 .max_keysize
= AES_MAX_KEY_SIZE
,
132 .ivsize
= AES_BLOCK_SIZE
,