forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CRYPTO] Allow multiple implementations of the same algorithm
This is the first step on the road towards asynchronous support in the Crypto API. It adds support for having multiple crypto_alg objects for the same algorithm registered in the system. For example, each device driver would register a crypto_alg object for each algorithm that it supports. While at the same time the user may load software implementations of those same algorithms. Users of the Crypto API may then select a specific implementation by name, or choose any implementation for a given algorithm with the highest priority. The priority field is a 32-bit signed integer. In future it will be possible to modify it from user-space. This also provides a solution to the problem of selecting amongst various AES implementations, that is, aes vs. aes-i586 vs. aes-padlock. Signed-off-by: Herbert Xu <[email protected]>
- Loading branch information
Showing
4 changed files
with
60 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
* | ||
* Copyright (c) 2002 James Morris <[email protected]> | ||
* Copyright (c) 2002 David S. Miller ([email protected]) | ||
* Copyright (c) 2005 Herbert Xu <[email protected]> | ||
* | ||
* Portions derived from Cryptoapi, by Alexander Kjeldaas <[email protected]> | ||
* and Nettle, by Niels Möller. | ||
|
@@ -18,9 +19,11 @@ | |
#include <linux/init.h> | ||
#include <linux/crypto.h> | ||
#include <linux/errno.h> | ||
#include <linux/kernel.h> | ||
#include <linux/kmod.h> | ||
#include <linux/rwsem.h> | ||
#include <linux/slab.h> | ||
#include <linux/string.h> | ||
#include "internal.h" | ||
|
||
LIST_HEAD(crypto_alg_list); | ||
|
@@ -39,18 +42,31 @@ static inline void crypto_alg_put(struct crypto_alg *alg) | |
static struct crypto_alg *crypto_alg_lookup(const char *name) | ||
{ | ||
struct crypto_alg *q, *alg = NULL; | ||
int best = -1; | ||
|
||
if (!name) | ||
return NULL; | ||
|
||
down_read(&crypto_alg_sem); | ||
|
||
list_for_each_entry(q, &crypto_alg_list, cra_list) { | ||
if (!(strcmp(q->cra_name, name))) { | ||
if (crypto_alg_get(q)) | ||
alg = q; | ||
int exact, fuzzy; | ||
|
||
exact = !strcmp(q->cra_driver_name, name); | ||
fuzzy = !strcmp(q->cra_name, name); | ||
if (!exact && !(fuzzy && q->cra_priority > best)) | ||
continue; | ||
|
||
if (unlikely(!crypto_alg_get(q))) | ||
continue; | ||
|
||
best = q->cra_priority; | ||
if (alg) | ||
crypto_alg_put(alg); | ||
alg = q; | ||
|
||
if (exact) | ||
break; | ||
} | ||
} | ||
|
||
up_read(&crypto_alg_sem); | ||
|
@@ -207,9 +223,26 @@ void crypto_free_tfm(struct crypto_tfm *tfm) | |
kfree(tfm); | ||
} | ||
|
||
static inline int crypto_set_driver_name(struct crypto_alg *alg) | ||
{ | ||
static const char suffix[] = "-generic"; | ||
char *driver_name = (char *)alg->cra_driver_name; | ||
int len; | ||
|
||
if (*driver_name) | ||
return 0; | ||
|
||
len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); | ||
if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) | ||
return -ENAMETOOLONG; | ||
|
||
memcpy(driver_name + len, suffix, sizeof(suffix)); | ||
return 0; | ||
} | ||
|
||
int crypto_register_alg(struct crypto_alg *alg) | ||
{ | ||
int ret = 0; | ||
int ret; | ||
struct crypto_alg *q; | ||
|
||
if (alg->cra_alignmask & (alg->cra_alignmask + 1)) | ||
|
@@ -220,11 +253,18 @@ int crypto_register_alg(struct crypto_alg *alg) | |
|
||
if (alg->cra_blocksize > PAGE_SIZE) | ||
return -EINVAL; | ||
|
||
if (alg->cra_priority < 0) | ||
return -EINVAL; | ||
|
||
ret = crypto_set_driver_name(alg); | ||
if (unlikely(ret)) | ||
return ret; | ||
|
||
down_write(&crypto_alg_sem); | ||
|
||
list_for_each_entry(q, &crypto_alg_list, cra_list) { | ||
if (!(strcmp(q->cra_name, alg->cra_name))) { | ||
if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) { | ||
ret = -EEXIST; | ||
goto out; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
* Cryptographic API. | ||
* | ||
* Copyright (c) 2002 James Morris <[email protected]> | ||
* Copyright (c) 2005 Herbert Xu <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License as published by the Free | ||
|
@@ -16,10 +17,15 @@ | |
#include <linux/highmem.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/init.h> | ||
#include <linux/list.h> | ||
#include <linux/kernel.h> | ||
#include <linux/rwsem.h> | ||
#include <linux/slab.h> | ||
#include <asm/kmap_types.h> | ||
|
||
extern struct list_head crypto_alg_list; | ||
extern struct rw_semaphore crypto_alg_sem; | ||
|
||
extern enum km_type crypto_km_types[]; | ||
|
||
static inline enum km_type crypto_kmap_type(int out) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
* Procfs information. | ||
* | ||
* Copyright (c) 2002 James Morris <[email protected]> | ||
* Copyright (c) 2005 Herbert Xu <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License as published by the Free | ||
|
@@ -18,9 +19,6 @@ | |
#include <linux/seq_file.h> | ||
#include "internal.h" | ||
|
||
extern struct list_head crypto_alg_list; | ||
extern struct rw_semaphore crypto_alg_sem; | ||
|
||
static void *c_start(struct seq_file *m, loff_t *pos) | ||
{ | ||
struct list_head *v; | ||
|
@@ -53,7 +51,9 @@ 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, "driver : %s\n", alg->cra_driver_name); | ||
seq_printf(m, "module : %s\n", module_name(alg->cra_module)); | ||
seq_printf(m, "priority : %d\n", alg->cra_priority); | ||
|
||
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { | ||
case CRYPTO_ALG_TYPE_CIPHER: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
* | ||
* Copyright (c) 2002 James Morris <[email protected]> | ||
* Copyright (c) 2002 David S. Miller ([email protected]) | ||
* Copyright (c) 2005 Herbert Xu <[email protected]> | ||
* | ||
* Portions derived from Cryptoapi, by Alexander Kjeldaas <[email protected]> | ||
* and Nettle, by Niels Möller. | ||
|
@@ -126,7 +127,11 @@ struct crypto_alg { | |
unsigned int cra_blocksize; | ||
unsigned int cra_ctxsize; | ||
unsigned int cra_alignmask; | ||
|
||
int cra_priority; | ||
|
||
const char cra_name[CRYPTO_MAX_ALG_NAME]; | ||
const char cra_driver_name[CRYPTO_MAX_ALG_NAME]; | ||
|
||
union { | ||
struct cipher_alg cipher; | ||
|