Commit 03882e04 authored by James Morris's avatar James Morris

[CRYPTO]: Cleanups and more consistency checks.

- Removed local_bh_disable() from kmap wrapper, not needed now with
two atomic kmaps.
- Nuked atomic flag, use in_softirq() instead.
- Converted crypto_kmap() and crypto_yield() to check in_softirq().
- Check CRYPTO_MAX_CIPHER_BLOCK_SIZE during alg init.
- Try to initialize as much at compile time as possible
(feedback from Christoph Hellwig).
- Clean up list handling a bit (feedback from Christoph Hellwig).
parent 3ba6853f
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "internal.h" #include "internal.h"
static LIST_HEAD(crypto_alg_list); static LIST_HEAD(crypto_alg_list);
static struct rw_semaphore crypto_alg_sem; static DECLARE_RWSEM(crypto_alg_sem);
static inline int crypto_alg_get(struct crypto_alg *alg) static inline int crypto_alg_get(struct crypto_alg *alg)
{ {
...@@ -38,17 +38,12 @@ static inline void crypto_alg_put(struct crypto_alg *alg) ...@@ -38,17 +38,12 @@ static inline void crypto_alg_put(struct crypto_alg *alg)
struct crypto_alg *crypto_alg_lookup(char *name) struct crypto_alg *crypto_alg_lookup(char *name)
{ {
struct list_head *p; struct crypto_alg *q, *alg = NULL;
struct crypto_alg *alg = NULL;
down_read(&crypto_alg_sem); down_read(&crypto_alg_sem);
list_for_each(p, &crypto_alg_list) { list_for_each_entry(q, &crypto_alg_list, cra_list) {
struct crypto_alg *q =
list_entry(p, struct crypto_alg, cra_list);
if (!(strcmp(q->cra_name, name))) { if (!(strcmp(q->cra_name, name))) {
if (crypto_alg_get(q)) if (crypto_alg_get(q))
alg = q; alg = q;
break; break;
...@@ -63,9 +58,6 @@ static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) ...@@ -63,9 +58,6 @@ static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
{ {
tfm->crt_flags = 0; tfm->crt_flags = 0;
if (flags & CRYPTO_TFM_REQ_ATOMIC)
tfm->crt_flags |= CRYPTO_TFM_REQ_ATOMIC;
switch (crypto_tfm_alg_type(tfm)) { switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER: case CRYPTO_ALG_TYPE_CIPHER:
return crypto_init_cipher_flags(tfm, flags); return crypto_init_cipher_flags(tfm, flags);
...@@ -164,22 +156,34 @@ void crypto_free_tfm(struct crypto_tfm *tfm) ...@@ -164,22 +156,34 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
kfree(tfm); kfree(tfm);
} }
static inline int crypto_alg_blocksize_check(struct crypto_alg *alg)
{
return ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK)
== CRYPTO_ALG_TYPE_CIPHER &&
alg->cra_blocksize > CRYPTO_MAX_CIPHER_BLOCK_SIZE);
}
int crypto_register_alg(struct crypto_alg *alg) int crypto_register_alg(struct crypto_alg *alg)
{ {
int ret = 0; int ret = 0;
struct list_head *p; struct crypto_alg *q;
down_write(&crypto_alg_sem); down_write(&crypto_alg_sem);
list_for_each(p, &crypto_alg_list) { list_for_each_entry(q, &crypto_alg_list, cra_list) {
struct crypto_alg *q =
list_entry(p, struct crypto_alg, cra_list);
if (!(strcmp(q->cra_name, alg->cra_name))) { if (!(strcmp(q->cra_name, alg->cra_name))) {
ret = -EEXIST; ret = -EEXIST;
goto out; goto out;
} }
} }
if (crypto_alg_blocksize_check(alg)) {
printk(KERN_WARNING "%s: blocksize %Zd exceeds max. "
"size %Zd\n", __FUNCTION__, alg->cra_blocksize,
CRYPTO_MAX_CIPHER_BLOCK_SIZE);
ret = -EINVAL;
}
else
list_add_tail(&alg->cra_list, &crypto_alg_list); list_add_tail(&alg->cra_list, &crypto_alg_list);
out: out:
up_write(&crypto_alg_sem); up_write(&crypto_alg_sem);
...@@ -189,14 +193,14 @@ int crypto_register_alg(struct crypto_alg *alg) ...@@ -189,14 +193,14 @@ int crypto_register_alg(struct crypto_alg *alg)
int crypto_unregister_alg(struct crypto_alg *alg) int crypto_unregister_alg(struct crypto_alg *alg)
{ {
int ret = -ENOENT; int ret = -ENOENT;
struct list_head *p; struct crypto_alg *q;
BUG_ON(!alg->cra_module); BUG_ON(!alg->cra_module);
down_write(&crypto_alg_sem); down_write(&crypto_alg_sem);
list_for_each(p, &crypto_alg_list) { list_for_each_entry(q, &crypto_alg_list, cra_list) {
if (alg == (void *)p) { if (alg == q) {
list_del(p); list_del(&alg->cra_list);
ret = 0; ret = 0;
goto out; goto out;
} }
...@@ -282,7 +286,6 @@ static int __init init_crypto(void) ...@@ -282,7 +286,6 @@ static int __init init_crypto(void)
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
printk(KERN_INFO "Initializing Cryptographic API\n"); printk(KERN_INFO "Initializing Cryptographic API\n");
init_rwsem(&crypto_alg_sem);
proc = create_proc_entry("crypto", 0, NULL); proc = create_proc_entry("crypto", 0, NULL);
if (proc) if (proc)
proc->proc_fops = &proc_crypto_ops; proc->proc_fops = &proc_crypto_ops;
......
...@@ -71,14 +71,14 @@ static int copy_chunks(struct crypto_tfm *tfm, u8 *buf, ...@@ -71,14 +71,14 @@ static int copy_chunks(struct crypto_tfm *tfm, u8 *buf,
clen = rlen; clen = rlen;
} }
p = crypto_kmap(tfm, sg[i].page) + sg[i].offset + coff; p = crypto_kmap(sg[i].page) + sg[i].offset + coff;
if (in) if (in)
memcpy(&buf[copied], p, clen); memcpy(&buf[copied], p, clen);
else else
memcpy(p, &buf[copied], clen); memcpy(p, &buf[copied], clen);
crypto_kunmap(tfm, p); crypto_kunmap(p);
*last = aligned ? 0 : clen; *last = aligned ? 0 : clen;
copied += clen; copied += clen;
} }
...@@ -118,7 +118,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, ...@@ -118,7 +118,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
{ {
int i, coff; int i, coff;
size_t bsize = crypto_tfm_alg_blocksize(tfm); size_t bsize = crypto_tfm_alg_blocksize(tfm);
u8 tmp[CRYPTO_MAX_BLOCK_SIZE]; u8 tmp[CRYPTO_MAX_CIPHER_BLOCK_SIZE];
if (sglen(sg, nsg) % bsize) { if (sglen(sg, nsg) % bsize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
...@@ -128,11 +128,11 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, ...@@ -128,11 +128,11 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
for (i = 0, coff = 0; i < nsg; i++) { for (i = 0, coff = 0; i < nsg; i++) {
int n = 0, boff = 0; int n = 0, boff = 0;
int len = sg[i].length - coff; int len = sg[i].length - coff;
char *p = crypto_kmap(tfm, sg[i].page) + sg[i].offset + coff; char *p = crypto_kmap(sg[i].page) + sg[i].offset + coff;
while (len) { while (len) {
if (len < bsize) { if (len < bsize) {
crypto_kunmap(tfm, p); crypto_kunmap(p);
n = gather_chunks(tfm, tmp, sg, i, len, &coff); n = gather_chunks(tfm, tmp, sg, i, len, &coff);
prfn(tfm, tmp, crfn, enc); prfn(tfm, tmp, crfn, enc);
scatter_chunks(tfm, tmp, sg, i, len, &coff); scatter_chunks(tfm, tmp, sg, i, len, &coff);
...@@ -140,12 +140,12 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, ...@@ -140,12 +140,12 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
goto unmapped; goto unmapped;
} else { } else {
prfn(tfm, p, crfn, enc); prfn(tfm, p, crfn, enc);
crypto_kunmap(tfm, p); crypto_kunmap(p);
crypto_yield(tfm); crypto_yield(tfm);
/* remap and point to recalculated offset */ /* remap and point to recalculated offset */
boff += bsize; boff += bsize;
p = crypto_kmap(tfm, sg[i].page) p = crypto_kmap(sg[i].page)
+ sg[i].offset + coff + boff; + sg[i].offset + coff + boff;
len -= bsize; len -= bsize;
...@@ -155,7 +155,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg, ...@@ -155,7 +155,7 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *sg,
coff = 0; coff = 0;
} }
} }
crypto_kunmap(tfm, p); crypto_kunmap(p);
unmapped: unmapped:
i += n; i += n;
...@@ -172,7 +172,7 @@ static void cbc_process(struct crypto_tfm *tfm, ...@@ -172,7 +172,7 @@ static void cbc_process(struct crypto_tfm *tfm,
memcpy(tfm->crt_cipher.cit_iv, block, memcpy(tfm->crt_cipher.cit_iv, block,
crypto_tfm_alg_blocksize(tfm)); crypto_tfm_alg_blocksize(tfm));
} else { } else {
u8 buf[CRYPTO_MAX_BLOCK_SIZE]; u8 buf[CRYPTO_MAX_CIPHER_BLOCK_SIZE];
fn(tfm->crt_ctx, buf, block); fn(tfm->crt_ctx, buf, block);
xor_64(buf, tfm->crt_cipher.cit_iv); xor_64(buf, tfm->crt_cipher.cit_iv);
......
...@@ -1260,6 +1260,7 @@ static struct crypto_alg des_alg = { ...@@ -1260,6 +1260,7 @@ static struct crypto_alg des_alg = {
.cra_blocksize = DES_BLOCK_SIZE, .cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des_ctx), .cra_ctxsize = sizeof(struct des_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(des_alg.cra_list),
.cra_u = { .cipher = { .cra_u = { .cipher = {
.cia_keysize = DES_KEY_SIZE, .cia_keysize = DES_KEY_SIZE,
.cia_ivsize = DES_BLOCK_SIZE, .cia_ivsize = DES_BLOCK_SIZE,
...@@ -1274,6 +1275,7 @@ static struct crypto_alg des3_ede_alg = { ...@@ -1274,6 +1275,7 @@ static struct crypto_alg des3_ede_alg = {
.cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_blocksize = DES3_EDE_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des3_ede_ctx), .cra_ctxsize = sizeof(struct des3_ede_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(des3_ede_alg.cra_list),
.cra_u = { .cipher = { .cra_u = { .cipher = {
.cia_keysize = DES3_EDE_KEY_SIZE, .cia_keysize = DES3_EDE_KEY_SIZE,
.cia_ivsize = DES3_EDE_BLOCK_SIZE, .cia_ivsize = DES3_EDE_BLOCK_SIZE,
...@@ -1286,9 +1288,6 @@ static int __init init(void) ...@@ -1286,9 +1288,6 @@ static int __init init(void)
{ {
int ret = 0; int ret = 0;
INIT_LIST_HEAD(&des_alg.cra_list);
INIT_LIST_HEAD(&des3_ede_alg.cra_list);
ret = crypto_register_alg(&des_alg); ret = crypto_register_alg(&des_alg);
if (ret < 0) if (ret < 0)
goto out; goto out;
......
...@@ -34,10 +34,10 @@ static void update(struct crypto_tfm *tfm, struct scatterlist *sg, size_t nsg) ...@@ -34,10 +34,10 @@ static void update(struct crypto_tfm *tfm, struct scatterlist *sg, size_t nsg)
int i; int i;
for (i = 0; i < nsg; i++) { for (i = 0; i < nsg; i++) {
char *p = crypto_kmap(tfm, sg[i].page) + sg[i].offset; char *p = crypto_kmap(sg[i].page) + sg[i].offset;
tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
p, sg[i].length); p, sg[i].length);
crypto_kunmap(tfm, p); crypto_kunmap(p);
crypto_yield(tfm); crypto_yield(tfm);
} }
return; return;
...@@ -57,10 +57,10 @@ static void digest(struct crypto_tfm *tfm, ...@@ -57,10 +57,10 @@ static void digest(struct crypto_tfm *tfm,
tfm->crt_digest.dit_init(tfm); tfm->crt_digest.dit_init(tfm);
for (i = 0; i < nsg; i++) { for (i = 0; i < nsg; i++) {
char *p = crypto_kmap(tfm, sg[i].page) + sg[i].offset; char *p = crypto_kmap(sg[i].page) + sg[i].offset;
tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx,
p, sg[i].length); p, sg[i].length);
crypto_kunmap(tfm, p); crypto_kunmap(p);
crypto_yield(tfm); crypto_yield(tfm);
} }
crypto_digest_final(tfm, out); crypto_digest_final(tfm, out);
......
...@@ -17,31 +17,21 @@ ...@@ -17,31 +17,21 @@
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <asm/softirq.h> #include <asm/softirq.h>
static inline void *crypto_kmap(struct crypto_tfm *tfm, struct page *page) static inline void *crypto_kmap(struct page *page)
{ {
if (tfm->crt_flags & CRYPTO_TFM_REQ_ATOMIC) { return kmap_atomic(page, in_softirq() ?
#ifdef CONFIG_HIGHMEM /* XXX: remove this after the api change */ KM_CRYPTO_SOFTIRQ : KM_CRYPTO_USER);
local_bh_disable();
#endif
return kmap_atomic(page, KM_CRYPTO_SOFTIRQ);
} else
return kmap_atomic(page, KM_CRYPTO_USER);
} }
static inline void crypto_kunmap(struct crypto_tfm *tfm, void *vaddr) static inline void crypto_kunmap(void *vaddr)
{ {
if (tfm->crt_flags & CRYPTO_TFM_REQ_ATOMIC) { return kunmap_atomic(vaddr, in_softirq() ?
kunmap_atomic(vaddr, KM_CRYPTO_SOFTIRQ); KM_CRYPTO_SOFTIRQ : KM_CRYPTO_USER);
#ifdef CONFIG_HIGHMEM /* XXX: remove this after the api change */
local_bh_enable();
#endif
} else
kunmap_atomic(vaddr, KM_CRYPTO_USER);
} }
static inline void crypto_yield(struct crypto_tfm *tfm) static inline void crypto_yield(struct crypto_tfm *tfm)
{ {
if (!(tfm->crt_flags & CRYPTO_TFM_REQ_ATOMIC)) if (!in_softirq())
cond_resched(); cond_resched();
} }
......
...@@ -226,6 +226,7 @@ static struct crypto_alg alg = { ...@@ -226,6 +226,7 @@ static struct crypto_alg alg = {
.cra_blocksize = MD4_HMAC_BLOCK_SIZE, .cra_blocksize = MD4_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct md4_ctx), .cra_ctxsize = sizeof(struct md4_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = { .cra_u = { .digest = {
.dia_digestsize = MD4_DIGEST_SIZE, .dia_digestsize = MD4_DIGEST_SIZE,
.dia_init = md4_init, .dia_init = md4_init,
...@@ -235,7 +236,6 @@ static struct crypto_alg alg = { ...@@ -235,7 +236,6 @@ static struct crypto_alg alg = {
static int __init init(void) static int __init init(void)
{ {
INIT_LIST_HEAD(&alg.cra_list);
return crypto_register_alg(&alg); return crypto_register_alg(&alg);
} }
......
...@@ -219,6 +219,7 @@ static struct crypto_alg alg = { ...@@ -219,6 +219,7 @@ static struct crypto_alg alg = {
.cra_blocksize = MD5_HMAC_BLOCK_SIZE, .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct md5_ctx), .cra_ctxsize = sizeof(struct md5_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = { .cra_u = { .digest = {
.dia_digestsize = MD5_DIGEST_SIZE, .dia_digestsize = MD5_DIGEST_SIZE,
.dia_init = md5_init, .dia_init = md5_init,
...@@ -228,7 +229,6 @@ static struct crypto_alg alg = { ...@@ -228,7 +229,6 @@ static struct crypto_alg alg = {
static int __init init(void) static int __init init(void)
{ {
INIT_LIST_HEAD(&alg.cra_list);
return crypto_register_alg(&alg); return crypto_register_alg(&alg);
} }
......
...@@ -183,6 +183,7 @@ static struct crypto_alg alg = { ...@@ -183,6 +183,7 @@ static struct crypto_alg alg = {
.cra_blocksize = SHA1_HMAC_BLOCK_SIZE, .cra_blocksize = SHA1_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha1_ctx), .cra_ctxsize = sizeof(struct sha1_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = { .cra_u = { .digest = {
.dia_digestsize = SHA1_DIGEST_SIZE, .dia_digestsize = SHA1_DIGEST_SIZE,
.dia_init = sha1_init, .dia_init = sha1_init,
...@@ -192,7 +193,6 @@ static struct crypto_alg alg = { ...@@ -192,7 +193,6 @@ static struct crypto_alg alg = {
static int __init init(void) static int __init init(void)
{ {
INIT_LIST_HEAD(&alg.cra_list);
return crypto_register_alg(&alg); return crypto_register_alg(&alg);
} }
......
...@@ -739,7 +739,7 @@ test_des(void) ...@@ -739,7 +739,7 @@ test_des(void)
*/ */
i = 7; i = 7;
key = des_tv[i].key; key = des_tv[i].key;
tfm->crt_flags = CRYPTO_TFM_REQ_ATOMIC; tfm->crt_flags = 0;
ret = crypto_cipher_setkey(tfm, key, 8); ret = crypto_cipher_setkey(tfm, key, 8);
if (ret) { if (ret) {
...@@ -985,7 +985,6 @@ test_des(void) ...@@ -985,7 +985,6 @@ test_des(void)
for (i = 0; i < DES_CBC_ENC_TEST_VECTORS; i++) { for (i = 0; i < DES_CBC_ENC_TEST_VECTORS; i++) {
printk("test %d:\n", i + 1); printk("test %d:\n", i + 1);
tfm->crt_flags |= CRYPTO_TFM_REQ_ATOMIC;
key = des_tv[i].key; key = des_tv[i].key;
ret = crypto_cipher_setkey(tfm, key, 8); ret = crypto_cipher_setkey(tfm, key, 8);
......
...@@ -37,8 +37,7 @@ ...@@ -37,8 +37,7 @@
#define CRYPTO_TFM_MODE_CFB 0x00000004 #define CRYPTO_TFM_MODE_CFB 0x00000004
#define CRYPTO_TFM_MODE_CTR 0x00000008 #define CRYPTO_TFM_MODE_CTR 0x00000008
#define CRYPTO_TFM_REQ_ATOMIC 0x00000100 #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000200
#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
...@@ -52,7 +51,7 @@ ...@@ -52,7 +51,7 @@
*/ */
#define CRYPTO_UNSPEC 0 #define CRYPTO_UNSPEC 0
#define CRYPTO_MAX_ALG_NAME 64 #define CRYPTO_MAX_ALG_NAME 64
#define CRYPTO_MAX_BLOCK_SIZE 16 #define CRYPTO_MAX_CIPHER_BLOCK_SIZE 16
struct scatterlist; struct scatterlist;
......
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