diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-02-19 17:01:52 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-02-19 17:01:52 +0100 |
commit | 12883105566c38cf0b0ccd2a258311435283a97b (patch) | |
tree | 6aa4865fae628c4c8674fea834f06761de27d528 | |
parent | c75d5221a2b57789916ca85fcbfcac12553d2ee6 (diff) | |
download | cryptodev-linux-12883105566c38cf0b0ccd2a258311435283a97b.tar.gz cryptodev-linux-12883105566c38cf0b0ccd2a258311435283a97b.tar.xz cryptodev-linux-12883105566c38cf0b0ccd2a258311435283a97b.zip |
Added support for asynchronous block ciphers.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cryptodev_int.h | 24 | ||||
-rw-r--r-- | cryptodev_main.c (renamed from cryptodev.c) | 99 |
3 files changed, 55 insertions, 70 deletions
@@ -1,5 +1,7 @@ KERNEL_DIR := /lib/modules/$(shell uname -r)/build +cryptodev-objs = cryptodev_main.o cryptodev_cipher.o + obj-m += cryptodev.o build: diff --git a/cryptodev_int.h b/cryptodev_int.h new file mode 100644 index 0000000..f91bea7 --- /dev/null +++ b/cryptodev_int.h @@ -0,0 +1,24 @@ +struct cipher_data +{ + int type; /* 1 synchronous, 2 async, 0 uninitialized */ + int blocksize; + int ivsize; + union { + struct { + struct crypto_blkcipher* s; + struct blkcipher_desc desc; + } blk; + struct { + struct crypto_ablkcipher* s; + struct cryptodev_result *async_result; + struct ablkcipher_request *async_request; + uint8_t iv[EALG_MAX_BLOCK_LEN]; + } ablk; + } u; +}; + +int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, __user uint8_t * key, size_t keylen); +void cryptodev_cipher_deinit(struct cipher_data* cdata); +ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len); +ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len); +void cryptodev_cipher_set_iv(struct cipher_data* cdata, void* iv, size_t iv_size); diff --git a/cryptodev.c b/cryptodev_main.c index 5d195f3..2685161 100644 --- a/cryptodev.c +++ b/cryptodev_main.c @@ -47,8 +47,9 @@ #include <asm/uaccess.h> #include <asm/ioctl.h> #include <linux/scatterlist.h> +#include "cryptodev_int.h" -MODULE_AUTHOR("Michal Ludvig <mludvig@logix.net.nz>"); +MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>"); MODULE_DESCRIPTION("CryptoDev driver"); MODULE_LICENSE("GPL"); @@ -92,7 +93,7 @@ MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage"); struct csession { struct list_head entry; struct semaphore sem; - struct crypto_blkcipher *tfm; + struct cipher_data cdata; struct crypto_hash *hash_tfm; uint32_t sid; #ifdef CRYPTODEV_STATS @@ -114,12 +115,10 @@ static int crypto_create_session(struct fcrypt *fcr, struct session_op *sop) { struct csession *ses_new, *ses_ptr; - struct crypto_blkcipher *blk_tfm=NULL; struct crypto_hash *hash_tfm=NULL; int ret = 0; const char *alg_name=NULL; const char *hash_name=NULL; - struct blkcipher_alg* blkalg; int hmac_mode = 1; /* Does the request make sense? */ @@ -204,47 +203,22 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop) return -EINVAL; } - /* Set-up crypto transform. */ - if (alg_name) { - uint8_t keyp[CRYPTO_CIPHER_MAX_KEY_LEN]; - - blk_tfm = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(blk_tfm)) { - dprintk(1,KERN_DEBUG,"%s: Failed to load transform for %s\n", __func__, - alg_name); - return -EINVAL; - } - - blkalg = crypto_blkcipher_alg(blk_tfm); - if (blkalg != NULL) { - /* Was correct key length supplied? */ - if ((sop->keylen < blkalg->min_keysize) || - (sop->keylen > blkalg->max_keysize)) { - dprintk(0,KERN_DEBUG,"Wrong keylen '%zu' for algorithm '%s'. Use %u to %u.\n", - sop->keylen, alg_name, blkalg->min_keysize, - blkalg->max_keysize); - ret = -EINVAL; - goto error; - } - } + /* Create a session and put it to the list. */ + ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL); + if(!ses_new) { + ret = -ENOMEM; + goto error; + } - if (sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN) { - dprintk(0,KERN_DEBUG,"Setting key failed for %s-%zu.\n", - alg_name, sop->keylen*8); - ret = -EINVAL; - goto error; - } + memset(ses_new, 0, sizeof(*ses_new)); - /* Copy the key from user and set to TFM. */ - copy_from_user(keyp, sop->key, sop->keylen); - ret = crypto_blkcipher_setkey(blk_tfm, keyp, sop->keylen); - if (ret) { - dprintk(0,KERN_DEBUG,"Setting key failed for %s-%zu.\n", - alg_name, sop->keylen*8); - ret = -EINVAL; - goto error; + /* Set-up crypto transform. */ + if (alg_name) { + + ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, sop->key, sop->keylen); + if (ret < 0) { + return ret; } - } if (hash_name) { @@ -278,16 +252,8 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop) } - /* Create a session and put it to the list. */ - ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL); - if(!ses_new) { - ret = -ENOMEM; - goto error; - } - - memset(ses_new, 0, sizeof(*ses_new)); + /* put the new session to the list */ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); - ses_new->tfm = blk_tfm; ses_new->hash_tfm = hash_tfm; init_MUTEX(&ses_new->sem); @@ -312,11 +278,10 @@ restart: return 0; error: - if (blk_tfm) - crypto_free_blkcipher(blk_tfm); + cryptodev_cipher_deinit( &ses_new->cdata); if (hash_tfm) crypto_free_hash(hash_tfm); - + return ret; } @@ -342,10 +307,7 @@ crypto_destroy_session(struct csession *ses_ptr) ses_ptr->stat_count) : 0, ses_ptr->stat_count); #endif - if (ses_ptr->tfm) { - crypto_free_blkcipher(ses_ptr->tfm); - ses_ptr->tfm = NULL; - } + cryptodev_cipher_deinit(&ses_ptr->cdata); if (ses_ptr->hash_tfm) { crypto_free_hash(ses_ptr->hash_tfm); ses_ptr->hash_tfm = NULL; @@ -431,9 +393,6 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop) size_t nbytes, bufsize; int ret = 0; uint8_t hash_output[HASH_MAX_LEN]; - struct blkcipher_desc bdesc = { - .flags = CRYPTO_TFM_REQ_MAY_SLEEP, - }; struct hash_desc hdesc = { .flags = CRYPTO_TFM_REQ_MAY_SLEEP, }; @@ -460,7 +419,7 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop) bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes; nbytes = cop->len; - bdesc.tfm = ses_ptr->tfm; + hdesc.tfm = ses_ptr->hash_tfm; if (hdesc.tfm) { ret = crypto_hash_init(&hdesc); @@ -471,8 +430,8 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop) } } - if (bdesc.tfm) { - int blocksize = crypto_blkcipher_blocksize(bdesc.tfm); + if (ses_ptr->cdata.type != 0) { + int blocksize = ses_ptr->cdata.blocksize; if (unlikely(nbytes % blocksize)) { dprintk(1, KERN_ERR, @@ -482,11 +441,11 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop) goto out_unlock; } - ivsize = crypto_blkcipher_ivsize(bdesc.tfm); + ivsize = ses_ptr->cdata.ivsize; if (cop->iv) { copy_from_user(ivp, cop->iv, ivsize); - crypto_blkcipher_set_iv(bdesc.tfm, ivp, ivsize); + cryptodev_cipher_set_iv(&ses_ptr->cdata, ivp, ivsize); } } @@ -512,8 +471,8 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop) goto out; } } - if (bdesc.tfm) { - ret = crypto_blkcipher_encrypt(&bdesc, &sg, &sg, current_len); + if (ses_ptr->cdata.type != 0) { + ret = cryptodev_cipher_encrypt( &ses_ptr->cdata, &sg, &sg, current_len); if (unlikely(ret)) { dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret); @@ -523,8 +482,8 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop) dst += current_len; } } else { - if (bdesc.tfm) { - ret = crypto_blkcipher_decrypt(&bdesc, &sg, &sg, current_len); + if (ses_ptr->cdata.type != 0) { + ret = cryptodev_cipher_decrypt( &ses_ptr->cdata, &sg, &sg, current_len); if (unlikely(ret)) { dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret); |