Skip to content

Commit

Permalink
crypto: aead - prevent using AEADs without setting key
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eric Biggers authored and Herbert Xu committed Jan 12, 2018
1 parent f8d33fa commit dc26c17
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 11 deletions.
13 changes: 11 additions & 2 deletions crypto/aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,18 @@ int crypto_aead_setkey(struct crypto_aead *tfm,
const u8 *key, unsigned int keylen)
{
unsigned long alignmask = crypto_aead_alignmask(tfm);
int err;

if ((unsigned long)key & alignmask)
return setkey_unaligned(tfm, key, keylen);
err = setkey_unaligned(tfm, key, keylen);
else
err = crypto_aead_alg(tfm)->setkey(tfm, key, keylen);

if (err)
return err;

return crypto_aead_alg(tfm)->setkey(tfm, key, keylen);
crypto_aead_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
return 0;
}
EXPORT_SYMBOL_GPL(crypto_aead_setkey);

Expand Down Expand Up @@ -93,6 +100,8 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
struct crypto_aead *aead = __crypto_aead_cast(tfm);
struct aead_alg *alg = crypto_aead_alg(aead);

crypto_aead_set_flags(aead, CRYPTO_TFM_NEED_KEY);

aead->authsize = alg->maxauthsize;

if (alg->exit)
Expand Down
11 changes: 3 additions & 8 deletions crypto/algif_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@

struct aead_tfm {
struct crypto_aead *aead;
bool has_key;
struct crypto_skcipher *null_tfm;
};

Expand Down Expand Up @@ -398,7 +397,7 @@ static int aead_check_key(struct socket *sock)

err = -ENOKEY;
lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
if (!tfm->has_key)
if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
goto unlock;

if (!pask->refcnt++)
Expand Down Expand Up @@ -523,12 +522,8 @@ static int aead_setauthsize(void *private, unsigned int authsize)
static int aead_setkey(void *private, const u8 *key, unsigned int keylen)
{
struct aead_tfm *tfm = private;
int err;

err = crypto_aead_setkey(tfm->aead, key, keylen);
tfm->has_key = !err;

return err;
return crypto_aead_setkey(tfm->aead, key, keylen);
}

static void aead_sock_destruct(struct sock *sk)
Expand Down Expand Up @@ -589,7 +584,7 @@ static int aead_accept_parent(void *private, struct sock *sk)
{
struct aead_tfm *tfm = private;

if (!tfm->has_key)
if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY;

return aead_accept_parent_nokey(private, sk);
Expand Down
10 changes: 9 additions & 1 deletion include/crypto/aead.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,12 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
*/
static inline int crypto_aead_encrypt(struct aead_request *req)
{
return crypto_aead_alg(crypto_aead_reqtfm(req))->encrypt(req);
struct crypto_aead *aead = crypto_aead_reqtfm(req);

if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY;

return crypto_aead_alg(aead)->encrypt(req);
}

/**
Expand Down Expand Up @@ -356,6 +361,9 @@ static inline int crypto_aead_decrypt(struct aead_request *req)
{
struct crypto_aead *aead = crypto_aead_reqtfm(req);

if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY;

if (req->cryptlen < crypto_aead_authsize(aead))
return -EINVAL;

Expand Down

0 comments on commit dc26c17

Please sign in to comment.