diff options
author | Eric Biggers <ebiggers@google.com> | 2018-01-03 14:16:30 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-01-12 07:03:39 -0500 |
commit | dc26c17f743aa8e4720a5fda577dde855f2e36f8 (patch) | |
tree | fcd23cb048b79d5d3a83a0901aae8289da8e46cc /crypto | |
parent | f8d33fac84806eebd2ba31a3136066eeca19255f (diff) |
crypto: aead - prevent using AEADs without setting key
Similar to what was done for the hash API, update the AEAD API to track
whether each transform has been keyed, and reject encryption/decryption
if a key is needed but one hasn't been set.
This isn't quite as important as the equivalent fix for the hash API
because AEADs always require a key, so are unlikely to be used without
one. Still, tracking the key will prevent accidental unkeyed use.
algif_aead also had to track the key anyway, so the new flag replaces
that and slightly simplifies the algif_aead implementation.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/aead.c | 13 | ||||
-rw-r--r-- | crypto/algif_aead.c | 11 |
2 files changed, 14 insertions, 10 deletions
diff --git a/crypto/aead.c b/crypto/aead.c index fe00cbd7243d..60b3bbe973e7 100644 --- a/crypto/aead.c +++ b/crypto/aead.c | |||
@@ -54,11 +54,18 @@ int crypto_aead_setkey(struct crypto_aead *tfm, | |||
54 | const u8 *key, unsigned int keylen) | 54 | const u8 *key, unsigned int keylen) |
55 | { | 55 | { |
56 | unsigned long alignmask = crypto_aead_alignmask(tfm); | 56 | unsigned long alignmask = crypto_aead_alignmask(tfm); |
57 | int err; | ||
57 | 58 | ||
58 | if ((unsigned long)key & alignmask) | 59 | if ((unsigned long)key & alignmask) |
59 | return setkey_unaligned(tfm, key, keylen); | 60 | err = setkey_unaligned(tfm, key, keylen); |
61 | else | ||
62 | err = crypto_aead_alg(tfm)->setkey(tfm, key, keylen); | ||
63 | |||
64 | if (err) | ||
65 | return err; | ||
60 | 66 | ||
61 | return crypto_aead_alg(tfm)->setkey(tfm, key, keylen); | 67 | crypto_aead_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); |
68 | return 0; | ||
62 | } | 69 | } |
63 | EXPORT_SYMBOL_GPL(crypto_aead_setkey); | 70 | EXPORT_SYMBOL_GPL(crypto_aead_setkey); |
64 | 71 | ||
@@ -93,6 +100,8 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm) | |||
93 | struct crypto_aead *aead = __crypto_aead_cast(tfm); | 100 | struct crypto_aead *aead = __crypto_aead_cast(tfm); |
94 | struct aead_alg *alg = crypto_aead_alg(aead); | 101 | struct aead_alg *alg = crypto_aead_alg(aead); |
95 | 102 | ||
103 | crypto_aead_set_flags(aead, CRYPTO_TFM_NEED_KEY); | ||
104 | |||
96 | aead->authsize = alg->maxauthsize; | 105 | aead->authsize = alg->maxauthsize; |
97 | 106 | ||
98 | if (alg->exit) | 107 | if (alg->exit) |
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index d963c8cf8a55..4b07edd5a9ff 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c | |||
@@ -42,7 +42,6 @@ | |||
42 | 42 | ||
43 | struct aead_tfm { | 43 | struct aead_tfm { |
44 | struct crypto_aead *aead; | 44 | struct crypto_aead *aead; |
45 | bool has_key; | ||
46 | struct crypto_skcipher *null_tfm; | 45 | struct crypto_skcipher *null_tfm; |
47 | }; | 46 | }; |
48 | 47 | ||
@@ -398,7 +397,7 @@ static int aead_check_key(struct socket *sock) | |||
398 | 397 | ||
399 | err = -ENOKEY; | 398 | err = -ENOKEY; |
400 | lock_sock_nested(psk, SINGLE_DEPTH_NESTING); | 399 | lock_sock_nested(psk, SINGLE_DEPTH_NESTING); |
401 | if (!tfm->has_key) | 400 | if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) |
402 | goto unlock; | 401 | goto unlock; |
403 | 402 | ||
404 | if (!pask->refcnt++) | 403 | if (!pask->refcnt++) |
@@ -523,12 +522,8 @@ static int aead_setauthsize(void *private, unsigned int authsize) | |||
523 | static int aead_setkey(void *private, const u8 *key, unsigned int keylen) | 522 | static int aead_setkey(void *private, const u8 *key, unsigned int keylen) |
524 | { | 523 | { |
525 | struct aead_tfm *tfm = private; | 524 | struct aead_tfm *tfm = private; |
526 | int err; | ||
527 | |||
528 | err = crypto_aead_setkey(tfm->aead, key, keylen); | ||
529 | tfm->has_key = !err; | ||
530 | 525 | ||
531 | return err; | 526 | return crypto_aead_setkey(tfm->aead, key, keylen); |
532 | } | 527 | } |
533 | 528 | ||
534 | static void aead_sock_destruct(struct sock *sk) | 529 | static void aead_sock_destruct(struct sock *sk) |
@@ -589,7 +584,7 @@ static int aead_accept_parent(void *private, struct sock *sk) | |||
589 | { | 584 | { |
590 | struct aead_tfm *tfm = private; | 585 | struct aead_tfm *tfm = private; |
591 | 586 | ||
592 | if (!tfm->has_key) | 587 | if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) |
593 | return -ENOKEY; | 588 | return -ENOKEY; |
594 | 589 | ||
595 | return aead_accept_parent_nokey(private, sk); | 590 | return aead_accept_parent_nokey(private, sk); |