kernel: bump 4.14 to 4.14.114
[openwrt/openwrt.git] / target / linux / apm821xx / patches-4.14 / 020-0024-crypto-crypto4xx-add-aes-ccm-support.patch
1 From 65ea8b678fcf385ac18864743bae66c0643e6842 Mon Sep 17 00:00:00 2001
2 From: Christian Lamparter <chunkeey@gmail.com>
3 Date: Wed, 4 Oct 2017 01:00:16 +0200
4 Subject: [PATCH 24/25] crypto: crypto4xx - add aes-ccm support
5
6 This patch adds aes-ccm support.
7
8 Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
9 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
10 ---
11 drivers/crypto/amcc/crypto4xx_alg.c | 185 +++++++++++++++++++++++++++++++++++
12 drivers/crypto/amcc/crypto4xx_core.c | 23 +++++
13 drivers/crypto/amcc/crypto4xx_core.h | 8 ++
14 3 files changed, 216 insertions(+)
15
16 --- a/drivers/crypto/amcc/crypto4xx_alg.c
17 +++ b/drivers/crypto/amcc/crypto4xx_alg.c
18 @@ -232,6 +232,191 @@ int crypto4xx_rfc3686_decrypt(struct abl
19 ctx->sa_out, ctx->sa_len, 0);
20 }
21
22 +static inline bool crypto4xx_aead_need_fallback(struct aead_request *req,
23 + bool is_ccm, bool decrypt)
24 +{
25 + struct crypto_aead *aead = crypto_aead_reqtfm(req);
26 +
27 + /* authsize has to be a multiple of 4 */
28 + if (aead->authsize & 3)
29 + return true;
30 +
31 + /*
32 + * hardware does not handle cases where cryptlen
33 + * is less than a block
34 + */
35 + if (req->cryptlen < AES_BLOCK_SIZE)
36 + return true;
37 +
38 + /* assoc len needs to be a multiple of 4 */
39 + if (req->assoclen & 0x3)
40 + return true;
41 +
42 + /* CCM supports only counter field length of 2 and 4 bytes */
43 + if (is_ccm && !(req->iv[0] == 1 || req->iv[0] == 3))
44 + return true;
45 +
46 + /* CCM - fix CBC MAC mismatch in special case */
47 + if (is_ccm && decrypt && !req->assoclen)
48 + return true;
49 +
50 + return false;
51 +}
52 +
53 +static int crypto4xx_aead_fallback(struct aead_request *req,
54 + struct crypto4xx_ctx *ctx, bool do_decrypt)
55 +{
56 + char aead_req_data[sizeof(struct aead_request) +
57 + crypto_aead_reqsize(ctx->sw_cipher.aead)]
58 + __aligned(__alignof__(struct aead_request));
59 +
60 + struct aead_request *subreq = (void *) aead_req_data;
61 +
62 + memset(subreq, 0, sizeof(aead_req_data));
63 +
64 + aead_request_set_tfm(subreq, ctx->sw_cipher.aead);
65 + aead_request_set_callback(subreq, req->base.flags,
66 + req->base.complete, req->base.data);
67 + aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
68 + req->iv);
69 + aead_request_set_ad(subreq, req->assoclen);
70 + return do_decrypt ? crypto_aead_decrypt(subreq) :
71 + crypto_aead_encrypt(subreq);
72 +}
73 +
74 +static int crypto4xx_setup_fallback(struct crypto4xx_ctx *ctx,
75 + struct crypto_aead *cipher,
76 + const u8 *key,
77 + unsigned int keylen)
78 +{
79 + int rc;
80 +
81 + crypto_aead_clear_flags(ctx->sw_cipher.aead, CRYPTO_TFM_REQ_MASK);
82 + crypto_aead_set_flags(ctx->sw_cipher.aead,
83 + crypto_aead_get_flags(cipher) & CRYPTO_TFM_REQ_MASK);
84 + rc = crypto_aead_setkey(ctx->sw_cipher.aead, key, keylen);
85 + crypto_aead_clear_flags(cipher, CRYPTO_TFM_RES_MASK);
86 + crypto_aead_set_flags(cipher,
87 + crypto_aead_get_flags(ctx->sw_cipher.aead) &
88 + CRYPTO_TFM_RES_MASK);
89 +
90 + return rc;
91 +}
92 +
93 +/**
94 + * AES-CCM Functions
95 + */
96 +
97 +int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher, const u8 *key,
98 + unsigned int keylen)
99 +{
100 + struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
101 + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
102 + struct dynamic_sa_ctl *sa;
103 + int rc = 0;
104 +
105 + rc = crypto4xx_setup_fallback(ctx, cipher, key, keylen);
106 + if (rc)
107 + return rc;
108 +
109 + if (ctx->sa_in || ctx->sa_out)
110 + crypto4xx_free_sa(ctx);
111 +
112 + rc = crypto4xx_alloc_sa(ctx, SA_AES128_CCM_LEN + (keylen - 16) / 4);
113 + if (rc)
114 + return rc;
115 +
116 + /* Setup SA */
117 + sa = (struct dynamic_sa_ctl *) ctx->sa_in;
118 + sa->sa_contents.w = SA_AES_CCM_CONTENTS | (keylen << 2);
119 +
120 + set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
121 + SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
122 + SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
123 + SA_CIPHER_ALG_AES,
124 + SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
125 + SA_OPCODE_HASH_DECRYPT, DIR_INBOUND);
126 +
127 + set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
128 + CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
129 + SA_SEQ_MASK_OFF, SA_MC_ENABLE,
130 + SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
131 + SA_NOT_COPY_HDR);
132 +
133 + sa->sa_command_1.bf.key_len = keylen >> 3;
134 +
135 + crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa), key, keylen);
136 +
137 + memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
138 + sa = (struct dynamic_sa_ctl *) ctx->sa_out;
139 +
140 + set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
141 + SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
142 + SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
143 + SA_CIPHER_ALG_AES,
144 + SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
145 + SA_OPCODE_ENCRYPT_HASH, DIR_OUTBOUND);
146 +
147 + set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
148 + CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
149 + SA_SEQ_MASK_OFF, SA_MC_ENABLE,
150 + SA_COPY_PAD, SA_COPY_PAYLOAD,
151 + SA_NOT_COPY_HDR);
152 +
153 + sa->sa_command_1.bf.key_len = keylen >> 3;
154 + return 0;
155 +}
156 +
157 +static int crypto4xx_crypt_aes_ccm(struct aead_request *req, bool decrypt)
158 +{
159 + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
160 + struct crypto_aead *aead = crypto_aead_reqtfm(req);
161 + unsigned int len = req->cryptlen;
162 + __le32 iv[16];
163 + u32 tmp_sa[ctx->sa_len * 4];
164 + struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *)tmp_sa;
165 +
166 + if (crypto4xx_aead_need_fallback(req, true, decrypt))
167 + return crypto4xx_aead_fallback(req, ctx, decrypt);
168 +
169 + if (decrypt)
170 + len -= crypto_aead_authsize(aead);
171 +
172 + memcpy(tmp_sa, decrypt ? ctx->sa_in : ctx->sa_out, sizeof(tmp_sa));
173 + sa->sa_command_0.bf.digest_len = crypto_aead_authsize(aead) >> 2;
174 +
175 + if (req->iv[0] == 1) {
176 + /* CRYPTO_MODE_AES_ICM */
177 + sa->sa_command_1.bf.crypto_mode9_8 = 1;
178 + }
179 +
180 + iv[3] = cpu_to_le32(0);
181 + crypto4xx_memcpy_to_le32(iv, req->iv, 16 - (req->iv[0] + 1));
182 +
183 + return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
184 + len, iv, sizeof(iv),
185 + sa, ctx->sa_len, req->assoclen);
186 +}
187 +
188 +int crypto4xx_encrypt_aes_ccm(struct aead_request *req)
189 +{
190 + return crypto4xx_crypt_aes_ccm(req, false);
191 +}
192 +
193 +int crypto4xx_decrypt_aes_ccm(struct aead_request *req)
194 +{
195 + return crypto4xx_crypt_aes_ccm(req, true);
196 +}
197 +
198 +int crypto4xx_setauthsize_aead(struct crypto_aead *cipher,
199 + unsigned int authsize)
200 +{
201 + struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
202 + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
203 +
204 + return crypto_aead_setauthsize(ctx->sw_cipher.aead, authsize);
205 +}
206 +
207 /**
208 * HASH SHA1 Functions
209 */
210 --- a/drivers/crypto/amcc/crypto4xx_core.c
211 +++ b/drivers/crypto/amcc/crypto4xx_core.c
212 @@ -1219,6 +1219,29 @@ static struct crypto4xx_alg_common crypt
213 }
214 }
215 } },
216 +
217 + /* AEAD */
218 + { .type = CRYPTO_ALG_TYPE_AEAD, .u.aead = {
219 + .setkey = crypto4xx_setkey_aes_ccm,
220 + .setauthsize = crypto4xx_setauthsize_aead,
221 + .encrypt = crypto4xx_encrypt_aes_ccm,
222 + .decrypt = crypto4xx_decrypt_aes_ccm,
223 + .init = crypto4xx_aead_init,
224 + .exit = crypto4xx_aead_exit,
225 + .ivsize = AES_BLOCK_SIZE,
226 + .maxauthsize = 16,
227 + .base = {
228 + .cra_name = "ccm(aes)",
229 + .cra_driver_name = "ccm-aes-ppc4xx",
230 + .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
231 + .cra_flags = CRYPTO_ALG_ASYNC |
232 + CRYPTO_ALG_NEED_FALLBACK |
233 + CRYPTO_ALG_KERN_DRIVER_ONLY,
234 + .cra_blocksize = 1,
235 + .cra_ctxsize = sizeof(struct crypto4xx_ctx),
236 + .cra_module = THIS_MODULE,
237 + },
238 + } },
239 };
240
241 /**
242 --- a/drivers/crypto/amcc/crypto4xx_core.h
243 +++ b/drivers/crypto/amcc/crypto4xx_core.h
244 @@ -222,4 +222,12 @@ static inline void crypto4xx_memcpy_to_l
245 {
246 crypto4xx_memcpy_swab32((u32 *)dst, buf, len);
247 }
248 +
249 +int crypto4xx_setauthsize_aead(struct crypto_aead *ciper,
250 + unsigned int authsize);
251 +int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher,
252 + const u8 *key, unsigned int keylen);
253 +int crypto4xx_encrypt_aes_ccm(struct aead_request *req);
254 +int crypto4xx_decrypt_aes_ccm(struct aead_request *req);
255 +
256 #endif