Blame view
crypto/gcm.c
31 KB
d2912cb15
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
28db8e3e3
|
2 3 4 5 |
/* * GCM: Galois/Counter Mode. * * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi> |
28db8e3e3
|
6 |
*/ |
28db8e3e3
|
7 |
#include <crypto/gf128mul.h> |
dadbc53d0
|
8 |
#include <crypto/internal/aead.h> |
1472e5eba
|
9 |
#include <crypto/internal/skcipher.h> |
9382d97af
|
10 |
#include <crypto/internal/hash.h> |
17db85469
|
11 |
#include <crypto/null.h> |
42c271c6c
|
12 |
#include <crypto/scatterwalk.h> |
e0ab7e9c6
|
13 |
#include <crypto/gcm.h> |
9382d97af
|
14 |
#include <crypto/hash.h> |
28db8e3e3
|
15 16 17 18 19 |
#include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> |
28db8e3e3
|
20 |
struct gcm_instance_ctx { |
1472e5eba
|
21 |
struct crypto_skcipher_spawn ctr; |
9382d97af
|
22 |
struct crypto_ahash_spawn ghash; |
28db8e3e3
|
23 24 25 |
}; struct crypto_gcm_ctx { |
16f37ecdd
|
26 |
struct crypto_skcipher *ctr; |
9382d97af
|
27 |
struct crypto_ahash *ghash; |
28db8e3e3
|
28 |
}; |
dadbc53d0
|
29 30 31 32 |
struct crypto_rfc4106_ctx { struct crypto_aead *child; u8 nonce[4]; }; |
7b05a373a
|
33 34 35 36 37 |
struct crypto_rfc4106_req_ctx { struct scatterlist src[3]; struct scatterlist dst[3]; struct aead_request subreq; }; |
9489667d3
|
38 39 |
struct crypto_rfc4543_instance_ctx { struct crypto_aead_spawn aead; |
9489667d3
|
40 |
}; |
73c89c15b
|
41 42 |
struct crypto_rfc4543_ctx { struct crypto_aead *child; |
8d6053984
|
43 |
struct crypto_sync_skcipher *null; |
73c89c15b
|
44 45 46 47 |
u8 nonce[4]; }; struct crypto_rfc4543_req_ctx { |
73c89c15b
|
48 49 |
struct aead_request subreq; }; |
28db8e3e3
|
50 |
struct crypto_gcm_ghash_ctx { |
9382d97af
|
51 52 |
unsigned int cryptlen; struct scatterlist *src; |
adcbc688f
|
53 |
int (*complete)(struct aead_request *req, u32 flags); |
28db8e3e3
|
54 55 56 |
}; struct crypto_gcm_req_priv_ctx { |
adcbc688f
|
57 |
u8 iv[16]; |
28db8e3e3
|
58 |
u8 auth_tag[16]; |
6160b2899
|
59 |
u8 iauth_tag[16]; |
adcbc688f
|
60 61 62 |
struct scatterlist src[3]; struct scatterlist dst[3]; struct scatterlist sg; |
9382d97af
|
63 64 65 |
struct crypto_gcm_ghash_ctx ghash_ctx; union { struct ahash_request ahreq; |
16f37ecdd
|
66 |
struct skcipher_request skreq; |
9382d97af
|
67 |
} u; |
28db8e3e3
|
68 |
}; |
adcbc688f
|
69 70 71 72 73 74 |
static struct { u8 buf[16]; struct scatterlist sg; } *gcm_zeroes; static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc); |
9382d97af
|
75 |
|
2589469d7
|
76 77 78 79 80 81 82 |
static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_reqctx( struct aead_request *req) { unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req)); return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1); } |
28db8e3e3
|
83 84 85 86 |
static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead); |
9382d97af
|
87 |
struct crypto_ahash *ghash = ctx->ghash; |
16f37ecdd
|
88 |
struct crypto_skcipher *ctr = ctx->ctr; |
84c911523
|
89 90 |
struct { be128 hash; |
50d2e6dc1
|
91 |
u8 iv[16]; |
84c911523
|
92 |
|
76c673947
|
93 |
struct crypto_wait wait; |
84c911523
|
94 95 |
struct scatterlist sg[1]; |
16f37ecdd
|
96 |
struct skcipher_request req; |
84c911523
|
97 98 |
} *data; int err; |
28db8e3e3
|
99 |
|
16f37ecdd
|
100 101 102 103 |
crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK); crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); err = crypto_skcipher_setkey(ctr, key, keylen); |
28db8e3e3
|
104 |
if (err) |
84c911523
|
105 |
return err; |
28db8e3e3
|
106 |
|
16f37ecdd
|
107 |
data = kzalloc(sizeof(*data) + crypto_skcipher_reqsize(ctr), |
84c911523
|
108 109 110 |
GFP_KERNEL); if (!data) return -ENOMEM; |
76c673947
|
111 |
crypto_init_wait(&data->wait); |
84c911523
|
112 |
sg_init_one(data->sg, &data->hash, sizeof(data->hash)); |
16f37ecdd
|
113 114 115 |
skcipher_request_set_tfm(&data->req, ctr); skcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, |
76c673947
|
116 117 |
crypto_req_done, &data->wait); |
16f37ecdd
|
118 119 |
skcipher_request_set_crypt(&data->req, data->sg, data->sg, sizeof(data->hash), data->iv); |
76c673947
|
120 121 |
err = crypto_wait_req(crypto_skcipher_encrypt(&data->req), &data->wait); |
84c911523
|
122 |
|
28db8e3e3
|
123 124 |
if (err) goto out; |
9382d97af
|
125 126 127 128 |
crypto_ahash_clear_flags(ghash, CRYPTO_TFM_REQ_MASK); crypto_ahash_set_flags(ghash, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); err = crypto_ahash_setkey(ghash, (u8 *)&data->hash, sizeof(be128)); |
84c911523
|
129 |
out: |
adcbc688f
|
130 |
kzfree(data); |
28db8e3e3
|
131 132 |
return err; } |
dadbc53d0
|
133 134 135 |
static int crypto_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) { |
65526f638
|
136 |
return crypto_gcm_check_authsize(authsize); |
dadbc53d0
|
137 |
} |
adcbc688f
|
138 |
static void crypto_gcm_init_common(struct aead_request *req) |
28db8e3e3
|
139 |
{ |
2589469d7
|
140 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
84c911523
|
141 |
__be32 counter = cpu_to_be32(1); |
adcbc688f
|
142 |
struct scatterlist *sg; |
84c911523
|
143 144 |
memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag)); |
e0ab7e9c6
|
145 146 |
memcpy(pctx->iv, req->iv, GCM_AES_IV_SIZE); memcpy(pctx->iv + GCM_AES_IV_SIZE, &counter, 4); |
84c911523
|
147 |
|
adcbc688f
|
148 |
sg_init_table(pctx->src, 3); |
84c911523
|
149 |
sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag)); |
adcbc688f
|
150 151 |
sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen); if (sg != pctx->src + 1) |
c56f6d127
|
152 |
sg_chain(pctx->src, 2, sg); |
84c911523
|
153 |
|
84c911523
|
154 |
if (req->src != req->dst) { |
adcbc688f
|
155 |
sg_init_table(pctx->dst, 3); |
84c911523
|
156 |
sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag)); |
adcbc688f
|
157 158 |
sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen); if (sg != pctx->dst + 1) |
c56f6d127
|
159 |
sg_chain(pctx->dst, 2, sg); |
84c911523
|
160 |
} |
adcbc688f
|
161 162 163 164 165 166 167 168 |
} static void crypto_gcm_init_crypt(struct aead_request *req, unsigned int cryptlen) { struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead); struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
16f37ecdd
|
169 |
struct skcipher_request *skreq = &pctx->u.skreq; |
adcbc688f
|
170 171 172 |
struct scatterlist *dst; dst = req->src == req->dst ? pctx->src : pctx->dst; |
28db8e3e3
|
173 |
|
16f37ecdd
|
174 175 |
skcipher_request_set_tfm(skreq, ctx->ctr); skcipher_request_set_crypt(skreq, pctx->src, dst, |
84c911523
|
176 |
cryptlen + sizeof(pctx->auth_tag), |
adcbc688f
|
177 |
pctx->iv); |
9382d97af
|
178 179 180 181 182 183 184 185 186 |
} static inline unsigned int gcm_remain(unsigned int len) { len &= 0xfU; return len ? 16 - len : 0; } static void gcm_hash_len_done(struct crypto_async_request *areq, int err); |
28db8e3e3
|
187 |
|
9382d97af
|
188 |
static int gcm_hash_update(struct aead_request *req, |
3e3dc25fe
|
189 |
crypto_completion_t compl, |
9382d97af
|
190 |
struct scatterlist *src, |
adcbc688f
|
191 |
unsigned int len, u32 flags) |
9382d97af
|
192 |
{ |
adcbc688f
|
193 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
9382d97af
|
194 |
struct ahash_request *ahreq = &pctx->u.ahreq; |
28db8e3e3
|
195 |
|
adcbc688f
|
196 |
ahash_request_set_callback(ahreq, flags, compl, req); |
9382d97af
|
197 198 199 |
ahash_request_set_crypt(ahreq, src, NULL, len); return crypto_ahash_update(ahreq); |
28db8e3e3
|
200 |
} |
9382d97af
|
201 |
static int gcm_hash_remain(struct aead_request *req, |
9382d97af
|
202 |
unsigned int remain, |
adcbc688f
|
203 |
crypto_completion_t compl, u32 flags) |
28db8e3e3
|
204 |
{ |
adcbc688f
|
205 |
return gcm_hash_update(req, compl, &gcm_zeroes->sg, remain, flags); |
9382d97af
|
206 |
} |
adcbc688f
|
207 |
static int gcm_hash_len(struct aead_request *req, u32 flags) |
9382d97af
|
208 |
{ |
adcbc688f
|
209 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
9382d97af
|
210 211 |
struct ahash_request *ahreq = &pctx->u.ahreq; struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; |
18666550f
|
212 |
be128 lengths; |
9382d97af
|
213 214 215 216 |
lengths.a = cpu_to_be64(req->assoclen * 8); lengths.b = cpu_to_be64(gctx->cryptlen * 8); memcpy(pctx->iauth_tag, &lengths, 16); |
adcbc688f
|
217 218 219 220 |
sg_init_one(&pctx->sg, pctx->iauth_tag, 16); ahash_request_set_callback(ahreq, flags, gcm_hash_len_done, req); ahash_request_set_crypt(ahreq, &pctx->sg, pctx->iauth_tag, sizeof(lengths)); |
9382d97af
|
221 |
|
adcbc688f
|
222 |
return crypto_ahash_finup(ahreq); |
9382d97af
|
223 |
} |
adcbc688f
|
224 |
static int gcm_hash_len_continue(struct aead_request *req, u32 flags) |
9382d97af
|
225 |
{ |
2589469d7
|
226 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
9382d97af
|
227 |
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; |
adcbc688f
|
228 |
return gctx->complete(req, flags); |
9382d97af
|
229 |
} |
adcbc688f
|
230 |
static void gcm_hash_len_done(struct crypto_async_request *areq, int err) |
9382d97af
|
231 232 |
{ struct aead_request *req = areq->data; |
62c5593ae
|
233 |
|
adcbc688f
|
234 235 |
if (err) goto out; |
9382d97af
|
236 |
|
adcbc688f
|
237 238 239 |
err = gcm_hash_len_continue(req, 0); if (err == -EINPROGRESS) return; |
62c5593ae
|
240 |
|
adcbc688f
|
241 242 |
out: aead_request_complete(req, err); |
62c5593ae
|
243 |
} |
adcbc688f
|
244 |
static int gcm_hash_crypt_remain_continue(struct aead_request *req, u32 flags) |
62c5593ae
|
245 |
{ |
adcbc688f
|
246 247 |
return gcm_hash_len(req, flags) ?: gcm_hash_len_continue(req, flags); |
9382d97af
|
248 |
} |
62c5593ae
|
249 250 |
static void gcm_hash_crypt_remain_done(struct crypto_async_request *areq, int err) |
9382d97af
|
251 252 |
{ struct aead_request *req = areq->data; |
62c5593ae
|
253 |
|
adcbc688f
|
254 255 256 257 258 259 260 261 262 |
if (err) goto out; err = gcm_hash_crypt_remain_continue(req, 0); if (err == -EINPROGRESS) return; out: aead_request_complete(req, err); |
62c5593ae
|
263 |
} |
adcbc688f
|
264 |
static int gcm_hash_crypt_continue(struct aead_request *req, u32 flags) |
62c5593ae
|
265 |
{ |
9382d97af
|
266 267 268 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; unsigned int remain; |
adcbc688f
|
269 270 271 272 273 |
remain = gcm_remain(gctx->cryptlen); if (remain) return gcm_hash_remain(req, remain, gcm_hash_crypt_remain_done, flags) ?: gcm_hash_crypt_remain_continue(req, flags); |
9382d97af
|
274 |
|
adcbc688f
|
275 |
return gcm_hash_crypt_remain_continue(req, flags); |
9382d97af
|
276 |
} |
62c5593ae
|
277 |
static void gcm_hash_crypt_done(struct crypto_async_request *areq, int err) |
9382d97af
|
278 279 |
{ struct aead_request *req = areq->data; |
62c5593ae
|
280 |
|
adcbc688f
|
281 282 283 284 285 286 287 288 289 |
if (err) goto out; err = gcm_hash_crypt_continue(req, 0); if (err == -EINPROGRESS) return; out: aead_request_complete(req, err); |
62c5593ae
|
290 |
} |
adcbc688f
|
291 |
static int gcm_hash_assoc_remain_continue(struct aead_request *req, u32 flags) |
62c5593ae
|
292 |
{ |
9382d97af
|
293 294 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; |
9382d97af
|
295 |
|
adcbc688f
|
296 297 298 299 300 301 |
if (gctx->cryptlen) return gcm_hash_update(req, gcm_hash_crypt_done, gctx->src, gctx->cryptlen, flags) ?: gcm_hash_crypt_continue(req, flags); return gcm_hash_crypt_remain_continue(req, flags); |
9382d97af
|
302 |
} |
62c5593ae
|
303 304 |
static void gcm_hash_assoc_remain_done(struct crypto_async_request *areq, int err) |
9382d97af
|
305 306 |
{ struct aead_request *req = areq->data; |
62c5593ae
|
307 |
|
adcbc688f
|
308 309 310 311 312 313 314 315 316 |
if (err) goto out; err = gcm_hash_assoc_remain_continue(req, 0); if (err == -EINPROGRESS) return; out: aead_request_complete(req, err); |
62c5593ae
|
317 |
} |
adcbc688f
|
318 |
static int gcm_hash_assoc_continue(struct aead_request *req, u32 flags) |
62c5593ae
|
319 |
{ |
9382d97af
|
320 |
unsigned int remain; |
adcbc688f
|
321 322 323 324 325 |
remain = gcm_remain(req->assoclen); if (remain) return gcm_hash_remain(req, remain, gcm_hash_assoc_remain_done, flags) ?: gcm_hash_assoc_remain_continue(req, flags); |
9382d97af
|
326 |
|
adcbc688f
|
327 |
return gcm_hash_assoc_remain_continue(req, flags); |
9382d97af
|
328 |
} |
62c5593ae
|
329 |
static void gcm_hash_assoc_done(struct crypto_async_request *areq, int err) |
9382d97af
|
330 331 |
{ struct aead_request *req = areq->data; |
62c5593ae
|
332 |
|
adcbc688f
|
333 334 335 336 337 338 339 340 341 |
if (err) goto out; err = gcm_hash_assoc_continue(req, 0); if (err == -EINPROGRESS) return; out: aead_request_complete(req, err); |
62c5593ae
|
342 |
} |
adcbc688f
|
343 |
static int gcm_hash_init_continue(struct aead_request *req, u32 flags) |
62c5593ae
|
344 |
{ |
adcbc688f
|
345 346 347 348 |
if (req->assoclen) return gcm_hash_update(req, gcm_hash_assoc_done, req->src, req->assoclen, flags) ?: gcm_hash_assoc_continue(req, flags); |
9382d97af
|
349 |
|
adcbc688f
|
350 |
return gcm_hash_assoc_remain_continue(req, flags); |
62c5593ae
|
351 352 353 354 355 |
} static void gcm_hash_init_done(struct crypto_async_request *areq, int err) { struct aead_request *req = areq->data; |
adcbc688f
|
356 357 358 359 360 361 362 363 364 |
if (err) goto out; err = gcm_hash_init_continue(req, 0); if (err == -EINPROGRESS) return; out: aead_request_complete(req, err); |
9382d97af
|
365 |
} |
adcbc688f
|
366 |
static int gcm_hash(struct aead_request *req, u32 flags) |
9382d97af
|
367 |
{ |
adcbc688f
|
368 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
9382d97af
|
369 |
struct ahash_request *ahreq = &pctx->u.ahreq; |
adcbc688f
|
370 |
struct crypto_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); |
9382d97af
|
371 372 |
ahash_request_set_tfm(ahreq, ctx->ghash); |
adcbc688f
|
373 374 375 |
ahash_request_set_callback(ahreq, flags, gcm_hash_init_done, req); return crypto_ahash_init(ahreq) ?: gcm_hash_init_continue(req, flags); |
9382d97af
|
376 |
} |
adcbc688f
|
377 |
static int gcm_enc_copy_hash(struct aead_request *req, u32 flags) |
9382d97af
|
378 |
{ |
adcbc688f
|
379 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
9382d97af
|
380 381 |
struct crypto_aead *aead = crypto_aead_reqtfm(req); u8 *auth_tag = pctx->auth_tag; |
28db8e3e3
|
382 |
|
adcbc688f
|
383 384 385 |
crypto_xor(auth_tag, pctx->iauth_tag, 16); scatterwalk_map_and_copy(auth_tag, req->dst, req->assoclen + req->cryptlen, |
6160b2899
|
386 |
crypto_aead_authsize(aead), 1); |
adcbc688f
|
387 |
return 0; |
6160b2899
|
388 |
} |
adcbc688f
|
389 |
static int gcm_encrypt_continue(struct aead_request *req, u32 flags) |
6160b2899
|
390 |
{ |
9382d97af
|
391 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
adcbc688f
|
392 |
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; |
6160b2899
|
393 |
|
adcbc688f
|
394 395 396 |
gctx->src = sg_next(req->src == req->dst ? pctx->src : pctx->dst); gctx->cryptlen = req->cryptlen; gctx->complete = gcm_enc_copy_hash; |
6160b2899
|
397 |
|
adcbc688f
|
398 |
return gcm_hash(req, flags); |
28db8e3e3
|
399 |
} |
62c5593ae
|
400 |
static void gcm_encrypt_done(struct crypto_async_request *areq, int err) |
9382d97af
|
401 402 |
{ struct aead_request *req = areq->data; |
9382d97af
|
403 |
|
adcbc688f
|
404 405 406 407 408 409 |
if (err) goto out; err = gcm_encrypt_continue(req, 0); if (err == -EINPROGRESS) return; |
9382d97af
|
410 |
|
adcbc688f
|
411 |
out: |
62c5593ae
|
412 |
aead_request_complete(req, err); |
9382d97af
|
413 |
} |
28db8e3e3
|
414 415 |
static int crypto_gcm_encrypt(struct aead_request *req) { |
2589469d7
|
416 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
16f37ecdd
|
417 |
struct skcipher_request *skreq = &pctx->u.skreq; |
adcbc688f
|
418 |
u32 flags = aead_request_flags(req); |
9382d97af
|
419 |
|
adcbc688f
|
420 421 |
crypto_gcm_init_common(req); crypto_gcm_init_crypt(req, req->cryptlen); |
16f37ecdd
|
422 |
skcipher_request_set_callback(skreq, flags, gcm_encrypt_done, req); |
9382d97af
|
423 |
|
16f37ecdd
|
424 |
return crypto_skcipher_encrypt(skreq) ?: |
adcbc688f
|
425 |
gcm_encrypt_continue(req, flags); |
28db8e3e3
|
426 |
} |
adcbc688f
|
427 |
static int crypto_gcm_verify(struct aead_request *req) |
84c911523
|
428 |
{ |
adcbc688f
|
429 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
84c911523
|
430 |
struct crypto_aead *aead = crypto_aead_reqtfm(req); |
84c911523
|
431 432 433 434 |
u8 *auth_tag = pctx->auth_tag; u8 *iauth_tag = pctx->iauth_tag; unsigned int authsize = crypto_aead_authsize(aead); unsigned int cryptlen = req->cryptlen - authsize; |
9382d97af
|
435 |
crypto_xor(auth_tag, iauth_tag, 16); |
adcbc688f
|
436 437 |
scatterwalk_map_and_copy(iauth_tag, req->src, req->assoclen + cryptlen, authsize, 0); |
6bf37e5aa
|
438 |
return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0; |
84c911523
|
439 |
} |
9382d97af
|
440 |
static void gcm_decrypt_done(struct crypto_async_request *areq, int err) |
28db8e3e3
|
441 |
{ |
84c911523
|
442 443 444 |
struct aead_request *req = areq->data; if (!err) |
adcbc688f
|
445 |
err = crypto_gcm_verify(req); |
84c911523
|
446 447 |
aead_request_complete(req, err); |
28db8e3e3
|
448 |
} |
adcbc688f
|
449 |
static int gcm_dec_hash_continue(struct aead_request *req, u32 flags) |
9382d97af
|
450 |
{ |
9382d97af
|
451 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
16f37ecdd
|
452 |
struct skcipher_request *skreq = &pctx->u.skreq; |
9382d97af
|
453 |
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; |
adcbc688f
|
454 |
crypto_gcm_init_crypt(req, gctx->cryptlen); |
16f37ecdd
|
455 456 |
skcipher_request_set_callback(skreq, flags, gcm_decrypt_done, req); return crypto_skcipher_decrypt(skreq) ?: crypto_gcm_verify(req); |
9382d97af
|
457 |
} |
28db8e3e3
|
458 459 |
static int crypto_gcm_decrypt(struct aead_request *req) { |
6160b2899
|
460 |
struct crypto_aead *aead = crypto_aead_reqtfm(req); |
2589469d7
|
461 |
struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); |
9382d97af
|
462 |
struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; |
6160b2899
|
463 |
unsigned int authsize = crypto_aead_authsize(aead); |
9382d97af
|
464 |
unsigned int cryptlen = req->cryptlen; |
adcbc688f
|
465 |
u32 flags = aead_request_flags(req); |
28db8e3e3
|
466 |
|
6160b2899
|
467 |
cryptlen -= authsize; |
28db8e3e3
|
468 |
|
adcbc688f
|
469 |
crypto_gcm_init_common(req); |
28db8e3e3
|
470 |
|
adcbc688f
|
471 472 473 |
gctx->src = sg_next(pctx->src); gctx->cryptlen = cryptlen; gctx->complete = gcm_dec_hash_continue; |
28db8e3e3
|
474 |
|
adcbc688f
|
475 |
return gcm_hash(req, flags); |
28db8e3e3
|
476 |
} |
adcbc688f
|
477 |
static int crypto_gcm_init_tfm(struct crypto_aead *tfm) |
28db8e3e3
|
478 |
{ |
adcbc688f
|
479 480 481 |
struct aead_instance *inst = aead_alg_instance(tfm); struct gcm_instance_ctx *ictx = aead_instance_ctx(inst); struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm); |
16f37ecdd
|
482 |
struct crypto_skcipher *ctr; |
9382d97af
|
483 |
struct crypto_ahash *ghash; |
28db8e3e3
|
484 485 |
unsigned long align; int err; |
9382d97af
|
486 487 488 |
ghash = crypto_spawn_ahash(&ictx->ghash); if (IS_ERR(ghash)) return PTR_ERR(ghash); |
60425a8ba
|
489 |
ctr = crypto_spawn_skcipher(&ictx->ctr); |
28db8e3e3
|
490 491 |
err = PTR_ERR(ctr); if (IS_ERR(ctr)) |
9382d97af
|
492 |
goto err_free_hash; |
28db8e3e3
|
493 494 |
ctx->ctr = ctr; |
9382d97af
|
495 |
ctx->ghash = ghash; |
28db8e3e3
|
496 |
|
adcbc688f
|
497 |
align = crypto_aead_alignmask(tfm); |
28db8e3e3
|
498 |
align &= ~(crypto_tfm_ctx_alignment() - 1); |
adcbc688f
|
499 |
crypto_aead_set_reqsize(tfm, |
5d72336f1
|
500 |
align + offsetof(struct crypto_gcm_req_priv_ctx, u) + |
16f37ecdd
|
501 502 |
max(sizeof(struct skcipher_request) + crypto_skcipher_reqsize(ctr), |
9382d97af
|
503 |
sizeof(struct ahash_request) + |
5d72336f1
|
504 |
crypto_ahash_reqsize(ghash))); |
28db8e3e3
|
505 506 |
return 0; |
9382d97af
|
507 508 509 510 |
err_free_hash: crypto_free_ahash(ghash); return err; |
28db8e3e3
|
511 |
} |
adcbc688f
|
512 |
static void crypto_gcm_exit_tfm(struct crypto_aead *tfm) |
28db8e3e3
|
513 |
{ |
adcbc688f
|
514 |
struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm); |
28db8e3e3
|
515 |
|
9382d97af
|
516 |
crypto_free_ahash(ctx->ghash); |
16f37ecdd
|
517 |
crypto_free_skcipher(ctx->ctr); |
28db8e3e3
|
518 |
} |
7b05a373a
|
519 520 521 522 523 524 525 526 |
static void crypto_gcm_free(struct aead_instance *inst) { struct gcm_instance_ctx *ctx = aead_instance_ctx(inst); crypto_drop_skcipher(&ctx->ctr); crypto_drop_ahash(&ctx->ghash); kfree(inst); } |
adcbc688f
|
527 528 |
static int crypto_gcm_create_common(struct crypto_template *tmpl, struct rtattr **tb, |
adcbc688f
|
529 530 |
const char *ctr_name, const char *ghash_name) |
28db8e3e3
|
531 |
{ |
d00aa19b5
|
532 |
struct crypto_attr_type *algt; |
b9f76dddb
|
533 |
u32 mask; |
adcbc688f
|
534 |
struct aead_instance *inst; |
ab6ffd360
|
535 |
struct gcm_instance_ctx *ctx; |
16f37ecdd
|
536 |
struct skcipher_alg *ctr; |
adcbc688f
|
537 |
struct hash_alg_common *ghash; |
28db8e3e3
|
538 |
int err; |
28db8e3e3
|
539 |
|
d00aa19b5
|
540 |
algt = crypto_get_attr_type(tb); |
d00aa19b5
|
541 |
if (IS_ERR(algt)) |
adcbc688f
|
542 |
return PTR_ERR(algt); |
28db8e3e3
|
543 |
|
5e4b8c1fc
|
544 |
if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) |
adcbc688f
|
545 |
return -EINVAL; |
28db8e3e3
|
546 |
|
b9f76dddb
|
547 |
mask = crypto_requires_sync(algt->type, algt->mask); |
1472e5eba
|
548 549 |
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); if (!inst) |
ab6ffd360
|
550 |
return -ENOMEM; |
adcbc688f
|
551 |
ctx = aead_instance_ctx(inst); |
ab6ffd360
|
552 553 554 |
err = crypto_grab_ahash(&ctx->ghash, aead_crypto_instance(inst), ghash_name, 0, mask); |
9382d97af
|
555 556 |
if (err) goto err_free_inst; |
ab6ffd360
|
557 |
ghash = crypto_spawn_ahash_alg(&ctx->ghash); |
9382d97af
|
558 |
|
adcbc688f
|
559 |
err = -EINVAL; |
f699594d4
|
560 561 |
if (strcmp(ghash->base.cra_name, "ghash") != 0 || ghash->digestsize != 16) |
ab6ffd360
|
562 |
goto err_free_inst; |
adcbc688f
|
563 |
|
b9f76dddb
|
564 565 |
err = crypto_grab_skcipher(&ctx->ctr, aead_crypto_instance(inst), ctr_name, 0, mask); |
1472e5eba
|
566 |
if (err) |
ab6ffd360
|
567 |
goto err_free_inst; |
16f37ecdd
|
568 |
ctr = crypto_spawn_skcipher_alg(&ctx->ctr); |
28db8e3e3
|
569 |
|
f699594d4
|
570 |
/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */ |
9b40f79c0
|
571 |
err = -EINVAL; |
f699594d4
|
572 573 574 |
if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 || crypto_skcipher_alg_ivsize(ctr) != 16 || ctr->base.cra_blocksize != 1) |
ab6ffd360
|
575 |
goto err_free_inst; |
d00aa19b5
|
576 |
|
f699594d4
|
577 578 579 |
err = -ENAMETOOLONG; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "gcm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME) |
ab6ffd360
|
580 |
goto err_free_inst; |
28db8e3e3
|
581 |
|
adcbc688f
|
582 |
if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, |
16f37ecdd
|
583 |
"gcm_base(%s,%s)", ctr->base.cra_driver_name, |
ab6ffd360
|
584 |
ghash->base.cra_driver_name) >= |
d00aa19b5
|
585 |
CRYPTO_MAX_ALG_NAME) |
ab6ffd360
|
586 |
goto err_free_inst; |
28db8e3e3
|
587 |
|
16f37ecdd
|
588 589 |
inst->alg.base.cra_flags = (ghash->base.cra_flags | ctr->base.cra_flags) & CRYPTO_ALG_ASYNC; |
adcbc688f
|
590 |
inst->alg.base.cra_priority = (ghash->base.cra_priority + |
16f37ecdd
|
591 |
ctr->base.cra_priority) / 2; |
adcbc688f
|
592 593 |
inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = ghash->base.cra_alignmask | |
16f37ecdd
|
594 |
ctr->base.cra_alignmask; |
adcbc688f
|
595 |
inst->alg.base.cra_ctxsize = sizeof(struct crypto_gcm_ctx); |
e0ab7e9c6
|
596 |
inst->alg.ivsize = GCM_AES_IV_SIZE; |
16f37ecdd
|
597 |
inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr); |
adcbc688f
|
598 599 600 601 602 603 604 |
inst->alg.maxauthsize = 16; inst->alg.init = crypto_gcm_init_tfm; inst->alg.exit = crypto_gcm_exit_tfm; inst->alg.setkey = crypto_gcm_setkey; inst->alg.setauthsize = crypto_gcm_setauthsize; inst->alg.encrypt = crypto_gcm_encrypt; inst->alg.decrypt = crypto_gcm_decrypt; |
7b05a373a
|
605 |
inst->free = crypto_gcm_free; |
adcbc688f
|
606 |
err = aead_register_instance(tmpl, inst); |
ab6ffd360
|
607 |
if (err) { |
28db8e3e3
|
608 |
err_free_inst: |
ab6ffd360
|
609 610 611 |
crypto_gcm_free(inst); } return err; |
28db8e3e3
|
612 |
} |
adcbc688f
|
613 |
static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb) |
d00aa19b5
|
614 |
{ |
d00aa19b5
|
615 616 |
const char *cipher_name; char ctr_name[CRYPTO_MAX_ALG_NAME]; |
d00aa19b5
|
617 618 |
cipher_name = crypto_attr_alg_name(tb[1]); |
d00aa19b5
|
619 |
if (IS_ERR(cipher_name)) |
adcbc688f
|
620 |
return PTR_ERR(cipher_name); |
d00aa19b5
|
621 622 623 |
if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >= CRYPTO_MAX_ALG_NAME) |
adcbc688f
|
624 |
return -ENAMETOOLONG; |
d00aa19b5
|
625 |
|
f699594d4
|
626 |
return crypto_gcm_create_common(tmpl, tb, ctr_name, "ghash"); |
d00aa19b5
|
627 |
} |
adcbc688f
|
628 629 |
static int crypto_gcm_base_create(struct crypto_template *tmpl, struct rtattr **tb) |
d00aa19b5
|
630 |
{ |
d00aa19b5
|
631 |
const char *ctr_name; |
9382d97af
|
632 |
const char *ghash_name; |
d00aa19b5
|
633 634 |
ctr_name = crypto_attr_alg_name(tb[1]); |
d00aa19b5
|
635 |
if (IS_ERR(ctr_name)) |
adcbc688f
|
636 |
return PTR_ERR(ctr_name); |
d00aa19b5
|
637 |
|
9382d97af
|
638 |
ghash_name = crypto_attr_alg_name(tb[2]); |
9382d97af
|
639 |
if (IS_ERR(ghash_name)) |
adcbc688f
|
640 |
return PTR_ERR(ghash_name); |
9382d97af
|
641 |
|
f699594d4
|
642 |
return crypto_gcm_create_common(tmpl, tb, ctr_name, ghash_name); |
d00aa19b5
|
643 |
} |
dadbc53d0
|
644 645 646 647 648 |
static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key, unsigned int keylen) { struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent); struct crypto_aead *child = ctx->child; |
dadbc53d0
|
649 650 651 652 653 654 655 656 657 658 |
if (keylen < 4) return -EINVAL; keylen -= 4; memcpy(ctx->nonce, key + keylen, 4); crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_aead_set_flags(child, crypto_aead_get_flags(parent) & CRYPTO_TFM_REQ_MASK); |
af5034e8e
|
659 |
return crypto_aead_setkey(child, key, keylen); |
dadbc53d0
|
660 661 662 663 664 665 |
} static int crypto_rfc4106_setauthsize(struct crypto_aead *parent, unsigned int authsize) { struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent); |
65526f638
|
666 |
int err; |
dadbc53d0
|
667 |
|
65526f638
|
668 669 670 |
err = crypto_rfc4106_check_authsize(authsize); if (err) return err; |
dadbc53d0
|
671 672 673 674 675 676 |
return crypto_aead_setauthsize(ctx->child, authsize); } static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req) { |
7b05a373a
|
677 |
struct crypto_rfc4106_req_ctx *rctx = aead_request_ctx(req); |
dadbc53d0
|
678 679 |
struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead); |
7b05a373a
|
680 |
struct aead_request *subreq = &rctx->subreq; |
dadbc53d0
|
681 |
struct crypto_aead *child = ctx->child; |
7b05a373a
|
682 |
struct scatterlist *sg; |
dadbc53d0
|
683 684 |
u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child), crypto_aead_alignmask(child) + 1); |
e0ab7e9c6
|
685 |
scatterwalk_map_and_copy(iv + GCM_AES_IV_SIZE, req->src, 0, req->assoclen - 8, 0); |
7b05a373a
|
686 |
|
dadbc53d0
|
687 688 |
memcpy(iv, ctx->nonce, 4); memcpy(iv + 4, req->iv, 8); |
7b05a373a
|
689 |
sg_init_table(rctx->src, 3); |
e0ab7e9c6
|
690 |
sg_set_buf(rctx->src, iv + GCM_AES_IV_SIZE, req->assoclen - 8); |
7b05a373a
|
691 692 693 694 695 696 |
sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen); if (sg != rctx->src + 1) sg_chain(rctx->src, 2, sg); if (req->src != req->dst) { sg_init_table(rctx->dst, 3); |
e0ab7e9c6
|
697 |
sg_set_buf(rctx->dst, iv + GCM_AES_IV_SIZE, req->assoclen - 8); |
7b05a373a
|
698 699 700 701 |
sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen); if (sg != rctx->dst + 1) sg_chain(rctx->dst, 2, sg); } |
dadbc53d0
|
702 703 704 |
aead_request_set_tfm(subreq, child); aead_request_set_callback(subreq, req->base.flags, req->base.complete, req->base.data); |
7b05a373a
|
705 706 707 708 |
aead_request_set_crypt(subreq, rctx->src, req->src == req->dst ? rctx->src : rctx->dst, req->cryptlen, iv); aead_request_set_ad(subreq, req->assoclen - 8); |
dadbc53d0
|
709 710 711 712 713 714 |
return subreq; } static int crypto_rfc4106_encrypt(struct aead_request *req) { |
65526f638
|
715 716 717 718 719 |
int err; err = crypto_ipsec_check_assoclen(req->assoclen); if (err) return err; |
7b05a373a
|
720 |
|
dadbc53d0
|
721 722 723 724 725 726 727 |
req = crypto_rfc4106_crypt(req); return crypto_aead_encrypt(req); } static int crypto_rfc4106_decrypt(struct aead_request *req) { |
65526f638
|
728 729 730 731 732 |
int err; err = crypto_ipsec_check_assoclen(req->assoclen); if (err) return err; |
7b05a373a
|
733 |
|
dadbc53d0
|
734 735 736 737 |
req = crypto_rfc4106_crypt(req); return crypto_aead_decrypt(req); } |
adcbc688f
|
738 |
static int crypto_rfc4106_init_tfm(struct crypto_aead *tfm) |
dadbc53d0
|
739 |
{ |
adcbc688f
|
740 741 742 |
struct aead_instance *inst = aead_alg_instance(tfm); struct crypto_aead_spawn *spawn = aead_instance_ctx(inst); struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm); |
dadbc53d0
|
743 744 745 746 747 748 749 750 751 752 753 |
struct crypto_aead *aead; unsigned long align; aead = crypto_spawn_aead(spawn); if (IS_ERR(aead)) return PTR_ERR(aead); ctx->child = aead; align = crypto_aead_alignmask(aead); align &= ~(crypto_tfm_ctx_alignment() - 1); |
adcbc688f
|
754 755 |
crypto_aead_set_reqsize( tfm, |
7b05a373a
|
756 |
sizeof(struct crypto_rfc4106_req_ctx) + |
5d72336f1
|
757 |
ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) + |
7b05a373a
|
758 |
align + 24); |
dadbc53d0
|
759 760 761 |
return 0; } |
adcbc688f
|
762 |
static void crypto_rfc4106_exit_tfm(struct crypto_aead *tfm) |
dadbc53d0
|
763 |
{ |
adcbc688f
|
764 |
struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm); |
dadbc53d0
|
765 766 767 |
crypto_free_aead(ctx->child); } |
7b05a373a
|
768 769 770 771 772 |
static void crypto_rfc4106_free(struct aead_instance *inst) { crypto_drop_aead(aead_instance_ctx(inst)); kfree(inst); } |
adcbc688f
|
773 774 |
static int crypto_rfc4106_create(struct crypto_template *tmpl, struct rtattr **tb) |
dadbc53d0
|
775 776 |
{ struct crypto_attr_type *algt; |
cd900f0ca
|
777 |
u32 mask; |
adcbc688f
|
778 |
struct aead_instance *inst; |
dadbc53d0
|
779 |
struct crypto_aead_spawn *spawn; |
adcbc688f
|
780 |
struct aead_alg *alg; |
dadbc53d0
|
781 782 783 784 |
const char *ccm_name; int err; algt = crypto_get_attr_type(tb); |
dadbc53d0
|
785 |
if (IS_ERR(algt)) |
adcbc688f
|
786 |
return PTR_ERR(algt); |
dadbc53d0
|
787 |
|
5e4b8c1fc
|
788 |
if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) |
adcbc688f
|
789 |
return -EINVAL; |
dadbc53d0
|
790 |
|
cd900f0ca
|
791 |
mask = crypto_requires_sync(algt->type, algt->mask); |
dadbc53d0
|
792 |
ccm_name = crypto_attr_alg_name(tb[1]); |
dadbc53d0
|
793 |
if (IS_ERR(ccm_name)) |
adcbc688f
|
794 |
return PTR_ERR(ccm_name); |
dadbc53d0
|
795 796 797 |
inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) |
adcbc688f
|
798 |
return -ENOMEM; |
dadbc53d0
|
799 |
|
adcbc688f
|
800 |
spawn = aead_instance_ctx(inst); |
cd900f0ca
|
801 802 |
err = crypto_grab_aead(spawn, aead_crypto_instance(inst), ccm_name, 0, mask); |
dadbc53d0
|
803 804 |
if (err) goto out_free_inst; |
adcbc688f
|
805 |
alg = crypto_spawn_aead_alg(spawn); |
dadbc53d0
|
806 807 |
err = -EINVAL; |
adcbc688f
|
808 |
/* Underlying IV size must be 12. */ |
e0ab7e9c6
|
809 |
if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE) |
dadbc53d0
|
810 811 812 |
goto out_drop_alg; /* Not a stream cipher? */ |
adcbc688f
|
813 |
if (alg->base.cra_blocksize != 1) |
dadbc53d0
|
814 815 816 |
goto out_drop_alg; err = -ENAMETOOLONG; |
adcbc688f
|
817 818 819 820 821 |
if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "rfc4106(%s)", alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME || snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "rfc4106(%s)", alg->base.cra_driver_name) >= |
dadbc53d0
|
822 823 |
CRYPTO_MAX_ALG_NAME) goto out_drop_alg; |
7b05a373a
|
824 |
inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; |
adcbc688f
|
825 826 827 |
inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = alg->base.cra_alignmask; |
dadbc53d0
|
828 |
|
adcbc688f
|
829 |
inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx); |
dadbc53d0
|
830 |
|
e0ab7e9c6
|
831 |
inst->alg.ivsize = GCM_RFC4106_IV_SIZE; |
16f37ecdd
|
832 |
inst->alg.chunksize = crypto_aead_alg_chunksize(alg); |
adcbc688f
|
833 |
inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg); |
dadbc53d0
|
834 |
|
adcbc688f
|
835 836 |
inst->alg.init = crypto_rfc4106_init_tfm; inst->alg.exit = crypto_rfc4106_exit_tfm; |
dadbc53d0
|
837 |
|
adcbc688f
|
838 839 840 841 |
inst->alg.setkey = crypto_rfc4106_setkey; inst->alg.setauthsize = crypto_rfc4106_setauthsize; inst->alg.encrypt = crypto_rfc4106_encrypt; inst->alg.decrypt = crypto_rfc4106_decrypt; |
dadbc53d0
|
842 |
|
7b05a373a
|
843 |
inst->free = crypto_rfc4106_free; |
adcbc688f
|
844 845 846 |
err = aead_register_instance(tmpl, inst); if (err) goto out_drop_alg; |
dadbc53d0
|
847 848 |
out: |
adcbc688f
|
849 |
return err; |
dadbc53d0
|
850 851 852 853 854 |
out_drop_alg: crypto_drop_aead(spawn); out_free_inst: kfree(inst); |
dadbc53d0
|
855 856 |
goto out; } |
73c89c15b
|
857 858 859 860 861 |
static int crypto_rfc4543_setkey(struct crypto_aead *parent, const u8 *key, unsigned int keylen) { struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent); struct crypto_aead *child = ctx->child; |
73c89c15b
|
862 863 864 865 866 867 868 869 870 871 |
if (keylen < 4) return -EINVAL; keylen -= 4; memcpy(ctx->nonce, key + keylen, 4); crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK); crypto_aead_set_flags(child, crypto_aead_get_flags(parent) & CRYPTO_TFM_REQ_MASK); |
af5034e8e
|
872 |
return crypto_aead_setkey(child, key, keylen); |
73c89c15b
|
873 874 875 876 877 878 879 880 881 882 883 884 |
} static int crypto_rfc4543_setauthsize(struct crypto_aead *parent, unsigned int authsize) { struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent); if (authsize != 16) return -EINVAL; return crypto_aead_setauthsize(ctx->child, authsize); } |
adcbc688f
|
885 |
static int crypto_rfc4543_crypt(struct aead_request *req, bool enc) |
73c89c15b
|
886 887 888 |
{ struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead); |
adcbc688f
|
889 |
struct crypto_rfc4543_req_ctx *rctx = aead_request_ctx(req); |
73c89c15b
|
890 |
struct aead_request *subreq = &rctx->subreq; |
73c89c15b
|
891 |
unsigned int authsize = crypto_aead_authsize(aead); |
73c89c15b
|
892 893 |
u8 *iv = PTR_ALIGN((u8 *)(rctx + 1) + crypto_aead_reqsize(ctx->child), crypto_aead_alignmask(ctx->child) + 1); |
adcbc688f
|
894 895 896 897 898 899 900 |
int err; if (req->src != req->dst) { err = crypto_rfc4543_copy_src_to_dst(req, enc); if (err) return err; } |
73c89c15b
|
901 902 903 |
memcpy(iv, ctx->nonce, 4); memcpy(iv + 4, req->iv, 8); |
73c89c15b
|
904 |
aead_request_set_tfm(subreq, ctx->child); |
adcbc688f
|
905 906 907 908 909 910 911 912 |
aead_request_set_callback(subreq, req->base.flags, req->base.complete, req->base.data); aead_request_set_crypt(subreq, req->src, req->dst, enc ? 0 : authsize, iv); aead_request_set_ad(subreq, req->assoclen + req->cryptlen - subreq->cryptlen); return enc ? crypto_aead_encrypt(subreq) : crypto_aead_decrypt(subreq); |
73c89c15b
|
913 |
} |
9489667d3
|
914 915 916 917 918 |
static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc) { struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead); unsigned int authsize = crypto_aead_authsize(aead); |
adcbc688f
|
919 920 |
unsigned int nbytes = req->assoclen + req->cryptlen - (enc ? 0 : authsize); |
8d6053984
|
921 |
SYNC_SKCIPHER_REQUEST_ON_STACK(nreq, ctx->null); |
16f37ecdd
|
922 |
|
8d6053984
|
923 |
skcipher_request_set_sync_tfm(nreq, ctx->null); |
16f37ecdd
|
924 925 |
skcipher_request_set_callback(nreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(nreq, req->src, req->dst, nbytes, NULL); |
9489667d3
|
926 |
|
16f37ecdd
|
927 |
return crypto_skcipher_encrypt(nreq); |
9489667d3
|
928 |
} |
73c89c15b
|
929 930 |
static int crypto_rfc4543_encrypt(struct aead_request *req) { |
74bf81d09
|
931 932 |
return crypto_ipsec_check_assoclen(req->assoclen) ?: crypto_rfc4543_crypt(req, true); |
73c89c15b
|
933 934 935 936 |
} static int crypto_rfc4543_decrypt(struct aead_request *req) { |
74bf81d09
|
937 938 |
return crypto_ipsec_check_assoclen(req->assoclen) ?: crypto_rfc4543_crypt(req, false); |
73c89c15b
|
939 |
} |
adcbc688f
|
940 |
static int crypto_rfc4543_init_tfm(struct crypto_aead *tfm) |
73c89c15b
|
941 |
{ |
adcbc688f
|
942 943 |
struct aead_instance *inst = aead_alg_instance(tfm); struct crypto_rfc4543_instance_ctx *ictx = aead_instance_ctx(inst); |
9489667d3
|
944 |
struct crypto_aead_spawn *spawn = &ictx->aead; |
adcbc688f
|
945 |
struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm); |
73c89c15b
|
946 |
struct crypto_aead *aead; |
8d6053984
|
947 |
struct crypto_sync_skcipher *null; |
73c89c15b
|
948 |
unsigned long align; |
9489667d3
|
949 |
int err = 0; |
73c89c15b
|
950 951 952 953 |
aead = crypto_spawn_aead(spawn); if (IS_ERR(aead)) return PTR_ERR(aead); |
3a2d4fb51
|
954 |
null = crypto_get_default_null_skcipher(); |
9489667d3
|
955 956 957 |
err = PTR_ERR(null); if (IS_ERR(null)) goto err_free_aead; |
73c89c15b
|
958 |
ctx->child = aead; |
9489667d3
|
959 |
ctx->null = null; |
73c89c15b
|
960 961 962 |
align = crypto_aead_alignmask(aead); align &= ~(crypto_tfm_ctx_alignment() - 1); |
adcbc688f
|
963 964 |
crypto_aead_set_reqsize( tfm, |
5d72336f1
|
965 966 |
sizeof(struct crypto_rfc4543_req_ctx) + ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) + |
e0ab7e9c6
|
967 |
align + GCM_AES_IV_SIZE); |
73c89c15b
|
968 969 |
return 0; |
9489667d3
|
970 971 972 973 |
err_free_aead: crypto_free_aead(aead); return err; |
73c89c15b
|
974 |
} |
adcbc688f
|
975 |
static void crypto_rfc4543_exit_tfm(struct crypto_aead *tfm) |
73c89c15b
|
976 |
{ |
adcbc688f
|
977 |
struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm); |
73c89c15b
|
978 979 |
crypto_free_aead(ctx->child); |
3a2d4fb51
|
980 |
crypto_put_default_null_skcipher(); |
73c89c15b
|
981 |
} |
7b05a373a
|
982 983 984 985 986 987 988 989 |
static void crypto_rfc4543_free(struct aead_instance *inst) { struct crypto_rfc4543_instance_ctx *ctx = aead_instance_ctx(inst); crypto_drop_aead(&ctx->aead); kfree(inst); } |
adcbc688f
|
990 991 |
static int crypto_rfc4543_create(struct crypto_template *tmpl, struct rtattr **tb) |
73c89c15b
|
992 993 |
{ struct crypto_attr_type *algt; |
cd900f0ca
|
994 |
u32 mask; |
adcbc688f
|
995 |
struct aead_instance *inst; |
73c89c15b
|
996 |
struct crypto_aead_spawn *spawn; |
adcbc688f
|
997 |
struct aead_alg *alg; |
9489667d3
|
998 |
struct crypto_rfc4543_instance_ctx *ctx; |
73c89c15b
|
999 1000 1001 1002 |
const char *ccm_name; int err; algt = crypto_get_attr_type(tb); |
73c89c15b
|
1003 |
if (IS_ERR(algt)) |
adcbc688f
|
1004 |
return PTR_ERR(algt); |
73c89c15b
|
1005 |
|
5e4b8c1fc
|
1006 |
if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) |
adcbc688f
|
1007 |
return -EINVAL; |
73c89c15b
|
1008 |
|
cd900f0ca
|
1009 |
mask = crypto_requires_sync(algt->type, algt->mask); |
73c89c15b
|
1010 |
ccm_name = crypto_attr_alg_name(tb[1]); |
73c89c15b
|
1011 |
if (IS_ERR(ccm_name)) |
adcbc688f
|
1012 |
return PTR_ERR(ccm_name); |
73c89c15b
|
1013 |
|
9489667d3
|
1014 |
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); |
73c89c15b
|
1015 |
if (!inst) |
adcbc688f
|
1016 |
return -ENOMEM; |
73c89c15b
|
1017 |
|
adcbc688f
|
1018 |
ctx = aead_instance_ctx(inst); |
9489667d3
|
1019 |
spawn = &ctx->aead; |
cd900f0ca
|
1020 1021 |
err = crypto_grab_aead(spawn, aead_crypto_instance(inst), ccm_name, 0, mask); |
73c89c15b
|
1022 1023 |
if (err) goto out_free_inst; |
adcbc688f
|
1024 |
alg = crypto_spawn_aead_alg(spawn); |
73c89c15b
|
1025 1026 |
err = -EINVAL; |
adcbc688f
|
1027 |
/* Underlying IV size must be 12. */ |
e0ab7e9c6
|
1028 |
if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE) |
17db85469
|
1029 |
goto out_drop_alg; |
73c89c15b
|
1030 1031 |
/* Not a stream cipher? */ |
adcbc688f
|
1032 |
if (alg->base.cra_blocksize != 1) |
17db85469
|
1033 |
goto out_drop_alg; |
73c89c15b
|
1034 1035 |
err = -ENAMETOOLONG; |
adcbc688f
|
1036 1037 1038 1039 1040 |
if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, "rfc4543(%s)", alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME || snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "rfc4543(%s)", alg->base.cra_driver_name) >= |
73c89c15b
|
1041 |
CRYPTO_MAX_ALG_NAME) |
17db85469
|
1042 |
goto out_drop_alg; |
73c89c15b
|
1043 |
|
adcbc688f
|
1044 1045 1046 1047 |
inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.base.cra_priority = alg->base.cra_priority; inst->alg.base.cra_blocksize = 1; inst->alg.base.cra_alignmask = alg->base.cra_alignmask; |
73c89c15b
|
1048 |
|
adcbc688f
|
1049 |
inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4543_ctx); |
73c89c15b
|
1050 |
|
e0ab7e9c6
|
1051 |
inst->alg.ivsize = GCM_RFC4543_IV_SIZE; |
16f37ecdd
|
1052 |
inst->alg.chunksize = crypto_aead_alg_chunksize(alg); |
adcbc688f
|
1053 |
inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg); |
73c89c15b
|
1054 |
|
adcbc688f
|
1055 1056 |
inst->alg.init = crypto_rfc4543_init_tfm; inst->alg.exit = crypto_rfc4543_exit_tfm; |
73c89c15b
|
1057 |
|
adcbc688f
|
1058 1059 1060 1061 |
inst->alg.setkey = crypto_rfc4543_setkey; inst->alg.setauthsize = crypto_rfc4543_setauthsize; inst->alg.encrypt = crypto_rfc4543_encrypt; inst->alg.decrypt = crypto_rfc4543_decrypt; |
73c89c15b
|
1062 |
|
7b05a373a
|
1063 |
inst->free = crypto_rfc4543_free, |
adcbc688f
|
1064 1065 1066 |
err = aead_register_instance(tmpl, inst); if (err) goto out_drop_alg; |
73c89c15b
|
1067 1068 |
out: |
adcbc688f
|
1069 |
return err; |
73c89c15b
|
1070 1071 1072 1073 1074 |
out_drop_alg: crypto_drop_aead(spawn); out_free_inst: kfree(inst); |
73c89c15b
|
1075 1076 |
goto out; } |
56a00d9da
|
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 |
static struct crypto_template crypto_gcm_tmpls[] = { { .name = "gcm_base", .create = crypto_gcm_base_create, .module = THIS_MODULE, }, { .name = "gcm", .create = crypto_gcm_create, .module = THIS_MODULE, }, { .name = "rfc4106", .create = crypto_rfc4106_create, .module = THIS_MODULE, }, { .name = "rfc4543", .create = crypto_rfc4543_create, .module = THIS_MODULE, }, |
73c89c15b
|
1095 |
}; |
28db8e3e3
|
1096 1097 |
static int __init crypto_gcm_module_init(void) { |
d00aa19b5
|
1098 |
int err; |
adcbc688f
|
1099 |
gcm_zeroes = kzalloc(sizeof(*gcm_zeroes), GFP_KERNEL); |
9382d97af
|
1100 1101 |
if (!gcm_zeroes) return -ENOMEM; |
adcbc688f
|
1102 |
sg_init_one(&gcm_zeroes->sg, gcm_zeroes->buf, sizeof(gcm_zeroes->buf)); |
56a00d9da
|
1103 1104 |
err = crypto_register_templates(crypto_gcm_tmpls, ARRAY_SIZE(crypto_gcm_tmpls)); |
d00aa19b5
|
1105 |
if (err) |
56a00d9da
|
1106 |
kfree(gcm_zeroes); |
d00aa19b5
|
1107 |
|
9382d97af
|
1108 |
return err; |
28db8e3e3
|
1109 1110 1111 1112 |
} static void __exit crypto_gcm_module_exit(void) { |
9382d97af
|
1113 |
kfree(gcm_zeroes); |
56a00d9da
|
1114 1115 |
crypto_unregister_templates(crypto_gcm_tmpls, ARRAY_SIZE(crypto_gcm_tmpls)); |
28db8e3e3
|
1116 |
} |
c4741b230
|
1117 |
subsys_initcall(crypto_gcm_module_init); |
28db8e3e3
|
1118 1119 1120 1121 1122 |
module_exit(crypto_gcm_module_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Galois/Counter Mode"); MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>"); |
5d26a105b
|
1123 1124 1125 |
MODULE_ALIAS_CRYPTO("gcm_base"); MODULE_ALIAS_CRYPTO("rfc4106"); MODULE_ALIAS_CRYPTO("rfc4543"); |
4943ba16b
|
1126 |
MODULE_ALIAS_CRYPTO("gcm"); |