kernel: bump 4.14 to 4.14.114
[oweals/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