crypto: hash - prevent using keyed hashes without setting key
[pandora-kernel.git] / crypto / shash.c
index 0d66c2e..5441f4e 100644 (file)
@@ -57,11 +57,18 @@ int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
 {
        struct shash_alg *shash = crypto_shash_alg(tfm);
        unsigned long alignmask = crypto_shash_alignmask(tfm);
+       int err;
 
        if ((unsigned long)key & alignmask)
-               return shash_setkey_unaligned(tfm, key, keylen);
+               err = shash_setkey_unaligned(tfm, key, keylen);
+       else
+               err = shash->setkey(tfm, key, keylen);
+
+       if (err)
+               return err;
 
-       return shash->setkey(tfm, key, keylen);
+       crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(crypto_shash_setkey);
 
@@ -179,6 +186,9 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
        struct shash_alg *shash = crypto_shash_alg(tfm);
        unsigned long alignmask = crypto_shash_alignmask(tfm);
 
+       if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
+               return -ENOKEY;
+
        if (((unsigned long)data | (unsigned long)out) & alignmask)
                return shash_digest_unaligned(desc, data, len, out);
 
@@ -358,7 +368,8 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
        crt->digest = shash_async_digest;
        crt->setkey = shash_async_setkey;
 
-       crt->has_setkey = alg->setkey != shash_no_setkey;
+       crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
+                                   CRYPTO_TFM_NEED_KEY);
 
        if (alg->export)
                crt->export = shash_async_export;
@@ -518,8 +529,14 @@ static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type,
 static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
 {
        struct crypto_shash *hash = __crypto_shash_cast(tfm);
+       struct shash_alg *alg = crypto_shash_alg(hash);
+
+       hash->descsize = alg->descsize;
+
+       if (crypto_shash_alg_has_setkey(alg) &&
+           !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
+               crypto_shash_set_flags(hash, CRYPTO_TFM_NEED_KEY);
 
-       hash->descsize = crypto_shash_alg(hash)->descsize;
        return 0;
 }