162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ESSIV skcipher and aead template for block encryption 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This template encapsulates the ESSIV IV generation algorithm used by 662306a36Sopenharmony_ci * dm-crypt and fscrypt, which converts the initial vector for the skcipher 762306a36Sopenharmony_ci * used for block encryption, by encrypting it using the hash of the 862306a36Sopenharmony_ci * skcipher key as encryption key. Usually, the input IV is a 64-bit sector 962306a36Sopenharmony_ci * number in LE representation zero-padded to the size of the IV, but this 1062306a36Sopenharmony_ci * is not assumed by this driver. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * The typical use of this template is to instantiate the skcipher 1362306a36Sopenharmony_ci * 'essiv(cbc(aes),sha256)', which is the only instantiation used by 1462306a36Sopenharmony_ci * fscrypt, and the most relevant one for dm-crypt. However, dm-crypt 1562306a36Sopenharmony_ci * also permits ESSIV to be used in combination with the authenc template, 1662306a36Sopenharmony_ci * e.g., 'essiv(authenc(hmac(sha256),cbc(aes)),sha256)', in which case 1762306a36Sopenharmony_ci * we need to instantiate an aead that accepts the same special key format 1862306a36Sopenharmony_ci * as the authenc template, and deals with the way the encrypted IV is 1962306a36Sopenharmony_ci * embedded into the AAD area of the aead request. This means the AEAD 2062306a36Sopenharmony_ci * flavor produced by this template is tightly coupled to the way dm-crypt 2162306a36Sopenharmony_ci * happens to use it. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Copyright (c) 2019 Linaro, Ltd. <ard.biesheuvel@linaro.org> 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Heavily based on: 2662306a36Sopenharmony_ci * adiantum length-preserving encryption mode 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * Copyright 2018 Google LLC 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <crypto/authenc.h> 3262306a36Sopenharmony_ci#include <crypto/internal/aead.h> 3362306a36Sopenharmony_ci#include <crypto/internal/cipher.h> 3462306a36Sopenharmony_ci#include <crypto/internal/hash.h> 3562306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 3662306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 3762306a36Sopenharmony_ci#include <linux/module.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include "internal.h" 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct essiv_instance_ctx { 4262306a36Sopenharmony_ci union { 4362306a36Sopenharmony_ci struct crypto_skcipher_spawn skcipher_spawn; 4462306a36Sopenharmony_ci struct crypto_aead_spawn aead_spawn; 4562306a36Sopenharmony_ci } u; 4662306a36Sopenharmony_ci char essiv_cipher_name[CRYPTO_MAX_ALG_NAME]; 4762306a36Sopenharmony_ci char shash_driver_name[CRYPTO_MAX_ALG_NAME]; 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistruct essiv_tfm_ctx { 5162306a36Sopenharmony_ci union { 5262306a36Sopenharmony_ci struct crypto_skcipher *skcipher; 5362306a36Sopenharmony_ci struct crypto_aead *aead; 5462306a36Sopenharmony_ci } u; 5562306a36Sopenharmony_ci struct crypto_cipher *essiv_cipher; 5662306a36Sopenharmony_ci struct crypto_shash *hash; 5762306a36Sopenharmony_ci int ivoffset; 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistruct essiv_aead_request_ctx { 6162306a36Sopenharmony_ci struct scatterlist sg[4]; 6262306a36Sopenharmony_ci u8 *assoc; 6362306a36Sopenharmony_ci struct aead_request aead_req; 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int essiv_skcipher_setkey(struct crypto_skcipher *tfm, 6762306a36Sopenharmony_ci const u8 *key, unsigned int keylen) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 7062306a36Sopenharmony_ci u8 salt[HASH_MAX_DIGESTSIZE]; 7162306a36Sopenharmony_ci int err; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci crypto_skcipher_clear_flags(tctx->u.skcipher, CRYPTO_TFM_REQ_MASK); 7462306a36Sopenharmony_ci crypto_skcipher_set_flags(tctx->u.skcipher, 7562306a36Sopenharmony_ci crypto_skcipher_get_flags(tfm) & 7662306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 7762306a36Sopenharmony_ci err = crypto_skcipher_setkey(tctx->u.skcipher, key, keylen); 7862306a36Sopenharmony_ci if (err) 7962306a36Sopenharmony_ci return err; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci err = crypto_shash_tfm_digest(tctx->hash, key, keylen, salt); 8262306a36Sopenharmony_ci if (err) 8362306a36Sopenharmony_ci return err; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK); 8662306a36Sopenharmony_ci crypto_cipher_set_flags(tctx->essiv_cipher, 8762306a36Sopenharmony_ci crypto_skcipher_get_flags(tfm) & 8862306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 8962306a36Sopenharmony_ci return crypto_cipher_setkey(tctx->essiv_cipher, salt, 9062306a36Sopenharmony_ci crypto_shash_digestsize(tctx->hash)); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic int essiv_aead_setkey(struct crypto_aead *tfm, const u8 *key, 9462306a36Sopenharmony_ci unsigned int keylen) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); 9762306a36Sopenharmony_ci SHASH_DESC_ON_STACK(desc, tctx->hash); 9862306a36Sopenharmony_ci struct crypto_authenc_keys keys; 9962306a36Sopenharmony_ci u8 salt[HASH_MAX_DIGESTSIZE]; 10062306a36Sopenharmony_ci int err; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci crypto_aead_clear_flags(tctx->u.aead, CRYPTO_TFM_REQ_MASK); 10362306a36Sopenharmony_ci crypto_aead_set_flags(tctx->u.aead, crypto_aead_get_flags(tfm) & 10462306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 10562306a36Sopenharmony_ci err = crypto_aead_setkey(tctx->u.aead, key, keylen); 10662306a36Sopenharmony_ci if (err) 10762306a36Sopenharmony_ci return err; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 11062306a36Sopenharmony_ci return -EINVAL; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci desc->tfm = tctx->hash; 11362306a36Sopenharmony_ci err = crypto_shash_init(desc) ?: 11462306a36Sopenharmony_ci crypto_shash_update(desc, keys.enckey, keys.enckeylen) ?: 11562306a36Sopenharmony_ci crypto_shash_finup(desc, keys.authkey, keys.authkeylen, salt); 11662306a36Sopenharmony_ci if (err) 11762306a36Sopenharmony_ci return err; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci crypto_cipher_clear_flags(tctx->essiv_cipher, CRYPTO_TFM_REQ_MASK); 12062306a36Sopenharmony_ci crypto_cipher_set_flags(tctx->essiv_cipher, crypto_aead_get_flags(tfm) & 12162306a36Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 12262306a36Sopenharmony_ci return crypto_cipher_setkey(tctx->essiv_cipher, salt, 12362306a36Sopenharmony_ci crypto_shash_digestsize(tctx->hash)); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic int essiv_aead_setauthsize(struct crypto_aead *tfm, 12762306a36Sopenharmony_ci unsigned int authsize) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci return crypto_aead_setauthsize(tctx->u.aead, authsize); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic void essiv_skcipher_done(void *data, int err) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct skcipher_request *req = data; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci skcipher_request_complete(req, err); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic int essiv_skcipher_crypt(struct skcipher_request *req, bool enc) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 14462306a36Sopenharmony_ci const struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 14562306a36Sopenharmony_ci struct skcipher_request *subreq = skcipher_request_ctx(req); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci skcipher_request_set_tfm(subreq, tctx->u.skcipher); 15062306a36Sopenharmony_ci skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, 15162306a36Sopenharmony_ci req->iv); 15262306a36Sopenharmony_ci skcipher_request_set_callback(subreq, skcipher_request_flags(req), 15362306a36Sopenharmony_ci essiv_skcipher_done, req); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci return enc ? crypto_skcipher_encrypt(subreq) : 15662306a36Sopenharmony_ci crypto_skcipher_decrypt(subreq); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic int essiv_skcipher_encrypt(struct skcipher_request *req) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci return essiv_skcipher_crypt(req, true); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic int essiv_skcipher_decrypt(struct skcipher_request *req) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci return essiv_skcipher_crypt(req, false); 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic void essiv_aead_done(void *data, int err) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct aead_request *req = data; 17262306a36Sopenharmony_ci struct essiv_aead_request_ctx *rctx = aead_request_ctx(req); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (err == -EINPROGRESS) 17562306a36Sopenharmony_ci goto out; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci kfree(rctx->assoc); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ciout: 18062306a36Sopenharmony_ci aead_request_complete(req, err); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int essiv_aead_crypt(struct aead_request *req, bool enc) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 18662306a36Sopenharmony_ci const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); 18762306a36Sopenharmony_ci struct essiv_aead_request_ctx *rctx = aead_request_ctx(req); 18862306a36Sopenharmony_ci struct aead_request *subreq = &rctx->aead_req; 18962306a36Sopenharmony_ci struct scatterlist *src = req->src; 19062306a36Sopenharmony_ci int err; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* 19562306a36Sopenharmony_ci * dm-crypt embeds the sector number and the IV in the AAD region, so 19662306a36Sopenharmony_ci * we have to copy the converted IV into the right scatterlist before 19762306a36Sopenharmony_ci * we pass it on. 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ci rctx->assoc = NULL; 20062306a36Sopenharmony_ci if (req->src == req->dst || !enc) { 20162306a36Sopenharmony_ci scatterwalk_map_and_copy(req->iv, req->dst, 20262306a36Sopenharmony_ci req->assoclen - crypto_aead_ivsize(tfm), 20362306a36Sopenharmony_ci crypto_aead_ivsize(tfm), 1); 20462306a36Sopenharmony_ci } else { 20562306a36Sopenharmony_ci u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset; 20662306a36Sopenharmony_ci int ivsize = crypto_aead_ivsize(tfm); 20762306a36Sopenharmony_ci int ssize = req->assoclen - ivsize; 20862306a36Sopenharmony_ci struct scatterlist *sg; 20962306a36Sopenharmony_ci int nents; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci if (ssize < 0) 21262306a36Sopenharmony_ci return -EINVAL; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci nents = sg_nents_for_len(req->src, ssize); 21562306a36Sopenharmony_ci if (nents < 0) 21662306a36Sopenharmony_ci return -EINVAL; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci memcpy(iv, req->iv, ivsize); 21962306a36Sopenharmony_ci sg_init_table(rctx->sg, 4); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (unlikely(nents > 1)) { 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * This is a case that rarely occurs in practice, but 22462306a36Sopenharmony_ci * for correctness, we have to deal with it nonetheless. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci rctx->assoc = kmalloc(ssize, GFP_ATOMIC); 22762306a36Sopenharmony_ci if (!rctx->assoc) 22862306a36Sopenharmony_ci return -ENOMEM; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci scatterwalk_map_and_copy(rctx->assoc, req->src, 0, 23162306a36Sopenharmony_ci ssize, 0); 23262306a36Sopenharmony_ci sg_set_buf(rctx->sg, rctx->assoc, ssize); 23362306a36Sopenharmony_ci } else { 23462306a36Sopenharmony_ci sg_set_page(rctx->sg, sg_page(req->src), ssize, 23562306a36Sopenharmony_ci req->src->offset); 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci sg_set_buf(rctx->sg + 1, iv, ivsize); 23962306a36Sopenharmony_ci sg = scatterwalk_ffwd(rctx->sg + 2, req->src, req->assoclen); 24062306a36Sopenharmony_ci if (sg != rctx->sg + 2) 24162306a36Sopenharmony_ci sg_chain(rctx->sg, 3, sg); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci src = rctx->sg; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci aead_request_set_tfm(subreq, tctx->u.aead); 24762306a36Sopenharmony_ci aead_request_set_ad(subreq, req->assoclen); 24862306a36Sopenharmony_ci aead_request_set_callback(subreq, aead_request_flags(req), 24962306a36Sopenharmony_ci essiv_aead_done, req); 25062306a36Sopenharmony_ci aead_request_set_crypt(subreq, src, req->dst, req->cryptlen, req->iv); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci err = enc ? crypto_aead_encrypt(subreq) : 25362306a36Sopenharmony_ci crypto_aead_decrypt(subreq); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (rctx->assoc && err != -EINPROGRESS && err != -EBUSY) 25662306a36Sopenharmony_ci kfree(rctx->assoc); 25762306a36Sopenharmony_ci return err; 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cistatic int essiv_aead_encrypt(struct aead_request *req) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci return essiv_aead_crypt(req, true); 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic int essiv_aead_decrypt(struct aead_request *req) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci return essiv_aead_crypt(req, false); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic int essiv_init_tfm(struct essiv_instance_ctx *ictx, 27162306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct crypto_cipher *essiv_cipher; 27462306a36Sopenharmony_ci struct crypto_shash *hash; 27562306a36Sopenharmony_ci int err; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci essiv_cipher = crypto_alloc_cipher(ictx->essiv_cipher_name, 0, 0); 27862306a36Sopenharmony_ci if (IS_ERR(essiv_cipher)) 27962306a36Sopenharmony_ci return PTR_ERR(essiv_cipher); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci hash = crypto_alloc_shash(ictx->shash_driver_name, 0, 0); 28262306a36Sopenharmony_ci if (IS_ERR(hash)) { 28362306a36Sopenharmony_ci err = PTR_ERR(hash); 28462306a36Sopenharmony_ci goto err_free_essiv_cipher; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci tctx->essiv_cipher = essiv_cipher; 28862306a36Sopenharmony_ci tctx->hash = hash; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cierr_free_essiv_cipher: 29362306a36Sopenharmony_ci crypto_free_cipher(essiv_cipher); 29462306a36Sopenharmony_ci return err; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic int essiv_skcipher_init_tfm(struct crypto_skcipher *tfm) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci struct skcipher_instance *inst = skcipher_alg_instance(tfm); 30062306a36Sopenharmony_ci struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst); 30162306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 30262306a36Sopenharmony_ci struct crypto_skcipher *skcipher; 30362306a36Sopenharmony_ci int err; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci skcipher = crypto_spawn_skcipher(&ictx->u.skcipher_spawn); 30662306a36Sopenharmony_ci if (IS_ERR(skcipher)) 30762306a36Sopenharmony_ci return PTR_ERR(skcipher); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) + 31062306a36Sopenharmony_ci crypto_skcipher_reqsize(skcipher)); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci err = essiv_init_tfm(ictx, tctx); 31362306a36Sopenharmony_ci if (err) { 31462306a36Sopenharmony_ci crypto_free_skcipher(skcipher); 31562306a36Sopenharmony_ci return err; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci tctx->u.skcipher = skcipher; 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic int essiv_aead_init_tfm(struct crypto_aead *tfm) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct aead_instance *inst = aead_alg_instance(tfm); 32562306a36Sopenharmony_ci struct essiv_instance_ctx *ictx = aead_instance_ctx(inst); 32662306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); 32762306a36Sopenharmony_ci struct crypto_aead *aead; 32862306a36Sopenharmony_ci unsigned int subreq_size; 32962306a36Sopenharmony_ci int err; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci BUILD_BUG_ON(offsetofend(struct essiv_aead_request_ctx, aead_req) != 33262306a36Sopenharmony_ci sizeof(struct essiv_aead_request_ctx)); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci aead = crypto_spawn_aead(&ictx->u.aead_spawn); 33562306a36Sopenharmony_ci if (IS_ERR(aead)) 33662306a36Sopenharmony_ci return PTR_ERR(aead); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci subreq_size = sizeof_field(struct essiv_aead_request_ctx, aead_req) + 33962306a36Sopenharmony_ci crypto_aead_reqsize(aead); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci tctx->ivoffset = offsetof(struct essiv_aead_request_ctx, aead_req) + 34262306a36Sopenharmony_ci subreq_size; 34362306a36Sopenharmony_ci crypto_aead_set_reqsize(tfm, tctx->ivoffset + crypto_aead_ivsize(aead)); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci err = essiv_init_tfm(ictx, tctx); 34662306a36Sopenharmony_ci if (err) { 34762306a36Sopenharmony_ci crypto_free_aead(aead); 34862306a36Sopenharmony_ci return err; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci tctx->u.aead = aead; 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic void essiv_skcipher_exit_tfm(struct crypto_skcipher *tfm) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci crypto_free_skcipher(tctx->u.skcipher); 36062306a36Sopenharmony_ci crypto_free_cipher(tctx->essiv_cipher); 36162306a36Sopenharmony_ci crypto_free_shash(tctx->hash); 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic void essiv_aead_exit_tfm(struct crypto_aead *tfm) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci crypto_free_aead(tctx->u.aead); 36962306a36Sopenharmony_ci crypto_free_cipher(tctx->essiv_cipher); 37062306a36Sopenharmony_ci crypto_free_shash(tctx->hash); 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic void essiv_skcipher_free_instance(struct skcipher_instance *inst) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci struct essiv_instance_ctx *ictx = skcipher_instance_ctx(inst); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci crypto_drop_skcipher(&ictx->u.skcipher_spawn); 37862306a36Sopenharmony_ci kfree(inst); 37962306a36Sopenharmony_ci} 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_cistatic void essiv_aead_free_instance(struct aead_instance *inst) 38262306a36Sopenharmony_ci{ 38362306a36Sopenharmony_ci struct essiv_instance_ctx *ictx = aead_instance_ctx(inst); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci crypto_drop_aead(&ictx->u.aead_spawn); 38662306a36Sopenharmony_ci kfree(inst); 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic bool parse_cipher_name(char *essiv_cipher_name, const char *cra_name) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci const char *p, *q; 39262306a36Sopenharmony_ci int len; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* find the last opening parens */ 39562306a36Sopenharmony_ci p = strrchr(cra_name, '('); 39662306a36Sopenharmony_ci if (!p++) 39762306a36Sopenharmony_ci return false; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* find the first closing parens in the tail of the string */ 40062306a36Sopenharmony_ci q = strchr(p, ')'); 40162306a36Sopenharmony_ci if (!q) 40262306a36Sopenharmony_ci return false; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci len = q - p; 40562306a36Sopenharmony_ci if (len >= CRYPTO_MAX_ALG_NAME) 40662306a36Sopenharmony_ci return false; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci memcpy(essiv_cipher_name, p, len); 40962306a36Sopenharmony_ci essiv_cipher_name[len] = '\0'; 41062306a36Sopenharmony_ci return true; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic bool essiv_supported_algorithms(const char *essiv_cipher_name, 41462306a36Sopenharmony_ci struct shash_alg *hash_alg, 41562306a36Sopenharmony_ci int ivsize) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci struct crypto_alg *alg; 41862306a36Sopenharmony_ci bool ret = false; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci alg = crypto_alg_mod_lookup(essiv_cipher_name, 42162306a36Sopenharmony_ci CRYPTO_ALG_TYPE_CIPHER, 42262306a36Sopenharmony_ci CRYPTO_ALG_TYPE_MASK); 42362306a36Sopenharmony_ci if (IS_ERR(alg)) 42462306a36Sopenharmony_ci return false; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if (hash_alg->digestsize < alg->cra_cipher.cia_min_keysize || 42762306a36Sopenharmony_ci hash_alg->digestsize > alg->cra_cipher.cia_max_keysize) 42862306a36Sopenharmony_ci goto out; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci if (ivsize != alg->cra_blocksize) 43162306a36Sopenharmony_ci goto out; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci if (crypto_shash_alg_needs_key(hash_alg)) 43462306a36Sopenharmony_ci goto out; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci ret = true; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ciout: 43962306a36Sopenharmony_ci crypto_mod_put(alg); 44062306a36Sopenharmony_ci return ret; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic int essiv_create(struct crypto_template *tmpl, struct rtattr **tb) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci struct crypto_attr_type *algt; 44662306a36Sopenharmony_ci const char *inner_cipher_name; 44762306a36Sopenharmony_ci const char *shash_name; 44862306a36Sopenharmony_ci struct skcipher_instance *skcipher_inst = NULL; 44962306a36Sopenharmony_ci struct aead_instance *aead_inst = NULL; 45062306a36Sopenharmony_ci struct crypto_instance *inst; 45162306a36Sopenharmony_ci struct crypto_alg *base, *block_base; 45262306a36Sopenharmony_ci struct essiv_instance_ctx *ictx; 45362306a36Sopenharmony_ci struct skcipher_alg *skcipher_alg = NULL; 45462306a36Sopenharmony_ci struct aead_alg *aead_alg = NULL; 45562306a36Sopenharmony_ci struct crypto_alg *_hash_alg; 45662306a36Sopenharmony_ci struct shash_alg *hash_alg; 45762306a36Sopenharmony_ci int ivsize; 45862306a36Sopenharmony_ci u32 type; 45962306a36Sopenharmony_ci u32 mask; 46062306a36Sopenharmony_ci int err; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci algt = crypto_get_attr_type(tb); 46362306a36Sopenharmony_ci if (IS_ERR(algt)) 46462306a36Sopenharmony_ci return PTR_ERR(algt); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci inner_cipher_name = crypto_attr_alg_name(tb[1]); 46762306a36Sopenharmony_ci if (IS_ERR(inner_cipher_name)) 46862306a36Sopenharmony_ci return PTR_ERR(inner_cipher_name); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci shash_name = crypto_attr_alg_name(tb[2]); 47162306a36Sopenharmony_ci if (IS_ERR(shash_name)) 47262306a36Sopenharmony_ci return PTR_ERR(shash_name); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci type = algt->type & algt->mask; 47562306a36Sopenharmony_ci mask = crypto_algt_inherited_mask(algt); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci switch (type) { 47862306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_SKCIPHER: 47962306a36Sopenharmony_ci skcipher_inst = kzalloc(sizeof(*skcipher_inst) + 48062306a36Sopenharmony_ci sizeof(*ictx), GFP_KERNEL); 48162306a36Sopenharmony_ci if (!skcipher_inst) 48262306a36Sopenharmony_ci return -ENOMEM; 48362306a36Sopenharmony_ci inst = skcipher_crypto_instance(skcipher_inst); 48462306a36Sopenharmony_ci base = &skcipher_inst->alg.base; 48562306a36Sopenharmony_ci ictx = crypto_instance_ctx(inst); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* Symmetric cipher, e.g., "cbc(aes)" */ 48862306a36Sopenharmony_ci err = crypto_grab_skcipher(&ictx->u.skcipher_spawn, inst, 48962306a36Sopenharmony_ci inner_cipher_name, 0, mask); 49062306a36Sopenharmony_ci if (err) 49162306a36Sopenharmony_ci goto out_free_inst; 49262306a36Sopenharmony_ci skcipher_alg = crypto_spawn_skcipher_alg(&ictx->u.skcipher_spawn); 49362306a36Sopenharmony_ci block_base = &skcipher_alg->base; 49462306a36Sopenharmony_ci ivsize = crypto_skcipher_alg_ivsize(skcipher_alg); 49562306a36Sopenharmony_ci break; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci case CRYPTO_ALG_TYPE_AEAD: 49862306a36Sopenharmony_ci aead_inst = kzalloc(sizeof(*aead_inst) + 49962306a36Sopenharmony_ci sizeof(*ictx), GFP_KERNEL); 50062306a36Sopenharmony_ci if (!aead_inst) 50162306a36Sopenharmony_ci return -ENOMEM; 50262306a36Sopenharmony_ci inst = aead_crypto_instance(aead_inst); 50362306a36Sopenharmony_ci base = &aead_inst->alg.base; 50462306a36Sopenharmony_ci ictx = crypto_instance_ctx(inst); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* AEAD cipher, e.g., "authenc(hmac(sha256),cbc(aes))" */ 50762306a36Sopenharmony_ci err = crypto_grab_aead(&ictx->u.aead_spawn, inst, 50862306a36Sopenharmony_ci inner_cipher_name, 0, mask); 50962306a36Sopenharmony_ci if (err) 51062306a36Sopenharmony_ci goto out_free_inst; 51162306a36Sopenharmony_ci aead_alg = crypto_spawn_aead_alg(&ictx->u.aead_spawn); 51262306a36Sopenharmony_ci block_base = &aead_alg->base; 51362306a36Sopenharmony_ci if (!strstarts(block_base->cra_name, "authenc(")) { 51462306a36Sopenharmony_ci pr_warn("Only authenc() type AEADs are supported by ESSIV\n"); 51562306a36Sopenharmony_ci err = -EINVAL; 51662306a36Sopenharmony_ci goto out_drop_skcipher; 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci ivsize = aead_alg->ivsize; 51962306a36Sopenharmony_ci break; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci default: 52262306a36Sopenharmony_ci return -EINVAL; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (!parse_cipher_name(ictx->essiv_cipher_name, block_base->cra_name)) { 52662306a36Sopenharmony_ci pr_warn("Failed to parse ESSIV cipher name from skcipher cra_name\n"); 52762306a36Sopenharmony_ci err = -EINVAL; 52862306a36Sopenharmony_ci goto out_drop_skcipher; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci /* Synchronous hash, e.g., "sha256" */ 53262306a36Sopenharmony_ci _hash_alg = crypto_alg_mod_lookup(shash_name, 53362306a36Sopenharmony_ci CRYPTO_ALG_TYPE_SHASH, 53462306a36Sopenharmony_ci CRYPTO_ALG_TYPE_MASK | mask); 53562306a36Sopenharmony_ci if (IS_ERR(_hash_alg)) { 53662306a36Sopenharmony_ci err = PTR_ERR(_hash_alg); 53762306a36Sopenharmony_ci goto out_drop_skcipher; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci hash_alg = __crypto_shash_alg(_hash_alg); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* Check the set of algorithms */ 54262306a36Sopenharmony_ci if (!essiv_supported_algorithms(ictx->essiv_cipher_name, hash_alg, 54362306a36Sopenharmony_ci ivsize)) { 54462306a36Sopenharmony_ci pr_warn("Unsupported essiv instantiation: essiv(%s,%s)\n", 54562306a36Sopenharmony_ci block_base->cra_name, hash_alg->base.cra_name); 54662306a36Sopenharmony_ci err = -EINVAL; 54762306a36Sopenharmony_ci goto out_free_hash; 54862306a36Sopenharmony_ci } 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* record the driver name so we can instantiate this exact algo later */ 55162306a36Sopenharmony_ci strscpy(ictx->shash_driver_name, hash_alg->base.cra_driver_name, 55262306a36Sopenharmony_ci CRYPTO_MAX_ALG_NAME); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* Instance fields */ 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci err = -ENAMETOOLONG; 55762306a36Sopenharmony_ci if (snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, 55862306a36Sopenharmony_ci "essiv(%s,%s)", block_base->cra_name, 55962306a36Sopenharmony_ci hash_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME) 56062306a36Sopenharmony_ci goto out_free_hash; 56162306a36Sopenharmony_ci if (snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, 56262306a36Sopenharmony_ci "essiv(%s,%s)", block_base->cra_driver_name, 56362306a36Sopenharmony_ci hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 56462306a36Sopenharmony_ci goto out_free_hash; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci /* 56762306a36Sopenharmony_ci * hash_alg wasn't gotten via crypto_grab*(), so we need to inherit its 56862306a36Sopenharmony_ci * flags manually. 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_ci base->cra_flags |= (hash_alg->base.cra_flags & 57162306a36Sopenharmony_ci CRYPTO_ALG_INHERITED_FLAGS); 57262306a36Sopenharmony_ci base->cra_blocksize = block_base->cra_blocksize; 57362306a36Sopenharmony_ci base->cra_ctxsize = sizeof(struct essiv_tfm_ctx); 57462306a36Sopenharmony_ci base->cra_alignmask = block_base->cra_alignmask; 57562306a36Sopenharmony_ci base->cra_priority = block_base->cra_priority; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci if (type == CRYPTO_ALG_TYPE_SKCIPHER) { 57862306a36Sopenharmony_ci skcipher_inst->alg.setkey = essiv_skcipher_setkey; 57962306a36Sopenharmony_ci skcipher_inst->alg.encrypt = essiv_skcipher_encrypt; 58062306a36Sopenharmony_ci skcipher_inst->alg.decrypt = essiv_skcipher_decrypt; 58162306a36Sopenharmony_ci skcipher_inst->alg.init = essiv_skcipher_init_tfm; 58262306a36Sopenharmony_ci skcipher_inst->alg.exit = essiv_skcipher_exit_tfm; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci skcipher_inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(skcipher_alg); 58562306a36Sopenharmony_ci skcipher_inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(skcipher_alg); 58662306a36Sopenharmony_ci skcipher_inst->alg.ivsize = ivsize; 58762306a36Sopenharmony_ci skcipher_inst->alg.chunksize = crypto_skcipher_alg_chunksize(skcipher_alg); 58862306a36Sopenharmony_ci skcipher_inst->alg.walksize = crypto_skcipher_alg_walksize(skcipher_alg); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci skcipher_inst->free = essiv_skcipher_free_instance; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci err = skcipher_register_instance(tmpl, skcipher_inst); 59362306a36Sopenharmony_ci } else { 59462306a36Sopenharmony_ci aead_inst->alg.setkey = essiv_aead_setkey; 59562306a36Sopenharmony_ci aead_inst->alg.setauthsize = essiv_aead_setauthsize; 59662306a36Sopenharmony_ci aead_inst->alg.encrypt = essiv_aead_encrypt; 59762306a36Sopenharmony_ci aead_inst->alg.decrypt = essiv_aead_decrypt; 59862306a36Sopenharmony_ci aead_inst->alg.init = essiv_aead_init_tfm; 59962306a36Sopenharmony_ci aead_inst->alg.exit = essiv_aead_exit_tfm; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci aead_inst->alg.ivsize = ivsize; 60262306a36Sopenharmony_ci aead_inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(aead_alg); 60362306a36Sopenharmony_ci aead_inst->alg.chunksize = crypto_aead_alg_chunksize(aead_alg); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci aead_inst->free = essiv_aead_free_instance; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci err = aead_register_instance(tmpl, aead_inst); 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (err) 61162306a36Sopenharmony_ci goto out_free_hash; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci crypto_mod_put(_hash_alg); 61462306a36Sopenharmony_ci return 0; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ciout_free_hash: 61762306a36Sopenharmony_ci crypto_mod_put(_hash_alg); 61862306a36Sopenharmony_ciout_drop_skcipher: 61962306a36Sopenharmony_ci if (type == CRYPTO_ALG_TYPE_SKCIPHER) 62062306a36Sopenharmony_ci crypto_drop_skcipher(&ictx->u.skcipher_spawn); 62162306a36Sopenharmony_ci else 62262306a36Sopenharmony_ci crypto_drop_aead(&ictx->u.aead_spawn); 62362306a36Sopenharmony_ciout_free_inst: 62462306a36Sopenharmony_ci kfree(skcipher_inst); 62562306a36Sopenharmony_ci kfree(aead_inst); 62662306a36Sopenharmony_ci return err; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci/* essiv(cipher_name, shash_name) */ 63062306a36Sopenharmony_cistatic struct crypto_template essiv_tmpl = { 63162306a36Sopenharmony_ci .name = "essiv", 63262306a36Sopenharmony_ci .create = essiv_create, 63362306a36Sopenharmony_ci .module = THIS_MODULE, 63462306a36Sopenharmony_ci}; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic int __init essiv_module_init(void) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci return crypto_register_template(&essiv_tmpl); 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic void __exit essiv_module_exit(void) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci crypto_unregister_template(&essiv_tmpl); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cisubsys_initcall(essiv_module_init); 64762306a36Sopenharmony_cimodule_exit(essiv_module_exit); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ciMODULE_DESCRIPTION("ESSIV skcipher/aead wrapper for block encryption"); 65062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 65162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("essiv"); 65262306a36Sopenharmony_ciMODULE_IMPORT_NS(CRYPTO_INTERNAL); 653