diff options
-rw-r--r-- | crypto/Kconfig | 28 | ||||
-rw-r--r-- | crypto/Makefile | 1 | ||||
-rw-r--r-- | crypto/essiv.c | 663 |
3 files changed, 692 insertions, 0 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index e801450bcb1c..1e8390d32b6d 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
@@ -568,6 +568,34 @@ config CRYPTO_ADIANTUM | |||
568 | 568 | ||
569 | If unsure, say N. | 569 | If unsure, say N. |
570 | 570 | ||
571 | config CRYPTO_ESSIV | ||
572 | tristate "ESSIV support for block encryption" | ||
573 | select CRYPTO_AUTHENC | ||
574 | help | ||
575 | Encrypted salt-sector initialization vector (ESSIV) is an IV | ||
576 | generation method that is used in some cases by fscrypt and/or | ||
577 | dm-crypt. It uses the hash of the block encryption key as the | ||
578 | symmetric key for a block encryption pass applied to the input | ||
579 | IV, making low entropy IV sources more suitable for block | ||
580 | encryption. | ||
581 | |||
582 | This driver implements a crypto API template that can be | ||
583 | instantiated either as a skcipher or as a aead (depending on the | ||
584 | type of the first template argument), and which defers encryption | ||
585 | and decryption requests to the encapsulated cipher after applying | ||
586 | ESSIV to the input IV. Note that in the aead case, it is assumed | ||
587 | that the keys are presented in the same format used by the authenc | ||
588 | template, and that the IV appears at the end of the authenticated | ||
589 | associated data (AAD) region (which is how dm-crypt uses it.) | ||
590 | |||
591 | Note that the use of ESSIV is not recommended for new deployments, | ||
592 | and so this only needs to be enabled when interoperability with | ||
593 | existing encrypted volumes of filesystems is required, or when | ||
594 | building for a particular system that requires it (e.g., when | ||
595 | the SoC in question has accelerated CBC but not XTS, making CBC | ||
596 | combined with ESSIV the only feasible mode for h/w accelerated | ||
597 | block encryption) | ||
598 | |||
571 | comment "Hash modes" | 599 | comment "Hash modes" |
572 | 600 | ||
573 | config CRYPTO_CMAC | 601 | config CRYPTO_CMAC |
diff --git a/crypto/Makefile b/crypto/Makefile index 9479e1a45d8c..157cb0a324df 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -147,6 +147,7 @@ obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o | |||
147 | obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o | 147 | obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o |
148 | obj-$(CONFIG_CRYPTO_OFB) += ofb.o | 148 | obj-$(CONFIG_CRYPTO_OFB) += ofb.o |
149 | obj-$(CONFIG_CRYPTO_ECC) += ecc.o | 149 | obj-$(CONFIG_CRYPTO_ECC) += ecc.o |
150 | obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o | ||
150 | 151 | ||
151 | ecdh_generic-y += ecdh.o | 152 | ecdh_generic-y += ecdh.o |
152 | ecdh_generic-y += ecdh_helper.o | 153 | ecdh_generic-y += ecdh_helper.o |
diff --git a/crypto/essiv.c b/crypto/essiv.c new file mode 100644 index 000000000000..a8befc8fb06e --- /dev/null +++ b/crypto/essiv.c | |||
@@ -0,0 +1,663 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * ESSIV skcipher and aead template for block encryption | ||
4 | * | ||
5 | * This template encapsulates the ESSIV IV generation algorithm used by | ||
6 | * dm-crypt and fscrypt, which converts the initial vector for the skcipher | ||
7 | * used for block encryption, by encrypting it using the hash of the | ||
8 | * skcipher key as encryption key. Usually, the input IV is a 64-bit sector | ||
9 | * number in LE representation zero-padded to the size of the IV, but this | ||
10 | * is not assumed by this driver. | ||
11 | * | ||
12 | * The typical use of this template is to instantiate the skcipher | ||
13 | * 'essiv(cbc(aes),sha256)', which is the only instantiation used by | ||
14 | * fscrypt, and the most relevant one for dm-crypt. However, dm-crypt | ||
15 | * also permits ESSIV to be used in combination with the authenc template, | ||
16 | * e.g., 'essiv(authenc(hmac(sha256),cbc(aes)),sha256)', in which case | ||
17 | * we need to instantiate an aead that accepts the same special key format | ||
18 | * as the authenc template, and deals with the way the encrypted IV is | ||
19 | * embedded into the AAD area of the aead request. This means the AEAD | ||
20 | * flavor produced by this template is tightly coupled to the way dm-crypt | ||
21 | * happens to use it. | ||
22 | * | ||
23 | * Copyright (c) 2019 Linaro, Ltd. <ard.biesheuvel@linaro.org> | ||
24 | * | ||
25 | * Heavily based on: | ||
26 | * adiantum length-preserving encryption mode | ||
27 | * | ||
28 | * Copyright 2018 Google LLC | ||
29 | */ | ||
30 | |||
31 | #include <crypto/authenc.h> | ||
32 | #include <crypto/internal/aead.h> | ||
33 | #include <crypto/internal/hash.h> | ||
34 | #include <crypto/internal/skcipher.h> | ||
35 | #include <crypto/scatterwalk.h> | ||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include "internal.h" | ||
39 | |||
40 | struct essiv_instance_ctx { | ||
41 | union { | ||
42 | struct crypto_skcipher_spawn skcipher_spawn; | ||
43 | struct crypto_aead_spawn aead_spawn; | ||
44 | } u; | ||
45 | char essiv_cipher_name[CRYPTO_MAX_ALG_NAME]; | ||
46 | char shash_driver_name[CRYPTO_MAX_ALG_NAME]; | ||
47 | }; | ||
48 | |||
49 | struct essiv_tfm_ctx { | ||
50 | union { | ||
51 | struct crypto_skcipher *skcipher; | ||
52 | struct crypto_aead *aead; | ||
53 | } u; | ||
54 | struct crypto_cipher *essiv_cipher; | ||
55 | struct crypto_shash *hash; | ||
56 | int ivoffset; | ||
57 | }; | ||
58 | |||
59 | struct essiv_aead_request_ctx { | ||
60 | struct scatterlist sg[4]; | ||
61 | u8 *assoc; | ||
62 | struct aead_request aead_req; | ||
63 | }; | ||
64 | |||
65 | static int essiv_skcipher_setkey(struct crypto_skcipher *tfm, | ||
66 | const u8 *key, unsigned int keylen) | ||
67 | { | ||
68 | struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); | ||
69 | SHASH_DESC_ON_STACK(desc, tctx->hash); | ||
70 | u8 salt[HASH_MAX_DIGESTSIZE]; | ||
71 | int err; | ||
72 | |||
73 | crypto_skcipher_clear_flags(tctx->u.skcipher, CRYPTO_TFM_REQ_MASK); | ||
74 | crypto_skcipher_set_flags(tctx->u.skcipher, | ||
75 | crypto_skcipher_get_flags(tfm) & | ||
76 | CRYPTO_TFM_REQ_MASK); | ||
77 | err = crypto_skcipher_setkey(tctx->u.skcipher, key, keylen); | ||
78 | crypto_skcipher_set_flags(tfm, | ||
79 | crypto_skcipher_get_flags(tctx->u.skcipher) & | ||
80 | CRYPTO_TFM_RES_MASK); | ||
81 | if (err) | ||
82 | return err; | ||
83 | |||
84 | desc->tfm = tctx->hash; | ||
85 | err = crypto_shash_digest(desc, key, keylen, salt); | ||
86 | if (err) | ||
87 | return err; | ||
88 | |||
89 | crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK); | ||
90 | crypto_cipher_set_flags(tctx->essiv_cipher, | ||
91 | crypto_skcipher_get_flags(tfm) & | ||
92 | CRYPTO_TFM_REQ_MASK); | ||
93 | err = crypto_cipher_setkey(tctx->essiv_cipher, salt, | ||
94 | crypto_shash_digestsize(tctx->hash)); | ||
95 | crypto_skcipher_set_flags(tfm, | ||
96 | crypto_cipher_get_flags(tctx->essiv_cipher) & | ||
97 | CRYPTO_TFM_RES_MASK); | ||
98 | |||
99 | return err; | ||
100 | } | ||
101 | |||
102 | static int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key, | ||
103 | unsigned int keylen) | ||
104 | { | ||
105 | struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); | ||
106 | SHASH_DESC_ON_STACK(desc, tctx->hash); | ||
107 | struct crypto_authenc_keys keys; | ||
108 | u8 salt[HASH_MAX_DIGESTSIZE]; | ||
109 | int err; | ||
110 | |||
111 | crypto_aead_clear_flags(tctx->u.aead, CRYPTO_TFM_REQ_MASK); | ||
112 | crypto_aead_set_flags(tctx->u.aead, crypto_aead_get_flags(tfm) & | ||
113 | CRYPTO_TFM_REQ_MASK); | ||
114 | err = crypto_aead_setkey(tctx->u.aead, key, keylen); | ||
115 | crypto_aead_set_flags(tfm, crypto_aead_get_flags(tctx->u.aead) & | ||
116 | CRYPTO_TFM_RES_MASK); | ||
117 | if (err) | ||
118 | return err; | ||
119 | |||
120 | if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) { | ||
121 | crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | |||
125 | desc->tfm = tctx->hash; | ||
126 | err = crypto_shash_init(desc) ?: | ||
127 | crypto_shash_update(desc, keys.enckey, keys.enckeylen) ?: | ||
128 | crypto_shash_finup(desc, keys.authkey, keys.authkeylen, salt); | ||
129 | if (err) | ||
130 | return err; | ||
131 | |||
132 | crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK); | ||
133 | crypto_cipher_set_flags(tctx->essiv_cipher, crypto_aead_get_flags(tfm) & | ||
134 | CRYPTO_TFM_REQ_MASK); | ||
135 | err = crypto_cipher_setkey(tctx->essiv_cipher, salt, | ||
136 | crypto_shash_digestsize(tctx->hash)); | ||
137 | crypto_aead_set_flags(tfm, crypto_cipher_get_flags(tctx->essiv_cipher) & | ||
138 | CRYPTO_TFM_RES_MASK); | ||
139 | |||
140 | return err; | ||
141 | } | ||
142 | |||
143 | static int essiv_aead_setauthsize(struct crypto_aead *tfm, | ||
144 | unsigned int authsize) | ||
145 | { | ||
146 | struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); | ||
147 | |||
148 | return crypto_aead_setauthsize(tctx->u.aead, authsize); | ||
149 | } | ||
150 | |||
151 | static void essiv_skcipher_done(struct crypto_async_request *areq, int err) | ||
152 | { | ||
153 | struct skcipher_request *req = areq->data; | ||
154 | |||
155 | skcipher_request_complete(req, err); | ||
156 | } | ||
157 | |||
158 | static int essiv_skcipher_crypt(struct skcipher_request *req, bool enc) | ||
159 | { | ||
160 | struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); | ||
161 | const struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); | ||
162 | struct skcipher_request *subreq = skcipher_request_ctx(req); | ||
163 | |||
164 | crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv); | ||
165 | |||
166 | skcipher_request_set_tfm(subreq, tctx->u.skcipher); | ||
167 | skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, | ||
168 | req->iv); | ||
169 | skcipher_request_set_callback(subreq, skcipher_request_flags(req), | ||
170 | essiv_skcipher_done, req); | ||
171 | |||
172 | return enc ? crypto_skcipher_encrypt(subreq) : | ||
173 | crypto_skcipher_decrypt(subreq); | ||
174 | } | ||
175 | |||
176 | static int essiv_skcipher_encrypt(struct skcipher_request *req) | ||
177 | { | ||
178 | return essiv_skcipher_crypt(req, true); | ||
179 | } | ||
180 | |||
181 | static int essiv_skcipher_decrypt(struct skcipher_request *req) | ||
182 | { | ||
183 | return essiv_skcipher_crypt(req, false); | ||
184 | } | ||
185 | |||
186 | static void essiv_aead_done(struct crypto_async_request *areq, int err) | ||
187 | { | ||
188 | struct aead_request *req = areq->data; | ||
189 | struct essiv_aead_request_ctx *rctx = aead_request_ctx(req); | ||
190 | |||
191 | if (rctx->assoc) | ||
192 | kfree(rctx->assoc); | ||
193 | aead_request_complete(req, err); | ||
194 | } | ||
195 | |||
196 | static int essiv_aead_crypt(struct aead_request *req, bool enc) | ||
197 | { | ||
198 | struct crypto_aead *tfm = crypto_aead_reqtfm(req); | ||
199 | const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); | ||
200 | struct essiv_aead_request_ctx *rctx = aead_request_ctx(req); | ||
201 | struct aead_request *subreq = &rctx->aead_req; | ||
202 | struct scatterlist *src = req->src; | ||
203 | int err; | ||
204 | |||
205 | crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv); | ||
206 | |||
207 | /* | ||
208 | * dm-crypt embeds the sector number and the IV in the AAD region, so | ||
209 | * we have to copy the converted IV into the right scatterlist before | ||
210 | * we pass it on. | ||
211 | */ | ||
212 | rctx->assoc = NULL; | ||
213 | if (req->src == req->dst || !enc) { | ||
214 | scatterwalk_map_and_copy(req->iv, req->dst, | ||
215 | req->assoclen - crypto_aead_ivsize(tfm), | ||
216 | crypto_aead_ivsize(tfm), 1); | ||
217 | } else { | ||
218 | u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset; | ||
219 | int ivsize = crypto_aead_ivsize(tfm); | ||
220 | int ssize = req->assoclen - ivsize; | ||
221 | struct scatterlist *sg; | ||
222 | int nents; | ||
223 | |||
224 | if (ssize < 0) | ||
225 | return -EINVAL; | ||
226 | |||
227 | nents = sg_nents_for_len(req->src, ssize); | ||
228 | if (nents < 0) | ||
229 | return -EINVAL; | ||
230 | |||
231 | memcpy(iv, req->iv, ivsize); | ||
232 | sg_init_table(rctx->sg, 4); | ||
233 | |||
234 | if (unlikely(nents > 1)) { | ||
235 | /* | ||
236 | * This is a case that rarely occurs in practice, but | ||
237 | * for correctness, we have to deal with it nonetheless. | ||
238 | */ | ||
239 | rctx->assoc = kmalloc(ssize, GFP_ATOMIC); | ||
240 | if (!rctx->assoc) | ||
241 | return -ENOMEM; | ||
242 | |||
243 | scatterwalk_map_and_copy(rctx->assoc, req->src, 0, | ||
244 | ssize, 0); | ||
245 | sg_set_buf(rctx->sg, rctx->assoc, ssize); | ||
246 | } else { | ||
247 | sg_set_page(rctx->sg, sg_page(req->src), ssize, | ||
248 | req->src->offset); | ||
249 | } | ||
250 | |||
251 | sg_set_buf(rctx->sg + 1, iv, ivsize); | ||
252 | sg = scatterwalk_ffwd(rctx->sg + 2, req->src, req->assoclen); | ||
253 | if (sg != rctx->sg + 2) | ||
254 | sg_chain(rctx->sg, 3, sg); | ||
255 | |||
256 | src = rctx->sg; | ||
257 | } | ||
258 | |||
259 | aead_request_set_tfm(subreq, tctx->u.aead); | ||
260 | aead_request_set_ad(subreq, req->assoclen); | ||
261 | aead_request_set_callback(subreq, aead_request_flags(req), | ||
262 | essiv_aead_done, req); | ||
263 | aead_request_set_crypt(subreq, src, req->dst, req->cryptlen, req->iv); | ||
264 | |||
265 | err = enc ? crypto_aead_encrypt(subreq) : | ||
266 | crypto_aead_decrypt(subreq); | ||
267 | |||
268 | if (rctx->assoc && err != -EINPROGRESS) | ||
269 | kfree(rctx->assoc); | ||
270 | return err; | ||
271 | } | ||
272 | |||
273 | static int essiv_aead_encrypt(struct aead_request *req) | ||
274 | { | ||
275 | return essiv_aead_crypt(req, true); | ||
276 | } | ||
277 | |||
278 | static int essiv_aead_decrypt(struct aead_request *req) | ||
279 | { | ||
280 | return essiv_aead_crypt(req, false); | ||
281 | } | ||
282 | |||
283 | static int essiv_init_tfm(struct essiv_instance_ctx *ictx, | ||
284 | struct essiv_tfm_ctx *tctx) | ||
285 | { | ||
286 | struct crypto_cipher *essiv_cipher; | ||
287 | struct crypto_shash *hash; | ||
288 | int err; | ||
289 | |||
290 | essiv_cipher = crypto_alloc_cipher(ictx->essiv_cipher_name, 0, 0); | ||
291 | if (IS_ERR(essiv_cipher)) | ||
292 | return PTR_ERR(essiv_cipher); | ||
293 | |||
294 | hash = crypto_alloc_shash(ictx->shash_driver_name, 0, 0); | ||
295 | if (IS_ERR(hash)) { | ||
296 | err = PTR_ERR(hash); | ||
297 | goto err_free_essiv_cipher; | ||
298 | } | ||
299 | |||
300 | tctx->essiv_cipher = essiv_cipher; | ||
301 | tctx->hash = hash; | ||
302 | |||
303 | return 0; | ||
304 | |||
305 | err_free_essiv_cipher: | ||
306 | crypto_free_cipher(essiv_cipher); | ||
307 | return err; | ||
308 | } | ||
309 | |||
310 | static int essiv_skcipher_init_tfm(struct crypto_skcipher *tfm) | ||
311 | { | ||
312 | struct skcipher_instance *inst = skcipher_alg_instance(tfm); | ||
313 | struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst); | ||
314 | struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); | ||
315 | struct crypto_skcipher *skcipher; | ||
316 | int err; | ||
317 | |||
318 | skcipher = crypto_spawn_skcipher(&ictx->u.skcipher_spawn); | ||
319 | if (IS_ERR(skcipher)) | ||
320 | return PTR_ERR(skcipher); | ||
321 | |||
322 | crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) + | ||
323 | crypto_skcipher_reqsize(skcipher)); | ||
324 | |||
325 | err = essiv_init_tfm(ictx, tctx); | ||
326 | if (err) { | ||
327 | crypto_free_skcipher(skcipher); | ||
328 | return err; | ||
329 | } | ||
330 | |||
331 | tctx->u.skcipher = skcipher; | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int essiv_aead_init_tfm(struct crypto_aead *tfm) | ||
336 | { | ||
337 | struct aead_instance *inst = aead_alg_instance(tfm); | ||
338 | struct essiv_instance_ctx *ictx = aead_instance_ctx(inst); | ||
339 | struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); | ||
340 | struct crypto_aead *aead; | ||
341 | unsigned int subreq_size; | ||
342 | int err; | ||
343 | |||
344 | BUILD_BUG_ON(offsetofend(struct essiv_aead_request_ctx, aead_req) != | ||
345 | sizeof(struct essiv_aead_request_ctx)); | ||
346 | |||
347 | aead = crypto_spawn_aead(&ictx->u.aead_spawn); | ||
348 | if (IS_ERR(aead)) | ||
349 | return PTR_ERR(aead); | ||
350 | |||
351 | subreq_size = FIELD_SIZEOF(struct essiv_aead_request_ctx, aead_req) + | ||
352 | crypto_aead_reqsize(aead); | ||
353 | |||
354 | tctx->ivoffset = offsetof(struct essiv_aead_request_ctx, aead_req) + | ||
355 | subreq_size; | ||
356 | crypto_aead_set_reqsize(tfm, tctx->ivoffset + crypto_aead_ivsize(aead)); | ||
357 | |||
358 | err = essiv_init_tfm(ictx, tctx); | ||
359 | if (err) { | ||
360 | crypto_free_aead(aead); | ||
361 | return err; | ||
362 | } | ||
363 | |||
364 | tctx->u.aead = aead; | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static void essiv_skcipher_exit_tfm(struct crypto_skcipher *tfm) | ||
369 | { | ||
370 | struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); | ||
371 | |||
372 | crypto_free_skcipher(tctx->u.skcipher); | ||
373 | crypto_free_cipher(tctx->essiv_cipher); | ||
374 | crypto_free_shash(tctx->hash); | ||
375 | } | ||
376 | |||
377 | static void essiv_aead_exit_tfm(struct crypto_aead *tfm) | ||
378 | { | ||
379 | struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); | ||
380 | |||
381 | crypto_free_aead(tctx->u.aead); | ||
382 | crypto_free_cipher(tctx->essiv_cipher); | ||
383 | crypto_free_shash(tctx->hash); | ||
384 | } | ||
385 | |||
386 | static void essiv_skcipher_free_instance(struct skcipher_instance *inst) | ||
387 | { | ||
388 | struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst); | ||
389 | |||
390 | crypto_drop_skcipher(&ictx->u.skcipher_spawn); | ||
391 | kfree(inst); | ||
392 | } | ||
393 | |||
394 | static void essiv_aead_free_instance(struct aead_instance *inst) | ||
395 | { | ||
396 | struct essiv_instance_ctx *ictx = aead_instance_ctx(inst); | ||
397 | |||
398 | crypto_drop_aead(&ictx->u.aead_spawn); | ||
399 | kfree(inst); | ||
400 | } | ||
401 | |||
402 | static bool parse_cipher_name(char *essiv_cipher_name, const char *cra_name) | ||
403 | { | ||
404 | const char *p, *q; | ||
405 | int len; | ||
406 | |||
407 | /* find the last opening parens */ | ||
408 | p = strrchr(cra_name, '('); | ||
409 | if (!p++) | ||
410 | return false; | ||
411 | |||
412 | /* find the first closing parens in the tail of the string */ | ||
413 | q = strchr(p, ')'); | ||
414 | if (!q) | ||
415 | return false; | ||
416 | |||
417 | len = q - p; | ||
418 | if (len >= CRYPTO_MAX_ALG_NAME) | ||
419 | return false; | ||
420 | |||
421 | memcpy(essiv_cipher_name, p, len); | ||
422 | essiv_cipher_name[len] = '\0'; | ||
423 | return true; | ||
424 | } | ||
425 | |||
426 | static bool essiv_supported_algorithms(const char *essiv_cipher_name, | ||
427 | struct shash_alg *hash_alg, | ||
428 | int ivsize) | ||
429 | { | ||
430 | struct crypto_alg *alg; | ||
431 | bool ret = false; | ||
432 | |||
433 | alg = crypto_alg_mod_lookup(essiv_cipher_name, | ||
434 | CRYPTO_ALG_TYPE_CIPHER, | ||
435 | CRYPTO_ALG_TYPE_MASK); | ||
436 | if (IS_ERR(alg)) | ||
437 | return false; | ||
438 | |||
439 | if (hash_alg->digestsize < alg->cra_cipher.cia_min_keysize || | ||
440 | hash_alg->digestsize > alg->cra_cipher.cia_max_keysize) | ||
441 | goto out; | ||
442 | |||
443 | if (ivsize != alg->cra_blocksize) | ||
444 | goto out; | ||
445 | |||
446 | if (crypto_shash_alg_has_setkey(hash_alg)) | ||
447 | goto out; | ||
448 | |||
449 | ret = true; | ||
450 | |||
451 | out: | ||
452 | crypto_mod_put(alg); | ||
453 | return ret; | ||
454 | } | ||
455 | |||
456 | static int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) | ||
457 | { | ||
458 | struct crypto_attr_type *algt; | ||
459 | const char *inner_cipher_name; | ||
460 | const char *shash_name; | ||
461 | struct skcipher_instance *skcipher_inst = NULL; | ||
462 | struct aead_instance *aead_inst = NULL; | ||
463 | struct crypto_instance *inst; | ||
464 | struct crypto_alg *base, *block_base; | ||
465 | struct essiv_instance_ctx *ictx; | ||
466 | struct skcipher_alg *skcipher_alg = NULL; | ||
467 | struct aead_alg *aead_alg = NULL; | ||
468 | struct crypto_alg *_hash_alg; | ||
469 | struct shash_alg *hash_alg; | ||
470 | int ivsize; | ||
471 | u32 type; | ||
472 | int err; | ||
473 | |||
474 | algt = crypto_get_attr_type(tb); | ||
475 | if (IS_ERR(algt)) | ||
476 | return PTR_ERR(algt); | ||
477 | |||
478 | inner_cipher_name = crypto_attr_alg_name(tb[1]); | ||
479 | if (IS_ERR(inner_cipher_name)) | ||
480 | return PTR_ERR(inner_cipher_name); | ||
481 | |||
482 | shash_name = crypto_attr_alg_name(tb[2]); | ||
483 | if (IS_ERR(shash_name)) | ||
484 | return PTR_ERR(shash_name); | ||
485 | |||
486 | type = algt->type & algt->mask; | ||
487 | |||
488 | switch (type) { | ||
489 | case CRYPTO_ALG_TYPE_BLKCIPHER: | ||
490 | skcipher_inst = kzalloc(sizeof(*skcipher_inst) + | ||
491 | sizeof(*ictx), GFP_KERNEL); | ||
492 | if (!skcipher_inst) | ||
493 | return -ENOMEM; | ||
494 | inst = skcipher_crypto_instance(skcipher_inst); | ||
495 | base = &skcipher_inst->alg.base; | ||
496 | ictx = crypto_instance_ctx(inst); | ||
497 | |||
498 | /* Symmetric cipher, e.g., "cbc(aes)" */ | ||
499 | crypto_set_skcipher_spawn(&ictx->u.skcipher_spawn, inst); | ||
500 | err = crypto_grab_skcipher(&ictx->u.skcipher_spawn, | ||
501 | inner_cipher_name, 0, | ||
502 | crypto_requires_sync(algt->type, | ||
503 | algt->mask)); | ||
504 | if (err) | ||
505 | goto out_free_inst; | ||
506 | skcipher_alg = crypto_spawn_skcipher_alg(&ictx->u.skcipher_spawn); | ||
507 | block_base = &skcipher_alg->base; | ||
508 | ivsize = crypto_skcipher_alg_ivsize(skcipher_alg); | ||
509 | break; | ||
510 | |||
511 | case CRYPTO_ALG_TYPE_AEAD: | ||
512 | aead_inst = kzalloc(sizeof(*aead_inst) + | ||
513 | sizeof(*ictx), GFP_KERNEL); | ||
514 | if (!aead_inst) | ||
515 | return -ENOMEM; | ||
516 | inst = aead_crypto_instance(aead_inst); | ||
517 | base = &aead_inst->alg.base; | ||
518 | ictx = crypto_instance_ctx(inst); | ||
519 | |||
520 | /* AEAD cipher, e.g., "authenc(hmac(sha256),cbc(aes))" */ | ||
521 | crypto_set_aead_spawn(&ictx->u.aead_spawn, inst); | ||
522 | err = crypto_grab_aead(&ictx->u.aead_spawn, | ||
523 | inner_cipher_name, 0, | ||
524 | crypto_requires_sync(algt->type, | ||
525 | algt->mask)); | ||
526 | if (err) | ||
527 | goto out_free_inst; | ||
528 | aead_alg = crypto_spawn_aead_alg(&ictx->u.aead_spawn); | ||
529 | block_base = &aead_alg->base; | ||
530 | if (!strstarts(block_base->cra_name, "authenc(")) { | ||
531 | pr_warn("Only authenc() type AEADs are supported by ESSIV\n"); | ||
532 | err = -EINVAL; | ||
533 | goto out_drop_skcipher; | ||
534 | } | ||
535 | ivsize = aead_alg->ivsize; | ||
536 | break; | ||
537 | |||
538 | default: | ||
539 | return -EINVAL; | ||
540 | } | ||
541 | |||
542 | if (!parse_cipher_name(ictx->essiv_cipher_name, block_base->cra_name)) { | ||
543 | pr_warn("Failed to parse ESSIV cipher name from skcipher cra_name\n"); | ||
544 | err = -EINVAL; | ||
545 | goto out_drop_skcipher; | ||
546 | } | ||
547 | |||
548 | /* Synchronous hash, e.g., "sha256" */ | ||
549 | _hash_alg = crypto_alg_mod_lookup(shash_name, | ||
550 | CRYPTO_ALG_TYPE_SHASH, | ||
551 | CRYPTO_ALG_TYPE_MASK); | ||
552 | if (IS_ERR(_hash_alg)) { | ||
553 | err = PTR_ERR(_hash_alg); | ||
554 | goto out_drop_skcipher; | ||
555 | } | ||
556 | hash_alg = __crypto_shash_alg(_hash_alg); | ||
557 | |||
558 | /* Check the set of algorithms */ | ||
559 | if (!essiv_supported_algorithms(ictx->essiv_cipher_name, hash_alg, | ||
560 | ivsize)) { | ||
561 | pr_warn("Unsupported essiv instantiation: essiv(%s,%s)\n", | ||
562 | block_base->cra_name, hash_alg->base.cra_name); | ||
563 | err = -EINVAL; | ||
564 | goto out_free_hash; | ||
565 | } | ||
566 | |||
567 | /* record the driver name so we can instantiate this exact algo later */ | ||
568 | strlcpy(ictx->shash_driver_name, hash_alg->base.cra_driver_name, | ||
569 | CRYPTO_MAX_ALG_NAME); | ||
570 | |||
571 | /* Instance fields */ | ||
572 | |||
573 | err = -ENAMETOOLONG; | ||
574 | if (snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, | ||
575 | "essiv(%s,%s)", block_base->cra_name, | ||
576 | hash_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME) | ||
577 | goto out_free_hash; | ||
578 | if (snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, | ||
579 | "essiv(%s,%s)", block_base->cra_driver_name, | ||
580 | hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) | ||
581 | goto out_free_hash; | ||
582 | |||
583 | base->cra_flags = block_base->cra_flags & CRYPTO_ALG_ASYNC; | ||
584 | base->cra_blocksize = block_base->cra_blocksize; | ||
585 | base->cra_ctxsize = sizeof(struct essiv_tfm_ctx); | ||
586 | base->cra_alignmask = block_base->cra_alignmask; | ||
587 | base->cra_priority = block_base->cra_priority; | ||
588 | |||
589 | if (type == CRYPTO_ALG_TYPE_BLKCIPHER) { | ||
590 | skcipher_inst->alg.setkey = essiv_skcipher_setkey; | ||
591 | skcipher_inst->alg.encrypt = essiv_skcipher_encrypt; | ||
592 | skcipher_inst->alg.decrypt = essiv_skcipher_decrypt; | ||
593 | skcipher_inst->alg.init = essiv_skcipher_init_tfm; | ||
594 | skcipher_inst->alg.exit = essiv_skcipher_exit_tfm; | ||
595 | |||
596 | skcipher_inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(skcipher_alg); | ||
597 | skcipher_inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(skcipher_alg); | ||
598 | skcipher_inst->alg.ivsize = ivsize; | ||
599 | skcipher_inst->alg.chunksize = crypto_skcipher_alg_chunksize(skcipher_alg); | ||
600 | skcipher_inst->alg.walksize = crypto_skcipher_alg_walksize(skcipher_alg); | ||
601 | |||
602 | skcipher_inst->free = essiv_skcipher_free_instance; | ||
603 | |||
604 | err = skcipher_register_instance(tmpl, skcipher_inst); | ||
605 | } else { | ||
606 | aead_inst->alg.setkey = essiv_aead_setkey; | ||
607 | aead_inst->alg.setauthsize = essiv_aead_setauthsize; | ||
608 | aead_inst->alg.encrypt = essiv_aead_encrypt; | ||
609 | aead_inst->alg.decrypt = essiv_aead_decrypt; | ||
610 | aead_inst->alg.init = essiv_aead_init_tfm; | ||
611 | aead_inst->alg.exit = essiv_aead_exit_tfm; | ||
612 | |||
613 | aead_inst->alg.ivsize = ivsize; | ||
614 | aead_inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(aead_alg); | ||
615 | aead_inst->alg.chunksize = crypto_aead_alg_chunksize(aead_alg); | ||
616 | |||
617 | aead_inst->free = essiv_aead_free_instance; | ||
618 | |||
619 | err = aead_register_instance(tmpl, aead_inst); | ||
620 | } | ||
621 | |||
622 | if (err) | ||
623 | goto out_free_hash; | ||
624 | |||
625 | crypto_mod_put(_hash_alg); | ||
626 | return 0; | ||
627 | |||
628 | out_free_hash: | ||
629 | crypto_mod_put(_hash_alg); | ||
630 | out_drop_skcipher: | ||
631 | if (type == CRYPTO_ALG_TYPE_BLKCIPHER) | ||
632 | crypto_drop_skcipher(&ictx->u.skcipher_spawn); | ||
633 | else | ||
634 | crypto_drop_aead(&ictx->u.aead_spawn); | ||
635 | out_free_inst: | ||
636 | kfree(skcipher_inst); | ||
637 | kfree(aead_inst); | ||
638 | return err; | ||
639 | } | ||
640 | |||
641 | /* essiv(cipher_name, shash_name) */ | ||
642 | static struct crypto_template essiv_tmpl = { | ||
643 | .name = "essiv", | ||
644 | .create = essiv_create, | ||
645 | .module = THIS_MODULE, | ||
646 | }; | ||
647 | |||
648 | static int __init essiv_module_init(void) | ||
649 | { | ||
650 | return crypto_register_template(&essiv_tmpl); | ||
651 | } | ||
652 | |||
653 | static void __exit essiv_module_exit(void) | ||
654 | { | ||
655 | crypto_unregister_template(&essiv_tmpl); | ||
656 | } | ||
657 | |||
658 | subsys_initcall(essiv_module_init); | ||
659 | module_exit(essiv_module_exit); | ||
660 | |||
661 | MODULE_DESCRIPTION("ESSIV skcipher/aead wrapper for block encryption"); | ||
662 | MODULE_LICENSE("GPL v2"); | ||
663 | MODULE_ALIAS_CRYPTO("essiv"); | ||