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