mmu-notifiers: core
[linux-2.6.git] / crypto / aes_generic.c
index cf30af7..136dc98 100644 (file)
@@ -229,18 +229,29 @@ static void __init gen_tabs(void)
        ctx->key_enc[8 * i + 15] = t;                   \
 } while (0)
 
-int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+/**
+ * crypto_aes_expand_key - Expands the AES key as described in FIPS-197
+ * @ctx:       The location where the computed key will be stored.
+ * @in_key:    The supplied key.
+ * @key_len:   The length of the supplied key.
+ *
+ * Returns 0 on success. The function fails only if an invalid key size (or
+ * pointer) is supplied.
+ * The expanded key size is 240 bytes (max of 14 rounds with a unique 16 bytes
+ * key schedule plus a 16 bytes key which is used before the first round).
+ * The decryption key is prepared for the "Equivalent Inverse Cipher" as
+ * described in FIPS-197. The first slot (16 bytes) of each key (enc or dec) is
+ * for the initial combination, the second slot for the first round and so on.
+ */
+int crypto_aes_expand_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
                unsigned int key_len)
 {
-       struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
        const __le32 *key = (const __le32 *)in_key;
-       u32 *flags = &tfm->crt_flags;
        u32 i, t, u, v, w, j;
 
-       if (key_len % 8) {
-               *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+       if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_192 &&
+                       key_len != AES_KEYSIZE_256)
                return -EINVAL;
-       }
 
        ctx->key_length = key_len;
 
@@ -250,20 +261,20 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);
 
        switch (key_len) {
-       case 16:
+       case AES_KEYSIZE_128:
                t = ctx->key_enc[3];
                for (i = 0; i < 10; ++i)
                        loop4(i);
                break;
 
-       case 24:
+       case AES_KEYSIZE_192:
                ctx->key_enc[4] = le32_to_cpu(key[4]);
                t = ctx->key_enc[5] = le32_to_cpu(key[5]);
                for (i = 0; i < 8; ++i)
                        loop6(i);
                break;
 
-       case 32:
+       case AES_KEYSIZE_256:
                ctx->key_enc[4] = le32_to_cpu(key[4]);
                ctx->key_enc[5] = le32_to_cpu(key[5]);
                ctx->key_enc[6] = le32_to_cpu(key[6]);
@@ -284,6 +295,33 @@ int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(crypto_aes_expand_key);
+
+/**
+ * crypto_aes_set_key - Set the AES key.
+ * @tfm:       The %crypto_tfm that is used in the context.
+ * @in_key:    The input key.
+ * @key_len:   The size of the key.
+ *
+ * Returns 0 on success, on failure the %CRYPTO_TFM_RES_BAD_KEY_LEN flag in tfm
+ * is set. The function uses crypto_aes_expand_key() to expand the key.
+ * &crypto_aes_ctx _must_ be the private data embedded in @tfm which is
+ * retrieved with crypto_tfm_ctx().
+ */
+int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+               unsigned int key_len)
+{
+       struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+       u32 *flags = &tfm->crt_flags;
+       int ret;
+
+       ret = crypto_aes_expand_key(ctx, in_key, key_len);
+       if (!ret)
+               return 0;
+
+       *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+       return -EINVAL;
+}
 EXPORT_SYMBOL_GPL(crypto_aes_set_key);
 
 /* encrypt a block of text */