diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-07-25 20:48:26 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-07-25 21:34:37 +0200 |
commit | a9970bd8d7b690f03e770a16d8471924ea3ad126 (patch) | |
tree | 2281fec02d8f185f5ca843b001aff239fe10d48b /ncr-sessions.c | |
parent | 174add36f5b6592db7573145f5c59d0207856e07 (diff) | |
download | cryptodev-linux-a9970bd8d7b690f03e770a16d8471924ea3ad126.tar.gz cryptodev-linux-a9970bd8d7b690f03e770a16d8471924ea3ad126.tar.xz cryptodev-linux-a9970bd8d7b690f03e770a16d8471924ea3ad126.zip |
Separated the direct session functions.
Diffstat (limited to 'ncr-sessions.c')
-rw-r--r-- | ncr-sessions.c | 381 |
1 files changed, 2 insertions, 379 deletions
diff --git a/ncr-sessions.c b/ncr-sessions.c index fb9fe4f..8137276 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -25,8 +25,7 @@ #include "ncr_int.h" #include <linux/mm_types.h> #include <linux/scatterlist.h> - -static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); +#include <ncr-sessions.h> void ncr_sessions_list_deinit(struct list_sem_st* lst) { @@ -565,120 +564,7 @@ fail: return ret; } -/* Only the output buffer is given as scatterlist */ -static int get_userbuf1(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int pagecount = 0; - - if (op->data.udata.output == NULL) { - return -EINVAL; - } - - pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - - - ses->available_pages = pagecount; - - if (pagecount > ses->array_size) { - while (ses->array_size < pagecount) - ses->array_size *= 2; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, ses->array_size); - ses->pages = krealloc(ses->pages, ses->array_size * - sizeof(struct page *), GFP_KERNEL); - ses->sg = krealloc(ses->sg, ses->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - - if (ses->sg == NULL || ses->pages == NULL) { - return -ENOMEM; - } - } - - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, - pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*dst_sg) = ses->sg; - *dst_cnt = pagecount; - - return 0; -} - -/* make op->data.udata.input and op->data.udata.output available in scatterlists */ -static int get_userbuf2(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **src_sg, - unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - - if (op->data.udata.input == NULL) { - return -EINVAL; - } - - src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); - - if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ - if (op->data.udata.output != NULL) { - dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - write_src = 0; - } else { - dst_pagecount = 0; - } - } - - ses->available_pages = pagecount = src_pagecount + dst_pagecount; - - if (pagecount > ses->array_size) { - while (ses->array_size < pagecount) - ses->array_size *= 2; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, ses->array_size); - ses->pages = krealloc(ses->pages, ses->array_size * - sizeof(struct page *), GFP_KERNEL); - ses->sg = krealloc(ses->sg, ses->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - - if (ses->sg == NULL || ses->pages == NULL) { - return -ENOMEM; - } - } - - if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, - src_pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*src_sg) = ses->sg; - *src_cnt = src_pagecount; - - if (dst_pagecount) { - *dst_cnt = dst_pagecount; - (*dst_sg) = ses->sg + src_pagecount; - - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); - release_user_pages(ses->pages, src_pagecount); - return -EINVAL; - } - } else { - if (op->data.udata.output != NULL) { - *dst_cnt = src_pagecount; - (*dst_sg) = (*src_sg); - } else { - *dst_cnt = 0; - *dst_sg = NULL; - } - } - - return 0; -} - -static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) +void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) { struct session_item_st * item, *tmp; @@ -824,269 +710,6 @@ fail: return ret; } -/* Called when userspace buffers are used */ -static int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - int ret; - struct session_item_st* sess; - struct scatterlist *isg; - struct scatterlist *osg; - unsigned osg_cnt=0, isg_cnt=0; - size_t isg_size, osg_size; - - sess = ncr_sessions_item_get( &lists->sessions, op->ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - isg_size = op->data.udata.input_size; - osg_size = op->data.udata.output_size; - - switch(sess->op) { - case NCR_OP_ENCRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } - op->data.udata.output_size = osg_size; - - break; - case NCR_OP_DECRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - if (osg_size < isg_size) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } - op->data.udata.output_size = osg_size; - - break; - - case NCR_OP_SIGN: - case NCR_OP_VERIFY: - ret = cryptodev_hash_update(&sess->hash, isg, isg_size); - if (ret < 0) { - err(); - goto fail; - } - break; - default: - err(); - ret = -EINVAL; - goto fail; - } - - ret = 0; - -fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); - _ncr_sessions_item_put(sess); - - return ret; -} - -static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - if (op->data.udata.input != NULL) { - return _ncr_session_direct_update(lists, op); - } - - return 0; -} - -static int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - int ret; - struct session_item_st* sess; - struct data_item_st* odata = NULL; - int digest_size; - uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; - uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size = 0; - size_t orig_osg_size; - - sess = ncr_sessions_item_get( &lists->sessions, op->ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - ret = try_session_direct_update(lists, op); - if (ret < 0) { - err(); - _ncr_sessions_item_put(sess); - return ret; - } - - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - break; - case NCR_OP_VERIFY: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - orig_osg_size = osg_size = op->data.udata.output_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; - } - - if (sess->algorithm->is_hmac) { - ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - if (digest_size != odata->data_size || - memcmp(vdigest, digest, digest_size) != 0) { - - op->err = NCR_VERIFICATION_FAILED; - } else { - op->err = NCR_SUCCESS; - } - } else { - /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, - digest, digest_size, &op->err); - if (ret < 0) { - err(); - goto fail; - } - } - break; - - case NCR_OP_SIGN: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - orig_osg_size = osg_size = op->data.udata.output_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || osg_size < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; - } - - ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - osg_size = digest_size; - - cryptodev_hash_deinit(&sess->hash); - - if (sess->algorithm->is_pk) { - /* PK signature */ - - ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, - osg, osg_cnt, &orig_osg_size); - if (ret < 0) { - err(); - goto fail; - } - osg_size = orig_osg_size; - } - break; - default: - err(); - ret = -EINVAL; - goto fail; - } - - if (osg_size > 0) - op->data.udata.output_size = osg_size; - - ret = 0; - -fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); - - cryptodev_hash_deinit(&sess->hash); - if (sess->algorithm->is_symmetric) { - cryptodev_cipher_deinit(&sess->cipher); - } else { - ncr_pk_cipher_deinit(&sess->pk); - } - - _ncr_sessions_item_put(sess); - _ncr_session_remove(&lists->sessions, op->ses); - - return ret; -} - - int ncr_session_update(struct ncr_lists* lists, void __user* arg) { struct ncr_session_op_st op; |