Commit 5861f1be00b3b70f8ab5e5a81392a6cf69666cd2

Authored by Milan Broz
Committed by Alasdair G Kergon
1 parent 6047359277

dm crypt: restructure essiv error path

Use kzfree for salt deallocation because it is derived from the volume
key.  Use a common error path in ESSIV constructor.

Required by a later patch which fixes the way key material is wiped
from memory.

Cc: stable@kernel.org
Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 1 changed file with 26 additions and 20 deletions Side-by-side Diff

drivers/md/dm-crypt.c
... ... @@ -187,15 +187,15 @@
187 187 static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
188 188 const char *opts)
189 189 {
190   - struct crypto_cipher *essiv_tfm;
191   - struct crypto_hash *hash_tfm;
  190 + struct crypto_cipher *essiv_tfm = NULL;
  191 + struct crypto_hash *hash_tfm = NULL;
192 192 struct hash_desc desc;
193 193 struct scatterlist sg;
194 194 unsigned int saltsize;
195   - u8 *salt;
  195 + u8 *salt = NULL;
196 196 int err;
197 197  
198   - if (opts == NULL) {
  198 + if (!opts) {
199 199 ti->error = "Digest algorithm missing for ESSIV mode";
200 200 return -EINVAL;
201 201 }
202 202  
203 203  
... ... @@ -204,15 +204,16 @@
204 204 hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC);
205 205 if (IS_ERR(hash_tfm)) {
206 206 ti->error = "Error initializing ESSIV hash";
207   - return PTR_ERR(hash_tfm);
  207 + err = PTR_ERR(hash_tfm);
  208 + goto bad;
208 209 }
209 210  
210 211 saltsize = crypto_hash_digestsize(hash_tfm);
211   - salt = kmalloc(saltsize, GFP_KERNEL);
212   - if (salt == NULL) {
  212 + salt = kzalloc(saltsize, GFP_KERNEL);
  213 + if (!salt) {
213 214 ti->error = "Error kmallocing salt storage in ESSIV";
214   - crypto_free_hash(hash_tfm);
215   - return -ENOMEM;
  215 + err = -ENOMEM;
  216 + goto bad;
216 217 }
217 218  
218 219 sg_init_one(&sg, cc->key, cc->key_size);
219 220  
220 221  
221 222  
222 223  
223 224  
224 225  
... ... @@ -220,39 +221,44 @@
220 221 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
221 222 err = crypto_hash_digest(&desc, &sg, cc->key_size, salt);
222 223 crypto_free_hash(hash_tfm);
  224 + hash_tfm = NULL;
223 225  
224 226 if (err) {
225 227 ti->error = "Error calculating hash in ESSIV";
226   - kfree(salt);
227   - return err;
  228 + goto bad;
228 229 }
229 230  
230 231 /* Setup the essiv_tfm with the given salt */
231 232 essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC);
232 233 if (IS_ERR(essiv_tfm)) {
233 234 ti->error = "Error allocating crypto tfm for ESSIV";
234   - kfree(salt);
235   - return PTR_ERR(essiv_tfm);
  235 + err = PTR_ERR(essiv_tfm);
  236 + goto bad;
236 237 }
237 238 if (crypto_cipher_blocksize(essiv_tfm) !=
238 239 crypto_ablkcipher_ivsize(cc->tfm)) {
239 240 ti->error = "Block size of ESSIV cipher does "
240 241 "not match IV size of block cipher";
241   - crypto_free_cipher(essiv_tfm);
242   - kfree(salt);
243   - return -EINVAL;
  242 + err = -EINVAL;
  243 + goto bad;
244 244 }
245 245 err = crypto_cipher_setkey(essiv_tfm, salt, saltsize);
246 246 if (err) {
247 247 ti->error = "Failed to set key for ESSIV cipher";
248   - crypto_free_cipher(essiv_tfm);
249   - kfree(salt);
250   - return err;
  248 + goto bad;
251 249 }
252   - kfree(salt);
  250 + kzfree(salt);
253 251  
254 252 cc->iv_gen_private.essiv.tfm = essiv_tfm;
255 253 return 0;
  254 +
  255 +bad:
  256 + if (essiv_tfm && !IS_ERR(essiv_tfm))
  257 + crypto_free_cipher(essiv_tfm);
  258 + if (hash_tfm && !IS_ERR(hash_tfm))
  259 + crypto_free_hash(hash_tfm);
  260 + kzfree(salt);
  261 + return err;
256 262 }
257 263  
258 264 static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)