Commit | Line | Data |
---|---|---|
64d85cc9 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
dbb153c0 | 2 | /* |
8c755ace MC |
3 | * AES CBC routines supporting VMX instructions on the Power 8 |
4 | * | |
5 | * Copyright (C) 2015 International Business Machines Inc. | |
6 | * | |
8c755ace MC |
7 | * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com> |
8 | */ | |
9 | ||
626ddb2f | 10 | #include <asm/simd.h> |
8c755ace MC |
11 | #include <asm/switch_to.h> |
12 | #include <crypto/aes.h> | |
626ddb2f | 13 | #include <crypto/internal/simd.h> |
2621a869 | 14 | #include <crypto/internal/skcipher.h> |
8c755ace MC |
15 | |
16 | #include "aesp8-ppc.h" | |
17 | ||
18 | struct p8_aes_cbc_ctx { | |
2621a869 | 19 | struct crypto_skcipher *fallback; |
4beb1060 HX |
20 | struct aes_key enc_key; |
21 | struct aes_key dec_key; | |
8c755ace MC |
22 | }; |
23 | ||
2621a869 | 24 | static int p8_aes_cbc_init(struct crypto_skcipher *tfm) |
8c755ace | 25 | { |
2621a869 EB |
26 | struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); |
27 | struct crypto_skcipher *fallback; | |
c96d0a1c | 28 | |
2621a869 EB |
29 | fallback = crypto_alloc_skcipher("cbc(aes)", 0, |
30 | CRYPTO_ALG_NEED_FALLBACK | | |
31 | CRYPTO_ALG_ASYNC); | |
4beb1060 | 32 | if (IS_ERR(fallback)) { |
2621a869 EB |
33 | pr_err("Failed to allocate cbc(aes) fallback: %ld\n", |
34 | PTR_ERR(fallback)); | |
4beb1060 HX |
35 | return PTR_ERR(fallback); |
36 | } | |
4beb1060 | 37 | |
2621a869 EB |
38 | crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) + |
39 | crypto_skcipher_reqsize(fallback)); | |
4beb1060 | 40 | ctx->fallback = fallback; |
4beb1060 | 41 | return 0; |
8c755ace MC |
42 | } |
43 | ||
2621a869 | 44 | static void p8_aes_cbc_exit(struct crypto_skcipher *tfm) |
8c755ace | 45 | { |
2621a869 | 46 | struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); |
8c755ace | 47 | |
2621a869 | 48 | crypto_free_skcipher(ctx->fallback); |
8c755ace MC |
49 | } |
50 | ||
2621a869 | 51 | static int p8_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key, |
4beb1060 | 52 | unsigned int keylen) |
8c755ace | 53 | { |
2621a869 | 54 | struct p8_aes_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); |
4beb1060 | 55 | int ret; |
8c755ace | 56 | |
44d21c3f | 57 | preempt_disable(); |
4beb1060 | 58 | pagefault_disable(); |
2d6f0600 | 59 | enable_kernel_vsx(); |
4beb1060 | 60 | ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key); |
694e0db6 | 61 | ret |= aes_p8_set_decrypt_key(key, keylen * 8, &ctx->dec_key); |
dc4fbba1 | 62 | disable_kernel_vsx(); |
4beb1060 | 63 | pagefault_enable(); |
44d21c3f | 64 | preempt_enable(); |
8c755ace | 65 | |
2621a869 | 66 | ret |= crypto_skcipher_setkey(ctx->fallback, key, keylen); |
694e0db6 EB |
67 | |
68 | return ret ? -EINVAL : 0; | |
8c755ace MC |
69 | } |
70 | ||
2621a869 | 71 | static int p8_aes_cbc_crypt(struct skcipher_request *req, int enc) |
8c755ace | 72 | { |
2621a869 EB |
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; | |
76 | unsigned int nbytes; | |
4beb1060 | 77 | int ret; |
4beb1060 | 78 | |
626ddb2f | 79 | if (!crypto_simd_usable()) { |
2621a869 EB |
80 | struct skcipher_request *subreq = skcipher_request_ctx(req); |
81 | ||
82 | *subreq = *req; | |
83 | skcipher_request_set_tfm(subreq, ctx->fallback); | |
84 | return enc ? crypto_skcipher_encrypt(subreq) : | |
85 | crypto_skcipher_decrypt(subreq); | |
4beb1060 | 86 | } |
8c755ace | 87 | |
2621a869 EB |
88 | ret = skcipher_walk_virt(&walk, req, false); |
89 | while ((nbytes = walk.nbytes) != 0) { | |
90 | preempt_disable(); | |
91 | pagefault_disable(); | |
92 | enable_kernel_vsx(); | |
93 | aes_p8_cbc_encrypt(walk.src.virt.addr, | |
94 | walk.dst.virt.addr, | |
95 | round_down(nbytes, AES_BLOCK_SIZE), | |
96 | enc ? &ctx->enc_key : &ctx->dec_key, | |
97 | walk.iv, enc); | |
98 | disable_kernel_vsx(); | |
99 | pagefault_enable(); | |
100 | preempt_enable(); | |
101 | ||
102 | ret = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE); | |
103 | } | |
4beb1060 | 104 | return ret; |
8c755ace MC |
105 | } |
106 | ||
2621a869 | 107 | static int p8_aes_cbc_encrypt(struct skcipher_request *req) |
8c755ace | 108 | { |
2621a869 | 109 | return p8_aes_cbc_crypt(req, 1); |
8c755ace MC |
110 | } |
111 | ||
2621a869 EB |
112 | static int p8_aes_cbc_decrypt(struct skcipher_request *req) |
113 | { | |
114 | return p8_aes_cbc_crypt(req, 0); | |
115 | } | |
8c755ace | 116 | |
2621a869 EB |
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, | |
8c755ace | 133 | }; |