Commit 612893c0 authored by James Morris's avatar James Morris

[CRYPTO]: Algorithm lookup API change plus bug fixes.

- API change: implemented simplest version of algorithm lookup
by name (feedback from Rusty Russell and Herbert Valerio Riedel).
- Now need to add the following line to to /etc/modules.conf for
dynamic module loading:
    alias des3_ede des
parent d02509cd
......@@ -36,7 +36,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg)
__MOD_DEC_USE_COUNT(alg->cra_module);
}
struct crypto_alg *crypto_alg_lookup(u32 algid)
struct crypto_alg *crypto_alg_lookup(char *name)
{
struct list_head *p;
struct crypto_alg *alg = NULL;
......@@ -44,10 +44,13 @@ struct crypto_alg *crypto_alg_lookup(u32 algid)
down_read(&crypto_alg_sem);
list_for_each(p, &crypto_alg_list) {
if ((((struct crypto_alg *)p)->cra_id
& CRYPTO_ALG_MASK) == algid) {
if (crypto_alg_get((struct crypto_alg *)p))
alg = (struct crypto_alg *)p;
struct crypto_alg *q =
list_entry(p, struct crypto_alg, cra_list);
if (!(strcmp(q->cra_name, name))) {
if (crypto_alg_get(q))
alg = q;
break;
}
}
......@@ -56,18 +59,43 @@ struct crypto_alg *crypto_alg_lookup(u32 algid)
return alg;
}
static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
{
tfm->crt_flags = 0;
if (flags & CRYPTO_TFM_REQ_ATOMIC)
tfm->crt_flags |= CRYPTO_TFM_REQ_ATOMIC;
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
return crypto_init_cipher_flags(tfm, flags);
case CRYPTO_ALG_TYPE_DIGEST:
return crypto_init_digest_flags(tfm, flags);
case CRYPTO_ALG_TYPE_COMP:
return crypto_init_compress_flags(tfm, flags);
default:
BUG();
}
return -EINVAL;
}
static void crypto_init_ops(struct crypto_tfm *tfm)
{
switch (crypto_tfm_type(tfm) & CRYPTO_TYPE_MASK) {
case CRYPTO_TYPE_CIPHER:
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
crypto_init_cipher_ops(tfm);
break;
case CRYPTO_TYPE_DIGEST:
case CRYPTO_ALG_TYPE_DIGEST:
crypto_init_digest_ops(tfm);
break;
case CRYPTO_TYPE_COMP:
case CRYPTO_ALG_TYPE_COMP:
crypto_init_compress_ops(tfm);
break;
......@@ -77,16 +105,16 @@ static void crypto_init_ops(struct crypto_tfm *tfm)
}
}
struct crypto_tfm *crypto_alloc_tfm(u32 id)
struct crypto_tfm *crypto_alloc_tfm(char *name, u32 flags)
{
struct crypto_tfm *tfm = NULL;
struct crypto_alg *alg;
alg = crypto_alg_lookup(id & CRYPTO_ALG_MASK);
alg = crypto_alg_lookup(name);
#ifdef CONFIG_KMOD
if (alg == NULL) {
crypto_alg_autoload(id & CRYPTO_ALG_MASK);
alg = crypto_alg_lookup(id & CRYPTO_ALG_MASK);
crypto_alg_autoload(name);
alg = crypto_alg_lookup(name);
}
#endif
if (alg == NULL)
......@@ -102,17 +130,11 @@ struct crypto_tfm *crypto_alloc_tfm(u32 id)
goto out_free_tfm;
}
if ((alg->cra_id & CRYPTO_TYPE_MASK) == CRYPTO_TYPE_CIPHER) {
if (alg->cra_cipher.cia_ivsize) {
tfm->crt_cipher.cit_iv =
kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL);
if (tfm->crt_cipher.cit_iv == NULL)
goto out_free_ctx;
}
tfm->crt_cipher.cit_mode = id & CRYPTO_MODE_MASK;
}
tfm->__crt_alg = alg;
if (crypto_init_flags(tfm, flags))
goto out_free_ctx;
crypto_init_ops(tfm);
goto out;
......@@ -134,8 +156,8 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
if (tfm->__crt_alg->cra_ctxsize)
kfree(tfm->crt_ctx);
if (crypto_tfm_type(tfm) == CRYPTO_TYPE_CIPHER)
if (tfm->__crt_alg->cra_cipher.cia_ivsize)
if (crypto_tfm_alg_type(tfm) == CRYPTO_ALG_TYPE_CIPHER)
if (tfm->crt_cipher.cit_iv)
kfree(tfm->crt_cipher.cit_iv);
crypto_alg_put(tfm->__crt_alg);
......@@ -150,9 +172,10 @@ int crypto_register_alg(struct crypto_alg *alg)
down_write(&crypto_alg_sem);
list_for_each(p, &crypto_alg_list) {
struct crypto_alg *q = (struct crypto_alg *)p;
struct crypto_alg *q =
list_entry(p, struct crypto_alg, cra_list);
if (q->cra_id == alg->cra_id) {
if (!(strcmp(q->cra_name, alg->cra_name))) {
ret = -EEXIST;
goto out;
}
......@@ -172,7 +195,7 @@ int crypto_unregister_alg(struct crypto_alg *alg)
down_write(&crypto_alg_sem);
list_for_each(p, &crypto_alg_list) {
if (alg == (struct crypto_alg *)p) {
if (alg == (void *)p) {
list_del(p);
ret = 0;
goto out;
......@@ -215,16 +238,17 @@ static int c_show(struct seq_file *m, void *p)
struct crypto_alg *alg = (struct crypto_alg *)p;
seq_printf(m, "name : %s\n", alg->cra_name);
seq_printf(m, "id : 0x%08x\n", alg->cra_id);
seq_printf(m, "module : %s\n", alg->cra_module ?
alg->cra_module->name : "[static]");
seq_printf(m, "blocksize : %Zd\n", alg->cra_blocksize);
switch (alg->cra_id & CRYPTO_TYPE_MASK) {
case CRYPTO_TYPE_CIPHER:
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
case CRYPTO_ALG_TYPE_CIPHER:
seq_printf(m, "keysize : %Zd\n", alg->cra_cipher.cia_keysize);
seq_printf(m, "ivsize : %Zd\n", alg->cra_cipher.cia_ivsize);
break;
case CRYPTO_TYPE_DIGEST:
case CRYPTO_ALG_TYPE_DIGEST:
seq_printf(m, "digestsize : %Zd\n",
alg->cra_digest.dia_digestsize);
break;
......
......@@ -15,31 +15,17 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/crypto.h>
#include "internal.h"
static struct {
u32 algid;
char *name;
} alg_modmap[] = {
{ CRYPTO_ALG_DES, "des" },
{ CRYPTO_ALG_DES3_EDE, "des" },
{ CRYPTO_ALG_MD4, "md4" },
{ CRYPTO_ALG_MD5, "md5" },
{ CRYPTO_ALG_SHA1, "sha1" },
};
#define ALG_MAX_MODMAP 5
void crypto_alg_autoload(u32 algid)
/*
* A far more intelligent version of this is planned. For now, just
* try an exact match on the name of the algorithm.
*/
void crypto_alg_autoload(char *name)
{
int i;
for (i = 0; i < ALG_MAX_MODMAP ; i++) {
if ((alg_modmap[i].algid & CRYPTO_ALG_MASK) == algid) {
request_module(alg_modmap[i].name);
break;
}
}
request_module(name);
return;
}
......@@ -15,7 +15,9 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/highmem.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
......@@ -50,7 +52,7 @@ static int copy_chunks(struct crypto_tfm *tfm, u8 *buf,
int rlen, int *last, int in)
{
int i, copied, coff, j, aligned;
size_t bsize = crypto_tfm_blocksize(tfm);
size_t bsize = crypto_tfm_alg_blocksize(tfm);
for (i = sgidx, j = copied = 0, aligned = 0 ; copied < bsize; i++) {
int len = sg[i].length;
......@@ -115,11 +117,11 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
size_t nsg, cryptfn_t crfn, procfn_t prfn, int enc)
{
int i, coff;
size_t bsize = crypto_tfm_blocksize(tfm);
size_t bsize = crypto_tfm_alg_blocksize(tfm);
u8 tmp[CRYPTO_MAX_BLOCK_SIZE];
if (sglen(sg, nsg) % bsize) {
tfm->crt_flags |= CRYPTO_BAD_BLOCK_LEN;
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
return -EINVAL;
}
......@@ -168,15 +170,15 @@ static void cbc_process(struct crypto_tfm *tfm,
xor_64(tfm->crt_cipher.cit_iv, block);
fn(tfm->crt_ctx, block, tfm->crt_cipher.cit_iv);
memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_blocksize(tfm));
crypto_tfm_alg_blocksize(tfm));
} else {
u8 buf[CRYPTO_MAX_BLOCK_SIZE];
fn(tfm->crt_ctx, buf, block);
xor_64(buf, tfm->crt_cipher.cit_iv);
memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_blocksize(tfm));
memcpy(block, buf, crypto_tfm_blocksize(tfm));
crypto_tfm_alg_blocksize(tfm));
memcpy(block, buf, crypto_tfm_alg_blocksize(tfm));
}
}
......@@ -225,6 +227,27 @@ static int nocrypt(struct crypto_tfm *tfm, struct scatterlist *sg, size_t nsg)
return -ENOSYS;
}
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
{
struct crypto_alg *alg = tfm->__crt_alg;
u32 mode = flags & CRYPTO_TFM_MODE_MASK;
tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
if (alg->cra_cipher.cia_ivsize && mode != CRYPTO_TFM_MODE_ECB) {
tfm->crt_cipher.cit_iv =
kmalloc(alg->cra_cipher.cia_ivsize, GFP_KERNEL);
if (tfm->crt_cipher.cit_iv == NULL)
return -ENOMEM;
} else
tfm->crt_cipher.cit_iv = NULL;
if (flags & CRYPTO_TFM_REQ_WEAK_KEY)
tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY;
return 0;
}
void crypto_init_cipher_ops(struct crypto_tfm *tfm)
{
struct cipher_tfm *ops = &tfm->crt_cipher;
......@@ -232,22 +255,22 @@ void crypto_init_cipher_ops(struct crypto_tfm *tfm)
ops->cit_setkey = setkey;
switch (tfm->crt_cipher.cit_mode) {
case CRYPTO_MODE_ECB:
case CRYPTO_TFM_MODE_ECB:
ops->cit_encrypt = ecb_encrypt;
ops->cit_decrypt = ecb_decrypt;
break;
case CRYPTO_MODE_CBC:
case CRYPTO_TFM_MODE_CBC:
ops->cit_encrypt = cbc_encrypt;
ops->cit_decrypt = cbc_decrypt;
break;
case CRYPTO_MODE_CFB:
case CRYPTO_TFM_MODE_CFB:
ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt;
break;
case CRYPTO_MODE_CTR:
case CRYPTO_TFM_MODE_CTR:
ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt;
break;
......
......@@ -13,6 +13,8 @@
*/
#include <linux/types.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <asm/scatterlist.h>
#include <linux/string.h>
#include <linux/crypto.h>
......@@ -32,6 +34,11 @@ static void crypto_decompress(struct crypto_tfm *tfm)
return;
}
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
{
return crypto_cipher_flags(flags) ? -EINVAL : 0;
}
void crypto_init_compress_ops(struct crypto_tfm *tfm)
{
struct compress_tfm *ops = &tfm->crt_compress;
......
......@@ -1036,7 +1036,7 @@ static int setkey(u32 *expkey, const u8 *key, size_t keylen, int *flags)
u8 bits0[56], bits1[56];
if (keylen != DES_KEY_SIZE) {
*flags |= CRYPTO_BAD_KEY_LEN;
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
......@@ -1050,7 +1050,7 @@ static int setkey(u32 *expkey, const u8 *key, size_t keylen, int *flags)
n |= parity[key[7]];
w = 0x88888888L;
if ((*flags & CRYPTO_WEAK_KEY_CHECK)
if ((*flags & CRYPTO_TFM_REQ_WEAK_KEY)
&& !((n - (w >> 3)) & w)) { /* 1 in 10^10 keys passes this test */
if (n < 0x41415151) {
if (n < 0x31312121) {
......@@ -1108,7 +1108,7 @@ static int setkey(u32 *expkey, const u8 *key, size_t keylen, int *flags)
goto not_weak;
weak:
*flags |= CRYPTO_WEAK_KEY;
*flags |= CRYPTO_TFM_RES_WEAK_KEY;
return -EINVAL;
}
......@@ -1211,7 +1211,7 @@ static int des3_ede_setkey(void *ctx, const u8 *key, size_t keylen, int *flags)
struct des3_ede_ctx *dctx = ctx;
if (keylen != DES3_EDE_KEY_SIZE) {
*flags |= CRYPTO_BAD_KEY_LEN;
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
......@@ -1219,7 +1219,7 @@ static int des3_ede_setkey(void *ctx, const u8 *key, size_t keylen, int *flags)
memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
DES_KEY_SIZE))) {
*flags |= CRYPTO_BAD_KEY_SCHED;
*flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
return -EINVAL;
}
......@@ -1255,8 +1255,8 @@ static void des3_ede_decrypt(void *ctx, u8 *dst, u8 *src)
}
static struct crypto_alg des_alg = {
.cra_id = CRYPTO_ALG_DES,
.cra_name = "des",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des_ctx),
.cra_module = THIS_MODULE,
......@@ -1269,8 +1269,8 @@ static struct crypto_alg des_alg = {
};
static struct crypto_alg des3_ede_alg = {
.cra_id = CRYPTO_ALG_DES3_EDE,
.cra_name = "des3_ede",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = DES3_EDE_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des3_ede_ctx),
.cra_module = THIS_MODULE,
......
......@@ -16,6 +16,7 @@
*/
#include <linux/types.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <asm/scatterlist.h>
......@@ -71,15 +72,15 @@ static void hmac(struct crypto_tfm *tfm, u8 *key, size_t keylen,
{
int i;
struct scatterlist tmp;
char ipad[crypto_tfm_blocksize(tfm) + 1];
char opad[crypto_tfm_blocksize(tfm) + 1];
char ipad[crypto_tfm_alg_blocksize(tfm) + 1];
char opad[crypto_tfm_alg_blocksize(tfm) + 1];
if (keylen > crypto_tfm_blocksize(tfm)) {
if (keylen > crypto_tfm_alg_blocksize(tfm)) {
tmp.page = virt_to_page(key);
tmp.offset = ((long)key & ~PAGE_MASK);
tmp.length = keylen;
crypto_digest_digest(tfm, &tmp, 1, key);
keylen = crypto_tfm_digestsize(tfm);
keylen = crypto_tfm_alg_digestsize(tfm);
}
memset(ipad, 0, sizeof(ipad));
......@@ -87,14 +88,14 @@ static void hmac(struct crypto_tfm *tfm, u8 *key, size_t keylen,
memcpy(ipad, key, keylen);
memcpy(opad, key, keylen);
for (i = 0; i < crypto_tfm_blocksize(tfm); i++) {
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) {
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
tmp.page = virt_to_page(ipad);
tmp.offset = ((long)ipad & ~PAGE_MASK);
tmp.length = crypto_tfm_blocksize(tfm);
tmp.length = crypto_tfm_alg_blocksize(tfm);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &tmp, 1);
......@@ -103,20 +104,25 @@ static void hmac(struct crypto_tfm *tfm, u8 *key, size_t keylen,
tmp.page = virt_to_page(opad);
tmp.offset = ((long)opad & ~PAGE_MASK);
tmp.length = crypto_tfm_blocksize(tfm);
tmp.length = crypto_tfm_alg_blocksize(tfm);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &tmp, 1);
tmp.page = virt_to_page(out);
tmp.offset = ((long)out & ~PAGE_MASK);
tmp.length = crypto_tfm_digestsize(tfm);
tmp.length = crypto_tfm_alg_digestsize(tfm);
crypto_digest_update(tfm, &tmp, 1);
crypto_digest_final(tfm, out);
return;
}
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
{
return crypto_cipher_flags(flags) ? -EINVAL : 0;
}
void crypto_init_digest_ops(struct crypto_tfm *tfm)
{
struct digest_tfm *ops = &tfm->crt_digest;
......
......@@ -19,8 +19,8 @@
static inline void *crypto_kmap(struct crypto_tfm *tfm, struct page *page)
{
if (tfm->crt_flags & CRYPTO_ATOMIC) {
#ifdef CONFIG_HIGHMEM
if (tfm->crt_flags & CRYPTO_TFM_REQ_ATOMIC) {
#ifdef CONFIG_HIGHMEM /* XXX: remove this after the api change */
local_bh_disable();
#endif
return kmap_atomic(page, KM_CRYPTO_SOFTIRQ);
......@@ -30,9 +30,9 @@ static inline void *crypto_kmap(struct crypto_tfm *tfm, struct page *page)
static inline void crypto_kunmap(struct crypto_tfm *tfm, void *vaddr)
{
if (tfm->crt_flags & CRYPTO_ATOMIC) {
if (tfm->crt_flags & CRYPTO_TFM_REQ_ATOMIC) {
kunmap_atomic(vaddr, KM_CRYPTO_SOFTIRQ);
#ifdef CONFIG_HIGHMEM
#ifdef CONFIG_HIGHMEM /* XXX: remove this after the api change */
local_bh_enable();
#endif
} else
......@@ -41,14 +41,23 @@ static inline void crypto_kunmap(struct crypto_tfm *tfm, void *vaddr)
static inline void crypto_yield(struct crypto_tfm *tfm)
{
if (!(tfm->crt_flags & CRYPTO_ATOMIC))
if (!(tfm->crt_flags & CRYPTO_TFM_REQ_ATOMIC))
cond_resched();
}
static inline int crypto_cipher_flags(u32 flags)
{
return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY);
}
#ifdef CONFIG_KMOD
void crypto_alg_autoload(u32 algid);
void crypto_alg_autoload(char *name);
#endif
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
void crypto_init_digest_ops(struct crypto_tfm *tfm);
void crypto_init_cipher_ops(struct crypto_tfm *tfm);
void crypto_init_compress_ops(struct crypto_tfm *tfm);
......
......@@ -221,8 +221,8 @@ static void md4_final(void *ctx, u8 *out)
}
static struct crypto_alg alg = {
.cra_id = CRYPTO_ALG_MD4,
.cra_name = "md4",
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = MD4_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct md4_ctx),
.cra_module = THIS_MODULE,
......
......@@ -214,8 +214,8 @@ static void md5_final(void *ctx, u8 *out)
}
static struct crypto_alg alg = {
.cra_id = CRYPTO_ALG_MD5,
.cra_name = "md5",
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct md5_ctx),
.cra_module = THIS_MODULE,
......
......@@ -178,8 +178,8 @@ static void sha1_final(void* ctx, u8 *out)
}
static struct crypto_alg alg = {
.cra_id = CRYPTO_ALG_SHA1,
.cra_name = "sha1",
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = SHA1_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha1_ctx),
.cra_module = THIS_MODULE,
......
......@@ -76,9 +76,9 @@ static void test_md5(void)
memcpy(tvmem, md5_tv_template, tsize);
md5_tv = (void *)tvmem;
tfm = crypto_alloc_tfm(CRYPTO_ALG_MD5);
tfm = crypto_alloc_tfm("md5", 0);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_MD5\n");
printk("failed to load transform for md5\n");
return;
}
......@@ -95,8 +95,8 @@ static void test_md5(void)
crypto_digest_update(tfm, sg, 1);
crypto_digest_final(tfm, result);
hexdump(result, crypto_tfm_digestsize(tfm));
printk("%s\n", memcmp(result, md5_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, md5_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
}
printk("\ntesting md5 across pages\n");
......@@ -118,9 +118,9 @@ static void test_md5(void)
memset(result, 0, sizeof(result));
crypto_digest_digest(tfm, sg, 2, result);
hexdump(result, crypto_tfm_digestsize(tfm));
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, md5_tv[4].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
printk("%s\n", memcmp(result, md5_tv[4].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
printk("\ntesting hmac_md5\n");
......@@ -144,8 +144,8 @@ static void test_md5(void)
crypto_digest_hmac(tfm, hmac_md5_tv[i].key, strlen(hmac_md5_tv[i].key),sg , 1, result);
hexdump(result, crypto_tfm_digestsize(tfm));
printk("%s\n", memcmp(result, hmac_md5_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, hmac_md5_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
}
printk("\ntesting hmac_md5 across pages\n");
......@@ -167,9 +167,9 @@ static void test_md5(void)
memset(result, 0, sizeof(result));
crypto_digest_hmac(tfm, hmac_md5_tv[1].key, strlen(hmac_md5_tv[1].key), sg, 2, result);
hexdump(result, crypto_tfm_digestsize(tfm));
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, hmac_md5_tv[1].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
printk("%s\n", memcmp(result, hmac_md5_tv[1].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
crypto_free_tfm(tfm);
}
......@@ -195,9 +195,9 @@ static void test_md4(void)
memcpy(tvmem, md4_tv_template, tsize);
md4_tv = (void *)tvmem;
tfm = crypto_alloc_tfm(CRYPTO_ALG_MD4);
tfm = crypto_alloc_tfm("md4", 0);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_MD4\n");
printk("failed to load transform for md4\n");
return;
}
......@@ -212,8 +212,8 @@ static void test_md4(void)
crypto_digest_digest(tfm, sg, 1, result);
hexdump(result, crypto_tfm_digestsize(tfm));
printk("%s\n", memcmp(result, md4_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, md4_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
}
crypto_free_tfm(tfm);
......@@ -241,9 +241,9 @@ static void test_sha1(void)
memcpy(tvmem, sha1_tv_template, tsize);
sha1_tv = (void *)tvmem;
tfm = crypto_alloc_tfm(CRYPTO_ALG_SHA1);
tfm = crypto_alloc_tfm("sha1", 0);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_SHA1\n");
printk("failed to load transform for sha1\n");
return;
}
......@@ -260,8 +260,8 @@ static void test_sha1(void)
crypto_digest_update(tfm, sg, 1);
crypto_digest_final(tfm, result);
hexdump(result, crypto_tfm_digestsize(tfm));
printk("%s\n", memcmp(result, sha1_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, sha1_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
}
printk("\ntesting sha1 across pages\n");
......@@ -283,8 +283,8 @@ static void test_sha1(void)
memset(result, 0, sizeof(result));
crypto_digest_digest(tfm, sg, 2, result);
hexdump(result, crypto_tfm_digestsize(tfm));
printk("%s\n", memcmp(result, sha1_tv[1].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, sha1_tv[1].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
printk("\ntesting hmac_sha1\n");
......@@ -309,7 +309,7 @@ static void test_sha1(void)
crypto_digest_hmac(tfm, hmac_sha1_tv[i].key, strlen(hmac_sha1_tv[i].key),sg , 1, result);
hexdump(result, sizeof(result));
printk("%s\n", memcmp(result, hmac_sha1_tv[i].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
printk("%s\n", memcmp(result, hmac_sha1_tv[i].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
}
printk("\ntesting hmac_sha1 across pages\n");
......@@ -332,9 +332,9 @@ static void test_sha1(void)
memset(result, 0, sizeof(result));
crypto_digest_hmac(tfm, hmac_sha1_tv[1].key, strlen(hmac_sha1_tv[1].key), sg, 2, result);
hexdump(result, crypto_tfm_digestsize(tfm));
hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n", memcmp(result, hmac_sha1_tv[1].digest, crypto_tfm_digestsize(tfm)) ? "fail" : "pass");
printk("%s\n", memcmp(result, hmac_sha1_tv[1].digest, crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass");
crypto_free_tfm(tfm);
}
......@@ -360,9 +360,9 @@ void test_des(void)
memcpy(tvmem, des_enc_tv_template, tsize);
des_tv = (void *)tvmem;
tfm = crypto_alloc_tfm(CRYPTO_ALG_DES_ECB);
tfm = crypto_alloc_tfm("des", 0);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_DES_ECB\n");
printk("failed to load transform for des (default ecb)\n");
return;
}
......@@ -370,8 +370,8 @@ void test_des(void)
printk("test %d:\n", i + 1);
key = des_tv[i].key;
tfm->crt_flags = CRYPTO_WEAK_KEY_CHECK;
tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
ret = crypto_cipher_setkey(tfm, key, 8);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
......@@ -700,7 +700,7 @@ void test_des(void)
*/
i = 7;
key = des_tv[i].key;
tfm->crt_flags = CRYPTO_ATOMIC;
tfm->crt_flags = CRYPTO_TFM_REQ_ATOMIC;
ret = crypto_cipher_setkey(tfm, key, 8);
if (ret) {
......@@ -761,7 +761,6 @@ void test_des(void)
sg[7].length = 1;
ret = crypto_cipher_encrypt(tfm, sg, 8);
if (ret) {
printk("encrypt() failed flags=%x\n", tfm->crt_flags);
goto out;
......@@ -926,9 +925,9 @@ void test_des(void)
crypto_free_tfm(tfm);
tfm = crypto_alloc_tfm(CRYPTO_ALG_DES_CBC);
tfm = crypto_alloc_tfm("des", CRYPTO_TFM_MODE_CBC);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_DES_CBC\n");
printk("failed to load transform for des cbc\n");
return;
}
......@@ -945,7 +944,7 @@ void test_des(void)
for (i = 0; i < DES_CBC_ENC_TEST_VECTORS; i++) {
printk("test %d:\n", i + 1);
tfm->crt_flags = CRYPTO_ATOMIC;
tfm->crt_flags |= CRYPTO_TFM_REQ_ATOMIC;
key = des_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, 8);
......@@ -961,7 +960,7 @@ void test_des(void)
sg[0].offset = ((long)p & ~PAGE_MASK);
sg[0].length = len;
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_ivsize(tfm));
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
ret = crypto_cipher_encrypt(tfm, sg, 1);
if (ret) {
......@@ -987,7 +986,7 @@ void test_des(void)
printk("\ntesting des cbc encryption chunking scenario F\n");
i = 4;
tfm = crypto_alloc_tfm(CRYPTO_ALG_DES_CBC);
tfm = crypto_alloc_tfm("des", CRYPTO_TFM_MODE_CBC);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_DES_CCB\n");
return;
......@@ -1018,7 +1017,7 @@ void test_des(void)
sg[1].offset = ((long)p & ~PAGE_MASK);
sg[1].length = 11;
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_ivsize(tfm));
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
ret = crypto_cipher_encrypt(tfm, sg, 2);
if (ret) {
......@@ -1066,7 +1065,7 @@ void test_des(void)
sg[0].offset = ((long)p & ~PAGE_MASK);
sg[0].length = len;
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_blocksize(tfm));
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_alg_blocksize(tfm));
ret = crypto_cipher_decrypt(tfm, sg, 1);
if (ret) {
......@@ -1116,7 +1115,7 @@ void test_des(void)
sg[1].offset = ((long)p & ~PAGE_MASK);
sg[1].length = 4;
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_ivsize(tfm));
crypto_cipher_copy_iv(tfm, des_tv[i].iv, crypto_tfm_alg_ivsize(tfm));
ret = crypto_cipher_decrypt(tfm, sg, 2);
if (ret) {
......@@ -1161,9 +1160,9 @@ void test_des3_ede(void)
memcpy(tvmem, des3_ede_enc_tv_template, tsize);
des_tv = (void *)tvmem;
tfm = crypto_alloc_tfm(CRYPTO_ALG_DES3_EDE_ECB);
tfm = crypto_alloc_tfm("des3_ede", CRYPTO_TFM_MODE_ECB);
if (tfm == NULL) {
printk("failed to load transform for CRYPTO_ALG_DES3_EDE_ECB\n");
printk("failed to load transform for 3des ecb\n");
return;
}
......@@ -1171,8 +1170,6 @@ void test_des3_ede(void)
printk("test %d:\n", i + 1);
key = des_tv[i].key;
tfm->crt_flags = CRYPTO_WEAK_KEY_CHECK;
ret = crypto_cipher_setkey(tfm, key, 24);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
......@@ -1214,8 +1211,6 @@ void test_des3_ede(void)
printk("test %d:\n", i + 1);
key = des_tv[i].key;
tfm->crt_flags = CRYPTO_WEAK_KEY_CHECK;
ret = crypto_cipher_setkey(tfm, key, 24);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
......
......@@ -16,56 +16,50 @@
#ifndef _LINUX_CRYPTO_H
#define _LINUX_CRYPTO_H
/*
* Crypto context flags.
*/
#define CRYPTO_WEAK_KEY_CHECK 0x0001
#define CRYPTO_WEAK_KEY 0x0008
#define CRYPTO_BAD_KEY_LEN 0x0010
#define CRYPTO_BAD_KEY_SCHED 0x0020
#define CRYPTO_BAD_BLOCK_LEN 0x0040
#define CRYPTO_ATOMIC 0x1000
/*
* Algorithm identifiers. These may be expanded later to 64 bits
* and include vendor id info, so we can have multiple versions
* (e.g. asm, various hardware versions etc).
*
* Todo: sadb translation.
* Algorithm masks and types.
*/
#define CRYPTO_TYPE_MASK 0xf0000000
#define CRYPTO_MODE_MASK 0x0ff00000
#define CRYPTO_ALG_MASK 0x000fffff
#define CRYPTO_ALG_TYPE_MASK 0x000000ff
#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
#define CRYPTO_ALG_TYPE_COMP 0x00000004
#define CRYPTO_TYPE_CIPHER 0x10000000
#define CRYPTO_TYPE_DIGEST 0x20000000
#define CRYPTO_TYPE_COMP 0x40000000
#define CRYPTO_MODE_ECB 0x00100000
#define CRYPTO_MODE_CBC 0x00200000
#define CRYPTO_MODE_CFB 0x00400000
#define CRYPTO_MODE_CTR 0x00800000
/*
* Transform masks and values (for crt_flags).
*/
#define CRYPTO_TFM_MODE_MASK 0x000000ff
#define CRYPTO_TFM_REQ_MASK 0x000fff00
#define CRYPTO_TFM_RES_MASK 0xfff00000
#define CRYPTO_ALG_NULL 0x00000001
#define CRYPTO_TFM_MODE_ECB 0x00000001
#define CRYPTO_TFM_MODE_CBC 0x00000002
#define CRYPTO_TFM_MODE_CFB 0x00000004
#define CRYPTO_TFM_MODE_CTR 0x00000008
#define CRYPTO_ALG_DES (0x00000002|CRYPTO_TYPE_CIPHER)
#define CRYPTO_ALG_DES_ECB (CRYPTO_ALG_DES|CRYPTO_MODE_ECB)
#define CRYPTO_ALG_DES_CBC (CRYPTO_ALG_DES|CRYPTO_MODE_CBC)
#define CRYPTO_TFM_REQ_ATOMIC 0x00000100
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000200
#define CRYPTO_ALG_DES3_EDE (0x00000003|CRYPTO_TYPE_CIPHER)
#define CRYPTO_ALG_DES3_EDE_ECB (CRYPTO_ALG_DES3_EDE|CRYPTO_MODE_ECB)
#define CRYPTO_ALG_DES3_EDE_CBC (CRYPTO_ALG_DES3_EDE|CRYPTO_MODE_CBC)
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
#define CRYPTO_ALG_MD4 (0x00000f00|CRYPTO_TYPE_DIGEST)
#define CRYPTO_ALG_MD5 (0x00000f01|CRYPTO_TYPE_DIGEST)
#define CRYPTO_ALG_SHA1 (0x00000f02|CRYPTO_TYPE_DIGEST)
#define CRYPTO_UNSPEC 0
#define CRYPTO_MAX_ALG_NAME 64
#define CRYPTO_MAX_BLOCK_SIZE 16
/*
* Miscellaneous stuff.
*/
#define CRYPTO_UNSPEC 0
#define CRYPTO_MAX_ALG_NAME 64
#define CRYPTO_MAX_BLOCK_SIZE 16
struct scatterlist;
/*
* Algorithms: modular crypto algorithm implementations, managed
* via crypto_register_alg() and crypto_unregister_alg().
*/
struct cipher_alg {
size_t cia_keysize;
size_t cia_ivsize;
......@@ -92,7 +86,7 @@ struct compress_alg {
struct crypto_alg {
struct list_head cra_list;
u32 cra_id;
int cra_flags;
size_t cra_blocksize;
size_t cra_ctxsize;
char cra_name[CRYPTO_MAX_ALG_NAME];
......@@ -112,11 +106,13 @@ struct crypto_alg {
int crypto_register_alg(struct crypto_alg *alg);
int crypto_unregister_alg(struct crypto_alg *alg);
struct crypto_tfm;
/*
* Transformations: user-instantiated algorithms.
* Transforms: user-instantiated objects which encapsulate algorithms
* and core processing logic. Managed via crypto_alloc_tfm() and
* crypto_free_tfm(), as well as the various helpers below.
*/
struct crypto_tfm;
struct cipher_tfm {
void *cit_iv;
u32 cit_mode;
......@@ -161,17 +157,61 @@ struct crypto_tfm {
struct crypto_alg *__crt_alg;
};
/*
* Transform user interface.
*/
/*
* Finds specified algorithm, allocates and returns a transform for it.
* Will try an load a module based on the name if not present
* in the kernel. Increments its algorithm refcount.
* crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
* If that fails and the kernel supports dynamically loadable modules, it
* will then attempt to load a module of the same name or alias. A refcount
* is grabbed on the algorithm which is then associated with the new transform.
*/
struct crypto_tfm *crypto_alloc_tfm(u32 id);
struct crypto_tfm *crypto_alloc_tfm(char *alg_name, u32 tfm_flags);
void crypto_free_tfm(struct crypto_tfm *tfm);
/*
* Frees the transform and decrements its algorithm's recount.
* Transform helpers which query the underlying algorithm.
*/
void crypto_free_tfm(struct crypto_tfm *tfm);
static inline char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_name;
}
static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
{
struct crypto_alg *alg = tfm->__crt_alg;
if (alg->cra_module)
return alg->cra_module->name;
else
return NULL;
}
static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
}
static inline size_t crypto_tfm_alg_keysize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_cipher.cia_keysize;
}
static inline size_t crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_cipher.cia_ivsize;
}
static inline size_t crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_blocksize;
}
static inline size_t crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_digest.dia_digestsize;
}
/*
* API wrappers.
......@@ -241,47 +281,4 @@ static inline void crypto_comp_decompress(struct crypto_tfm *tfm)
tfm->crt_compress.cot_decompress(tfm);
}
/*
* Transform helpers which allow the underlying algorithm to be queried.
*/
static inline int crypto_tfm_id(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_id;
}
static inline int crypto_tfm_alg(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_id & CRYPTO_ALG_MASK;
}
static inline char *crypto_tfm_name(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_name;
}
static inline u32 crypto_tfm_type(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_id & CRYPTO_TYPE_MASK;
}
static inline size_t crypto_tfm_keysize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_cipher.cia_keysize;
}
static inline size_t crypto_tfm_ivsize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_cipher.cia_ivsize;
}
static inline size_t crypto_tfm_blocksize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_blocksize;
}
static inline size_t crypto_tfm_digestsize(struct crypto_tfm *tfm)
{
return tfm->__crt_alg->cra_digest.dia_digestsize;
}
#endif /* _LINUX_CRYPTO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment