diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c index a6b0f8353bb..89b6814c70a 100644 --- a/drivers/staging/sep/sep_crypto.c +++ b/drivers/staging/sep/sep_crypto.c @@ -88,17 +88,17 @@ static void sep_dequeuer(void *data); * This will only print dump if DEBUG is set; it does * follow kernel debug print enabling */ -static void crypto_sep_dump_message(struct sep_system_ctx *sctx) +static void crypto_sep_dump_message(struct sep_device *sep, void *msg) { #if 0 u32 *p; u32 *i; int count; - p = sctx->sep_used->shared_addr; - i = (u32 *)sctx->msg; - for (count = 0; count < 40 * 4; count += 4) - dev_dbg(&sctx->sep_used->pdev->dev, + p = sep->shared_addr; + i = (u32 *)msg; + for (count = 0; count < 10 * 4; count += 4) + dev_dbg(&sep->pdev->dev, "[PID%d] Word %d of the message is %x (local)%x\n", current->pid, count/4, *p++, *i++); #endif @@ -534,6 +534,67 @@ static void sep_dump_sg(struct sep_device *sep, char *stg, #endif } +/* Debug - prints only if DEBUG is defined */ +static void sep_dump_ivs(struct ablkcipher_request *req, char *reason) + + { + unsigned char *cptr; + struct sep_aes_internal_context *aes_internal; + struct sep_des_internal_context *des_internal; + int ct1; + + struct this_task_ctx *ta_ctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; + + ta_ctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); + + dev_dbg(&ta_ctx->sep_used->pdev->dev, "IV DUMP - %s\n", reason); + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + + des_internal = (struct sep_des_internal_context *) + sctx->des_private_ctx.ctx_buf; + /* print vendor */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - vendor iv for DES\n"); + cptr = (unsigned char *)des_internal->iv_context; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + + /* print walk */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - walk from kernel crypto iv for DES\n"); + cptr = (unsigned char *)ta_ctx->walk.iv; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + } else if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + + aes_internal = (struct sep_aes_internal_context *) + sctx->aes_private_ctx.cbuff; + /* print vendor */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - vendor iv for AES\n"); + cptr = (unsigned char *)aes_internal->aes_ctx_iv; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + + /* print walk */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep - walk from kernel crypto iv for AES\n"); + cptr = (unsigned char *)ta_ctx->walk.iv; + for (ct1 = 0; ct1 < crypto_ablkcipher_ivsize(tfm); ct1 += 1) + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "%02x\n", *(cptr + ct1)); + } +} + /** * RFC2451: Weak key check * Returns: 1 (weak), 0 (not weak) @@ -671,61 +732,61 @@ static u32 sep_sg_nents(struct scatterlist *sg) /** * sep_start_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @returns: offset to place for the next word in the message * Set up pointer in message pool for new message */ -static u32 sep_start_msg(struct sep_system_ctx *sctx) +static u32 sep_start_msg(struct this_task_ctx *ta_ctx) { u32 *word_ptr; - sctx->msg_len_words = 2; - sctx->msgptr = sctx->msg; - memset(sctx->msg, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - sctx->msgptr += sizeof(u32) * 2; - word_ptr = (u32 *)sctx->msgptr; + ta_ctx->msg_len_words = 2; + ta_ctx->msgptr = ta_ctx->msg; + memset(ta_ctx->msg, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); + ta_ctx->msgptr += sizeof(u32) * 2; + word_ptr = (u32 *)ta_ctx->msgptr; *word_ptr = SEP_START_MSG_TOKEN; return sizeof(u32) * 2; } /** * sep_end_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @messages_offset: current message offset * Returns: 0 for success; <0 otherwise * End message; set length and CRC; and * send interrupt to the SEP */ -static void sep_end_msg(struct sep_system_ctx *sctx, u32 msg_offset) +static void sep_end_msg(struct this_task_ctx *ta_ctx, u32 msg_offset) { u32 *word_ptr; /* Msg size goes into msg after token */ - sctx->msg_len_words = msg_offset / sizeof(u32) + 1; - word_ptr = (u32 *)sctx->msgptr; + ta_ctx->msg_len_words = msg_offset / sizeof(u32) + 1; + word_ptr = (u32 *)ta_ctx->msgptr; word_ptr += 1; - *word_ptr = sctx->msg_len_words; + *word_ptr = ta_ctx->msg_len_words; /* CRC (currently 0) goes at end of msg */ - word_ptr = (u32 *)(sctx->msgptr + msg_offset); + word_ptr = (u32 *)(ta_ctx->msgptr + msg_offset); *word_ptr = 0; } /** * sep_start_inbound_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: offset to place for the next word in the message * @returns: 0 for success; error value for failure * Set up pointer in message pool for inbound message */ -static u32 sep_start_inbound_msg(struct sep_system_ctx *sctx, u32 *msg_offset) +static u32 sep_start_inbound_msg(struct this_task_ctx *ta_ctx, u32 *msg_offset) { u32 *word_ptr; u32 token; u32 error = SEP_OK; *msg_offset = sizeof(u32) * 2; - word_ptr = (u32 *)sctx->msgptr; + word_ptr = (u32 *)ta_ctx->msgptr; token = *word_ptr; - sctx->msg_len_words = *(word_ptr + 1); + ta_ctx->msg_len_words = *(word_ptr + 1); if (token != SEP_START_MSG_TOKEN) { error = SEP_INVALID_START; @@ -739,7 +800,7 @@ end_function: /** * sep_write_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @in_addr: pointer to start of parameter * @size: size of parameter to copy (in bytes) * @max_size: size to move up offset; SEP mesg is in word sizes @@ -747,12 +808,12 @@ end_function: * @byte_array: flag ti indicate wheter endian must be changed * Copies data into the message area from caller */ -static void sep_write_msg(struct sep_system_ctx *sctx, void *in_addr, +static void sep_write_msg(struct this_task_ctx *ta_ctx, void *in_addr, u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) { u32 *word_ptr; void *void_ptr; - void_ptr = sctx->msgptr + *msg_offset; + void_ptr = ta_ctx->msgptr + *msg_offset; word_ptr = (u32 *)void_ptr; memcpy(void_ptr, in_addr, size); *msg_offset += max_size; @@ -767,18 +828,18 @@ static void sep_write_msg(struct sep_system_ctx *sctx, void *in_addr, /** * sep_make_header - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: pointer to current offset (is updated) * @op_code: op code to put into message * Puts op code into message and updates offset */ -static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, +static void sep_make_header(struct this_task_ctx *ta_ctx, u32 *msg_offset, u32 op_code) { u32 *word_ptr; - *msg_offset = sep_start_msg(sctx); - word_ptr = (u32 *)(sctx->msgptr + *msg_offset); + *msg_offset = sep_start_msg(ta_ctx); + word_ptr = (u32 *)(ta_ctx->msgptr + *msg_offset); *word_ptr = op_code; *msg_offset += sizeof(u32); } @@ -787,7 +848,7 @@ static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, /** * sep_read_msg - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @in_addr: pointer to start of parameter * @size: size of parameter to copy (in bytes) * @max_size: size to move up offset; SEP mesg is in word sizes @@ -795,12 +856,12 @@ static void sep_make_header(struct sep_system_ctx *sctx, u32 *msg_offset, * @byte_array: flag ti indicate wheter endian must be changed * Copies data out of the message area to caller */ -static void sep_read_msg(struct sep_system_ctx *sctx, void *in_addr, +static void sep_read_msg(struct this_task_ctx *ta_ctx, void *in_addr, u32 size, u32 max_size, u32 *msg_offset, u32 byte_array) { u32 *word_ptr; void *void_ptr; - void_ptr = sctx->msgptr + *msg_offset; + void_ptr = ta_ctx->msgptr + *msg_offset; word_ptr = (u32 *)void_ptr; /* Do we need to manipulate endian? */ @@ -816,28 +877,28 @@ static void sep_read_msg(struct sep_system_ctx *sctx, void *in_addr, /** * sep_verify_op - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @op_code: expected op_code * @msg_offset: pointer to current offset (is updated) * @returns: 0 for success; error for failure */ -static u32 sep_verify_op(struct sep_system_ctx *sctx, u32 op_code, +static u32 sep_verify_op(struct this_task_ctx *ta_ctx, u32 op_code, u32 *msg_offset) { u32 error; u32 in_ary[2]; - struct sep_device *sep = sctx->sep_used; + struct sep_device *sep = ta_ctx->sep_used; dev_dbg(&sep->pdev->dev, "dumping return message\n"); - error = sep_start_inbound_msg(sctx, msg_offset); + error = sep_start_inbound_msg(ta_ctx, msg_offset); if (error) { dev_warn(&sep->pdev->dev, "sep_start_inbound_msg error\n"); return error; } - sep_read_msg(sctx, in_ary, sizeof(u32) * 2, sizeof(u32) * 2, + sep_read_msg(ta_ctx, in_ary, sizeof(u32) * 2, sizeof(u32) * 2, msg_offset, 0); if (in_ary[0] != op_code) { @@ -863,7 +924,7 @@ return 0; /** * sep_read_context - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: point to current place in SEP msg; is updated * @dst: pointer to place to put the context * @len: size of the context structure (differs for crypro/hash) @@ -873,16 +934,16 @@ return 0; * it skips over some words in the msg area depending on the size * of the context */ -static void sep_read_context(struct sep_system_ctx *sctx, u32 *msg_offset, +static void sep_read_context(struct this_task_ctx *ta_ctx, u32 *msg_offset, void *dst, u32 len) { u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); - sep_read_msg(sctx, dst, len, max_length, msg_offset, 0); + sep_read_msg(ta_ctx, dst, len, max_length, msg_offset, 0); } /** * sep_write_context - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * @msg_offset: point to current place in SEP msg; is updated * @src: pointer to the current context * @len: size of the context structure (differs for crypro/hash) @@ -892,76 +953,77 @@ static void sep_read_context(struct sep_system_ctx *sctx, u32 *msg_offset, * it skips over some words in the msg area depending on the size * of the context */ -static void sep_write_context(struct sep_system_ctx *sctx, u32 *msg_offset, +static void sep_write_context(struct this_task_ctx *ta_ctx, u32 *msg_offset, void *src, u32 len) { u32 max_length = ((len + 3) / sizeof(u32)) * sizeof(u32); - sep_write_msg(sctx, src, len, max_length, msg_offset, 0); + sep_write_msg(ta_ctx, src, len, max_length, msg_offset, 0); } /** * sep_clear_out - - * @sctx: pointer to struct sep_system_ctx + * @ta_ctx: pointer to struct this_task_ctx * Clear out crypto related values in sep device structure * to enable device to be used by anyone; either kernel * crypto or userspace app via middleware */ -static void sep_clear_out(struct sep_system_ctx *sctx) +static void sep_clear_out(struct this_task_ctx *ta_ctx) { - if (sctx->src_sg_hold) { - sep_free_sg_buf(sctx->src_sg_hold); - sctx->src_sg_hold = NULL; + if (ta_ctx->src_sg_hold) { + sep_free_sg_buf(ta_ctx->src_sg_hold); + ta_ctx->src_sg_hold = NULL; } - if (sctx->dst_sg_hold) { - sep_free_sg_buf(sctx->dst_sg_hold); - sctx->dst_sg_hold = NULL; + if (ta_ctx->dst_sg_hold) { + sep_free_sg_buf(ta_ctx->dst_sg_hold); + ta_ctx->dst_sg_hold = NULL; } - sctx->src_sg = NULL; - sctx->dst_sg = NULL; + ta_ctx->src_sg = NULL; + ta_ctx->dst_sg = NULL; - sep_free_dma_table_data_handler(sctx->sep_used, &sctx->dma_ctx); + sep_free_dma_table_data_handler(ta_ctx->sep_used, &ta_ctx->dma_ctx); - if (sctx->i_own_sep) { + if (ta_ctx->i_own_sep) { /** * The following unlocks the sep and makes it available * to any other application * First, null out crypto entries in sep before relesing it */ - sctx->sep_used->current_hash_req = NULL; - sctx->sep_used->current_cypher_req = NULL; - sctx->sep_used->current_request = 0; - sctx->sep_used->current_hash_stage = 0; - sctx->sep_used->sctx = NULL; - sctx->sep_used->in_kernel = 0; + ta_ctx->sep_used->current_hash_req = NULL; + ta_ctx->sep_used->current_cypher_req = NULL; + ta_ctx->sep_used->current_request = 0; + ta_ctx->sep_used->current_hash_stage = 0; + ta_ctx->sep_used->ta_ctx = NULL; + ta_ctx->sep_used->in_kernel = 0; - sctx->call_status.status = 0; + ta_ctx->call_status.status = 0; /* Remove anything confidentail */ - memset(sctx->sep_used->shared_addr, 0, + memset(ta_ctx->sep_used->shared_addr, 0, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - sep_queue_status_remove(sctx->sep_used, &sctx->queue_elem); + sep_queue_status_remove(ta_ctx->sep_used, &ta_ctx->queue_elem); #ifdef SEP_ENABLE_RUNTIME_PM - sctx->sep_used->in_use = 0; - pm_runtime_mark_last_busy(&sctx->sep_used->pdev->dev); - pm_runtime_put_autosuspend(&sctx->sep_used->pdev->dev); + ta_ctx->sep_used->in_use = 0; + pm_runtime_mark_last_busy(&ta_ctx->sep_used->pdev->dev); + pm_runtime_put_autosuspend(&ta_ctx->sep_used->pdev->dev); #endif - clear_bit(SEP_WORKING_LOCK_BIT, &sctx->sep_used->in_use_flags); - sctx->sep_used->pid_doing_transaction = 0; + clear_bit(SEP_WORKING_LOCK_BIT, + &ta_ctx->sep_used->in_use_flags); + ta_ctx->sep_used->pid_doing_transaction = 0; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "[PID%d] waking up next transaction\n", current->pid); clear_bit(SEP_TRANSACTION_STARTED_LOCK_BIT, - &sctx->sep_used->in_use_flags); - wake_up(&sctx->sep_used->event_transactions); + &ta_ctx->sep_used->in_use_flags); + wake_up(&ta_ctx->sep_used->event_transactions); - sctx->i_own_sep = 0; + ta_ctx->i_own_sep = 0; } } @@ -969,22 +1031,34 @@ static void sep_clear_out(struct sep_system_ctx *sctx) * Release crypto infrastructure from EINPROGRESS and * clear sep_dev so that SEP is available to anyone */ -static void sep_crypto_release(struct sep_system_ctx *sctx, u32 error) +static void sep_crypto_release(struct sep_system_ctx *sctx, + struct this_task_ctx *ta_ctx, u32 error) { - struct ahash_request *hash_req = sctx->current_hash_req; + struct ahash_request *hash_req = ta_ctx->current_hash_req; struct ablkcipher_request *cypher_req = - sctx->current_cypher_req; - struct sep_device *sep = sctx->sep_used; + ta_ctx->current_cypher_req; + struct sep_device *sep = ta_ctx->sep_used; - sep_clear_out(sctx); + sep_clear_out(ta_ctx); + + /** + * This may not yet exist depending when we + * chose to bail out. If it does exist, set + * it to 1 + */ + if (ta_ctx->are_we_done_yet != NULL) + *ta_ctx->are_we_done_yet = 1; if (cypher_req != NULL) { - if (cypher_req->base.complete == NULL) { - dev_dbg(&sep->pdev->dev, - "release is null for cypher!"); - } else { - cypher_req->base.complete( - &cypher_req->base, error); + if ((sctx->key_sent == 1) || + ((error != 0) && (error != -EINPROGRESS))) { + if (cypher_req->base.complete == NULL) { + dev_dbg(&sep->pdev->dev, + "release is null for cypher!"); + } else { + cypher_req->base.complete( + &cypher_req->base, error); + } } } @@ -1005,20 +1079,20 @@ static void sep_crypto_release(struct sep_system_ctx *sctx, u32 error) * and it will return 0 if sep is now ours; error value if there * were problems */ -static int sep_crypto_take_sep(struct sep_system_ctx *sctx) +static int sep_crypto_take_sep(struct this_task_ctx *ta_ctx) { - struct sep_device *sep = sctx->sep_used; + struct sep_device *sep = ta_ctx->sep_used; int result; struct sep_msgarea_hdr *my_msg_header; - my_msg_header = (struct sep_msgarea_hdr *)sctx->msg; + my_msg_header = (struct sep_msgarea_hdr *)ta_ctx->msg; /* add to status queue */ - sctx->queue_elem = sep_queue_status_add(sep, my_msg_header->opcode, - sctx->nbytes, current->pid, + ta_ctx->queue_elem = sep_queue_status_add(sep, my_msg_header->opcode, + ta_ctx->nbytes, current->pid, current->comm, sizeof(current->comm)); - if (!sctx->queue_elem) { + if (!ta_ctx->queue_elem) { dev_dbg(&sep->pdev->dev, "[PID%d] updating queue" " status error\n", current->pid); return -EINVAL; @@ -1033,48 +1107,61 @@ static int sep_crypto_take_sep(struct sep_system_ctx *sctx) pm_runtime_get_sync(&sep_dev->pdev->dev); /* Copy in the message */ - memcpy(sep->shared_addr, sctx->msg, + memcpy(sep->shared_addr, ta_ctx->msg, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); /* Copy in the dcb information if there is any */ - if (sctx->dcb_region) { + if (ta_ctx->dcb_region) { result = sep_activate_dcb_dmatables_context(sep, - &sctx->dcb_region, &sctx->dmatables_region, - sctx->dma_ctx); + &ta_ctx->dcb_region, &ta_ctx->dmatables_region, + ta_ctx->dma_ctx); if (result) return result; } /* Mark the device so we know how to finish the job in the tasklet */ - if (sctx->current_hash_req) - sep->current_hash_req = sctx->current_hash_req; + if (ta_ctx->current_hash_req) + sep->current_hash_req = ta_ctx->current_hash_req; else - sep->current_cypher_req = sctx->current_cypher_req; + sep->current_cypher_req = ta_ctx->current_cypher_req; - sep->current_request = sctx->current_request; - sep->current_hash_stage = sctx->current_hash_stage; - sep->sctx = sctx; + sep->current_request = ta_ctx->current_request; + sep->current_hash_stage = ta_ctx->current_hash_stage; + sep->ta_ctx = ta_ctx; sep->in_kernel = 1; - sctx->i_own_sep = 1; + ta_ctx->i_own_sep = 1; + + /* need to set bit first to avoid race condition with interrupt */ + set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, &ta_ctx->call_status.status); result = sep_send_command_handler(sep); dev_dbg(&sep->pdev->dev, "[PID%d]: sending command to the sep\n", current->pid); - if (!result) { - set_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &sctx->call_status.status); + if (!result) dev_dbg(&sep->pdev->dev, "[PID%d]: command sent okay\n", current->pid); + else { + dev_dbg(&sep->pdev->dev, "[PID%d]: cant send command\n", + current->pid); + clear_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, + &ta_ctx->call_status.status); } return result; } -/* This needs to be run as a work queue as it can be put asleep */ -static void sep_crypto_block(void *data) +/** + * This function sets things up for a crypto data block process + * This does all preparation, but does not try to grab the + * sep + * @req: pointer to struct ablkcipher_request + * returns: 0 if all went well, non zero if error + */ +static int sep_crypto_block_data(struct ablkcipher_request *req) { + int int_error; u32 msg_offset; static u32 msg[10]; @@ -1085,318 +1172,440 @@ static void sep_crypto_block(void *data) ssize_t copy_result; int result; - u32 max_length; struct scatterlist *new_sg; - struct ablkcipher_request *req; - struct sep_block_ctx *bctx; + struct this_task_ctx *ta_ctx; struct crypto_ablkcipher *tfm; struct sep_system_ctx *sctx; - req = (struct ablkcipher_request *)data; - bctx = ablkcipher_request_ctx(req); + struct sep_des_internal_context *des_internal; + struct sep_aes_internal_context *aes_internal; + + ta_ctx = ablkcipher_request_ctx(req); tfm = crypto_ablkcipher_reqtfm(req); sctx = crypto_ablkcipher_ctx(tfm); /* start the walk on scatterlists */ - ablkcipher_walk_init(&bctx->walk, req->src, req->dst, req->nbytes); - dev_dbg(&sctx->sep_used->pdev->dev, "sep crypto block data size of %x\n", + ablkcipher_walk_init(&ta_ctx->walk, req->src, req->dst, req->nbytes); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep crypto block data size of %x\n", req->nbytes); - int_error = ablkcipher_walk_phys(req, &bctx->walk); + int_error = ablkcipher_walk_phys(req, &ta_ctx->walk); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, "walk phys error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", int_error); - sep_crypto_release(sctx, -ENOMEM); - return; + return -ENOMEM; } - /* check iv */ - if (bctx->des_opmode == SEP_DES_CBC) { - if (!bctx->walk.iv) { - dev_warn(&sctx->sep_used->pdev->dev, "no iv found\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } - - memcpy(bctx->iv, bctx->walk.iv, SEP_DES_IV_SIZE_BYTES); - sep_dump(sctx->sep_used, "iv", bctx->iv, SEP_DES_IV_SIZE_BYTES); - } - - if (bctx->aes_opmode == SEP_AES_CBC) { - if (!bctx->walk.iv) { - dev_warn(&sctx->sep_used->pdev->dev, "no iv found\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } - - memcpy(bctx->iv, bctx->walk.iv, SEP_AES_IV_SIZE_BYTES); - sep_dump(sctx->sep_used, "iv", bctx->iv, SEP_AES_IV_SIZE_BYTES); - } - - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto block: src is %lx dst is %lx\n", (unsigned long)req->src, (unsigned long)req->dst); /* Make sure all pages are even block */ - int_error = sep_oddball_pages(sctx->sep_used, req->src, - req->nbytes, bctx->walk.blocksize, &new_sg, 1); + int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, + req->nbytes, ta_ctx->walk.blocksize, &new_sg, 1); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, "oddball page eerror\n"); - sep_crypto_release(sctx, -ENOMEM); - return; + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball page eerror\n"); + return -ENOMEM; } else if (int_error == 1) { - sctx->src_sg = new_sg; - sctx->src_sg_hold = new_sg; + ta_ctx->src_sg = new_sg; + ta_ctx->src_sg_hold = new_sg; } else { - sctx->src_sg = req->src; - sctx->src_sg_hold = NULL; + ta_ctx->src_sg = req->src; + ta_ctx->src_sg_hold = NULL; } - int_error = sep_oddball_pages(sctx->sep_used, req->dst, - req->nbytes, bctx->walk.blocksize, &new_sg, 0); + int_error = sep_oddball_pages(ta_ctx->sep_used, req->dst, + req->nbytes, ta_ctx->walk.blocksize, &new_sg, 0); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, "walk phys error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", int_error); - sep_crypto_release(sctx, -ENOMEM); - return; + return -ENOMEM; } else if (int_error == 1) { - sctx->dst_sg = new_sg; - sctx->dst_sg_hold = new_sg; + ta_ctx->dst_sg = new_sg; + ta_ctx->dst_sg_hold = new_sg; } else { - sctx->dst_sg = req->dst; - sctx->dst_sg_hold = NULL; + ta_ctx->dst_sg = req->dst; + ta_ctx->dst_sg_hold = NULL; } - /* Do we need to perform init; ie; send key to sep? */ - if (sctx->key_sent == 0) { + /* set nbytes for queue status */ + ta_ctx->nbytes = req->nbytes; - dev_dbg(&sctx->sep_used->pdev->dev, "sending key\n"); + /* Key already done; this is for data */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending data\n"); - /* put together message to SEP */ - /* Start with op code */ - sep_make_header(sctx, &msg_offset, bctx->init_opcode); + sep_dump_sg(ta_ctx->sep_used, + "block sg in", ta_ctx->src_sg); - /* now deal with IV */ - if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { - if (bctx->des_opmode == SEP_DES_CBC) { - sep_write_msg(sctx, bctx->iv, - SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, - &msg_offset, 1); - sep_dump(sctx->sep_used, "initial IV", - bctx->walk.iv, SEP_DES_IV_SIZE_BYTES); - } else { - /* Skip if ECB */ - msg_offset += 4 * sizeof(u32); - } + /* check for valid data and proper spacing */ + src_ptr = sg_virt(ta_ctx->src_sg); + dst_ptr = sg_virt(ta_ctx->dst_sg); + + if (!src_ptr || !dst_ptr || + (ta_ctx->current_cypher_req->nbytes % + crypto_ablkcipher_blocksize(tfm))) { + + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cipher block size odd\n"); + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cipher block size is %x\n", + crypto_ablkcipher_blocksize(tfm)); + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cipher data size is %x\n", + ta_ctx->current_cypher_req->nbytes); + return -EINVAL; + } + + if (partial_overlap(src_ptr, dst_ptr, + ta_ctx->current_cypher_req->nbytes)) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "block partial overlap\n"); + return -EINVAL; + } + + /* Put together the message */ + sep_make_header(ta_ctx, &msg_offset, ta_ctx->block_opcode); + + /* If des, and size is 1 block, put directly in msg */ + if ((ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) && + (req->nbytes == crypto_ablkcipher_blocksize(tfm))) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "writing out one block des\n"); + + copy_result = sg_copy_to_buffer( + ta_ctx->src_sg, sep_sg_nents(ta_ctx->src_sg), + small_buf, crypto_ablkcipher_blocksize(tfm)); + + if (copy_result != crypto_ablkcipher_blocksize(tfm)) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "des block copy faild\n"); + return -ENOMEM; + } + + /* Put data into message */ + sep_write_msg(ta_ctx, small_buf, + crypto_ablkcipher_blocksize(tfm), + crypto_ablkcipher_blocksize(tfm) * 2, + &msg_offset, 1); + + /* Put size into message */ + sep_write_msg(ta_ctx, &req->nbytes, + sizeof(u32), sizeof(u32), &msg_offset, 0); + } else { + /* Otherwise, fill out dma tables */ + ta_ctx->dcb_input_data.app_in_address = src_ptr; + ta_ctx->dcb_input_data.data_in_size = req->nbytes; + ta_ctx->dcb_input_data.app_out_address = dst_ptr; + ta_ctx->dcb_input_data.block_size = + crypto_ablkcipher_blocksize(tfm); + ta_ctx->dcb_input_data.tail_block_size = 0; + ta_ctx->dcb_input_data.is_applet = 0; + ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; + ta_ctx->dcb_input_data.dst_sg = ta_ctx->dst_sg; + + result = sep_create_dcb_dmatables_context_kernel( + ta_ctx->sep_used, + &ta_ctx->dcb_region, + &ta_ctx->dmatables_region, + &ta_ctx->dma_ctx, + &ta_ctx->dcb_input_data, + 1); + if (result) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "crypto dma table create failed\n"); + return -EINVAL; + } + + /* Portion of msg is nulled (no data) */ + msg[0] = (u32)0; + msg[1] = (u32)0; + msg[2] = (u32)0; + msg[3] = (u32)0; + msg[4] = (u32)0; + sep_write_msg(ta_ctx, (void *)msg, sizeof(u32) * 5, + sizeof(u32) * 5, &msg_offset, 0); + } + + /** + * Before we write the message, we need to overwrite the + * vendor's IV with the one from our own ablkcipher walk + * iv because this is needed for dm-crypt + */ + sep_dump_ivs(req, "sending data block to sep\n"); + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "overwrite vendor iv on DES\n"); + des_internal = (struct sep_des_internal_context *) + sctx->des_private_ctx.ctx_buf; + memcpy((void *)des_internal->iv_context, + ta_ctx->walk.iv, crypto_ablkcipher_ivsize(tfm)); + } else if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "overwrite vendor iv on AES\n"); + aes_internal = (struct sep_aes_internal_context *) + sctx->aes_private_ctx.cbuff; + memcpy((void *)aes_internal->aes_ctx_iv, + ta_ctx->walk.iv, crypto_ablkcipher_ivsize(tfm)); + } + + /* Write context into message */ + if (ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) { + sep_write_context(ta_ctx, &msg_offset, + &sctx->des_private_ctx, + sizeof(struct sep_des_private_context)); + sep_dump(ta_ctx->sep_used, "ctx to block des", + &sctx->des_private_ctx, 40); + } else { + sep_write_context(ta_ctx, &msg_offset, + &sctx->aes_private_ctx, + sizeof(struct sep_aes_private_context)); + sep_dump(ta_ctx->sep_used, "ctx to block aes", + &sctx->aes_private_ctx, 20); + } + + /* conclude message */ + sep_end_msg(ta_ctx, msg_offset); + + /* Parent (caller) is now ready to tell the sep to do ahead */ + return 0; +} + + +/** + * This function sets things up for a crypto key submit process + * This does all preparation, but does not try to grab the + * sep + * @req: pointer to struct ablkcipher_request + * returns: 0 if all went well, non zero if error + */ +static int sep_crypto_send_key(struct ablkcipher_request *req) +{ + + int int_error; + u32 msg_offset; + static u32 msg[10]; + + u32 max_length; + struct this_task_ctx *ta_ctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; + + ta_ctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); + + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sending key\n"); + + /* start the walk on scatterlists */ + ablkcipher_walk_init(&ta_ctx->walk, req->src, req->dst, req->nbytes); + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "sep crypto block data size of %x\n", req->nbytes); + + int_error = ablkcipher_walk_phys(req, &ta_ctx->walk); + if (int_error) { + dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n", + int_error); + return -ENOMEM; + } + + /* check iv */ + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + if (!ta_ctx->walk.iv) { + dev_warn(&ta_ctx->sep_used->pdev->dev, "no iv found\n"); + return -EINVAL; + } + + memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); + sep_dump(ta_ctx->sep_used, "iv", + ta_ctx->iv, SEP_DES_IV_SIZE_BYTES); + } + + if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + if (!ta_ctx->walk.iv) { + dev_warn(&ta_ctx->sep_used->pdev->dev, "no iv found\n"); + return -EINVAL; + } + + memcpy(ta_ctx->iv, ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); + sep_dump(ta_ctx->sep_used, "iv", + ta_ctx->iv, SEP_AES_IV_SIZE_BYTES); + } + + /* put together message to SEP */ + /* Start with op code */ + sep_make_header(ta_ctx, &msg_offset, ta_ctx->init_opcode); + + /* now deal with IV */ + if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { + if (ta_ctx->des_opmode == SEP_DES_CBC) { + sep_write_msg(ta_ctx, ta_ctx->iv, + SEP_DES_IV_SIZE_BYTES, sizeof(u32) * 4, + &msg_offset, 1); + sep_dump(ta_ctx->sep_used, "initial IV", + ta_ctx->walk.iv, SEP_DES_IV_SIZE_BYTES); + } else { + /* Skip if ECB */ + msg_offset += 4 * sizeof(u32); + } + } else { + max_length = ((SEP_AES_IV_SIZE_BYTES + 3) / + sizeof(u32)) * sizeof(u32); + if (ta_ctx->aes_opmode == SEP_AES_CBC) { + sep_write_msg(ta_ctx, ta_ctx->iv, + SEP_AES_IV_SIZE_BYTES, max_length, + &msg_offset, 1); + sep_dump(ta_ctx->sep_used, "initial IV", + ta_ctx->walk.iv, SEP_AES_IV_SIZE_BYTES); } else { - max_length = ((SEP_AES_IV_SIZE_BYTES + 3) / - sizeof(u32)) * sizeof(u32); - if (bctx->aes_opmode == SEP_AES_CBC) { - sep_write_msg(sctx, bctx->iv, - SEP_AES_IV_SIZE_BYTES, max_length, - &msg_offset, 1); - sep_dump(sctx->sep_used, "initial IV", - bctx->walk.iv, SEP_AES_IV_SIZE_BYTES); - } else { /* Skip if ECB */ msg_offset += max_length; } } - /* load the key */ - if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { - sep_write_msg(sctx, (void *)&sctx->key.des.key1, - sizeof(u32) * 8, sizeof(u32) * 8, - &msg_offset, 1); + /* load the key */ + if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { + sep_write_msg(ta_ctx, (void *)&sctx->key.des.key1, + sizeof(u32) * 8, sizeof(u32) * 8, + &msg_offset, 1); - msg[0] = (u32)sctx->des_nbr_keys; - msg[1] = (u32)bctx->des_encmode; - msg[2] = (u32)bctx->des_opmode; - - sep_write_msg(sctx, (void *)msg, - sizeof(u32) * 3, sizeof(u32) * 3, - &msg_offset, 0); - } else { - sep_write_msg(sctx, (void *)&sctx->key.aes, - sctx->keylen, - SEP_AES_MAX_KEY_SIZE_BYTES, - &msg_offset, 1); - - msg[0] = (u32)sctx->aes_key_size; - msg[1] = (u32)bctx->aes_encmode; - msg[2] = (u32)bctx->aes_opmode; - msg[3] = (u32)0; /* Secret key is not used */ - sep_write_msg(sctx, (void *)msg, - sizeof(u32) * 4, sizeof(u32) * 4, - &msg_offset, 0); - } + msg[0] = (u32)sctx->des_nbr_keys; + msg[1] = (u32)ta_ctx->des_encmode; + msg[2] = (u32)ta_ctx->des_opmode; + sep_write_msg(ta_ctx, (void *)msg, + sizeof(u32) * 3, sizeof(u32) * 3, + &msg_offset, 0); } else { + sep_write_msg(ta_ctx, (void *)&sctx->key.aes, + sctx->keylen, + SEP_AES_MAX_KEY_SIZE_BYTES, + &msg_offset, 1); - /* set nbytes for queue status */ - sctx->nbytes = req->nbytes; - - /* Key already done; this is for data */ - dev_dbg(&sctx->sep_used->pdev->dev, "sending data\n"); - - sep_dump_sg(sctx->sep_used, - "block sg in", sctx->src_sg); - - /* check for valid data and proper spacing */ - src_ptr = sg_virt(sctx->src_sg); - dst_ptr = sg_virt(sctx->dst_sg); - - if (!src_ptr || !dst_ptr || - (sctx->current_cypher_req->nbytes % - crypto_ablkcipher_blocksize(tfm))) { - - dev_warn(&sctx->sep_used->pdev->dev, - "cipher block size odd\n"); - dev_warn(&sctx->sep_used->pdev->dev, - "cipher block size is %x\n", - crypto_ablkcipher_blocksize(tfm)); - dev_warn(&sctx->sep_used->pdev->dev, - "cipher data size is %x\n", - sctx->current_cypher_req->nbytes); - sep_crypto_release(sctx, -EINVAL); - return; - } - - if (partial_overlap(src_ptr, dst_ptr, - sctx->current_cypher_req->nbytes)) { - dev_warn(&sctx->sep_used->pdev->dev, - "block partial overlap\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } - - /* Put together the message */ - sep_make_header(sctx, &msg_offset, bctx->block_opcode); - - /* If des, and size is 1 block, put directly in msg */ - if ((bctx->block_opcode == SEP_DES_BLOCK_OPCODE) && - (req->nbytes == crypto_ablkcipher_blocksize(tfm))) { - - dev_dbg(&sctx->sep_used->pdev->dev, - "writing out one block des\n"); - - copy_result = sg_copy_to_buffer( - sctx->src_sg, sep_sg_nents(sctx->src_sg), - small_buf, crypto_ablkcipher_blocksize(tfm)); - - if (copy_result != crypto_ablkcipher_blocksize(tfm)) { - dev_warn(&sctx->sep_used->pdev->dev, - "des block copy faild\n"); - sep_crypto_release(sctx, -ENOMEM); - return; - } - - /* Put data into message */ - sep_write_msg(sctx, small_buf, - crypto_ablkcipher_blocksize(tfm), - crypto_ablkcipher_blocksize(tfm) * 2, - &msg_offset, 1); - - /* Put size into message */ - sep_write_msg(sctx, &req->nbytes, - sizeof(u32), sizeof(u32), &msg_offset, 0); - } else { - /* Otherwise, fill out dma tables */ - sctx->dcb_input_data.app_in_address = src_ptr; - sctx->dcb_input_data.data_in_size = req->nbytes; - sctx->dcb_input_data.app_out_address = dst_ptr; - sctx->dcb_input_data.block_size = - crypto_ablkcipher_blocksize(tfm); - sctx->dcb_input_data.tail_block_size = 0; - sctx->dcb_input_data.is_applet = 0; - sctx->dcb_input_data.src_sg = sctx->src_sg; - sctx->dcb_input_data.dst_sg = sctx->dst_sg; - - result = sep_create_dcb_dmatables_context_kernel( - sctx->sep_used, - &sctx->dcb_region, - &sctx->dmatables_region, - &sctx->dma_ctx, - &sctx->dcb_input_data, - 1); - if (result) { - dev_warn(&sctx->sep_used->pdev->dev, - "crypto dma table create failed\n"); - sep_crypto_release(sctx, -EINVAL); - return; - } - - /* Portion of msg is nulled (no data) */ - msg[0] = (u32)0; - msg[1] = (u32)0; - msg[2] = (u32)0; - msg[3] = (u32)0; - msg[4] = (u32)0; - sep_write_msg(sctx, (void *)msg, - sizeof(u32) * 5, - sizeof(u32) * 5, - &msg_offset, 0); - } - - /* Write context into message */ - if (bctx->block_opcode == SEP_DES_BLOCK_OPCODE) { - sep_write_context(sctx, &msg_offset, - &bctx->des_private_ctx, - sizeof(struct sep_des_private_context)); - sep_dump(sctx->sep_used, "ctx to block des", - &bctx->des_private_ctx, 40); - } else { - sep_write_context(sctx, &msg_offset, - &bctx->aes_private_ctx, - sizeof(struct sep_aes_private_context)); - sep_dump(sctx->sep_used, "ctx to block aes", - &bctx->aes_private_ctx, 20); - } + msg[0] = (u32)sctx->aes_key_size; + msg[1] = (u32)ta_ctx->aes_encmode; + msg[2] = (u32)ta_ctx->aes_opmode; + msg[3] = (u32)0; /* Secret key is not used */ + sep_write_msg(ta_ctx, (void *)msg, + sizeof(u32) * 4, sizeof(u32) * 4, + &msg_offset, 0); } - /* conclude message and then tell sep to do its thing */ - sctx->done_with_transaction = 0; + /* conclude message */ + sep_end_msg(ta_ctx, msg_offset); - sep_end_msg(sctx, msg_offset); - result = sep_crypto_take_sep(sctx); - if (result) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_crypto_take_sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + /* Parent (caller) is now ready to tell the sep to do ahead */ + return 0; +} + + +/* This needs to be run as a work queue as it can be put asleep */ +static void sep_crypto_block(void *data) +{ + unsigned long end_time; + + int result; + + struct ablkcipher_request *req; + struct this_task_ctx *ta_ctx; + struct crypto_ablkcipher *tfm; + struct sep_system_ctx *sctx; + int are_we_done_yet; + + req = (struct ablkcipher_request *)data; + ta_ctx = ablkcipher_request_ctx(req); + tfm = crypto_ablkcipher_reqtfm(req); + sctx = crypto_ablkcipher_ctx(tfm); + + ta_ctx->are_we_done_yet = &are_we_done_yet; + + pr_debug("sep_crypto_block\n"); + pr_debug("tfm is %p sctx is %p ta_ctx is %p\n", + tfm, sctx, ta_ctx); + pr_debug("key_sent is %d\n", sctx->key_sent); + + /* do we need to send the key */ + if (sctx->key_sent == 0) { + are_we_done_yet = 0; + result = sep_crypto_send_key(req); /* prep to send key */ + if (result != 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "could not prep key %x\n", result); + sep_crypto_release(sctx, ta_ctx, result); + return; + } + + result = sep_crypto_take_sep(ta_ctx); + if (result) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "sep_crypto_take_sep for key send failed\n"); + sep_crypto_release(sctx, ta_ctx, result); + return; + } + + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && + (are_we_done_yet == 0)) + schedule(); + + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "Send key job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; + } + + /* Set the key sent variable so this can be skipped later */ + sctx->key_sent = 1; + } + + /* Key sent (or maybe not if we did not have to), now send block */ + are_we_done_yet = 0; + + result = sep_crypto_block_data(req); + + if (result != 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "could prep not send block %x\n", result); + sep_crypto_release(sctx, ta_ctx, result); return; } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ + result = sep_crypto_take_sep(ta_ctx); + if (result) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "sep_crypto_take_sep for block send failed\n"); + sep_crypto_release(sctx, ta_ctx, result); + return; + } - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_crypto_block never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "Send block job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + + /* That's it; entire thing done, get out of queue */ + + pr_debug("crypto_block leaving\n"); + pr_debug("tfm is %p sctx is %p ta_ctx is %p\n", tfm, sctx, ta_ctx); } /** @@ -1405,7 +1614,6 @@ static void sep_crypto_block(void *data) static u32 crypto_post_op(struct sep_device *sep) { /* HERE */ - int int_error; u32 u32_error; u32 msg_offset; @@ -1413,169 +1621,185 @@ static u32 crypto_post_op(struct sep_device *sep) static char small_buf[100]; struct ablkcipher_request *req; - struct sep_block_ctx *bctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; struct crypto_ablkcipher *tfm; + struct sep_des_internal_context *des_internal; + struct sep_aes_internal_context *aes_internal; + if (!sep->current_cypher_req) return -EINVAL; /* hold req since we need to submit work after clearing sep */ req = sep->current_cypher_req; - bctx = ablkcipher_request_ctx(sep->current_cypher_req); + ta_ctx = ablkcipher_request_ctx(sep->current_cypher_req); tfm = crypto_ablkcipher_reqtfm(sep->current_cypher_req); sctx = crypto_ablkcipher_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "crypto post_op\n"); - dev_dbg(&sctx->sep_used->pdev->dev, "crypto post_op message dump\n"); - crypto_sep_dump_message(sctx); + pr_debug("crypto_post op\n"); + pr_debug("key_sent is %d tfm is %p sctx is %p ta_ctx is %p\n", + sctx->key_sent, tfm, sctx, ta_ctx); - sctx->done_with_transaction = 1; + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op\n"); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto post_op message dump\n"); + crypto_sep_dump_message(ta_ctx->sep_used, ta_ctx->msg); /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); /* Is this the result of performing init (key to SEP */ if (sctx->key_sent == 0) { /* Did SEP do it okay */ - u32_error = sep_verify_op(sctx, bctx->init_opcode, + u32_error = sep_verify_op(ta_ctx, ta_ctx->init_opcode, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "aes init error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Read Context */ - if (bctx->init_opcode == SEP_DES_INIT_OPCODE) { - sep_read_context(sctx, &msg_offset, - &bctx->des_private_ctx, + if (ta_ctx->init_opcode == SEP_DES_INIT_OPCODE) { + sep_read_context(ta_ctx, &msg_offset, + &sctx->des_private_ctx, sizeof(struct sep_des_private_context)); - sep_dump(sctx->sep_used, "ctx init des", - &bctx->des_private_ctx, 40); + sep_dump(ta_ctx->sep_used, "ctx init des", + &sctx->des_private_ctx, 40); } else { - sep_read_context(sctx, &msg_offset, - &bctx->aes_private_ctx, - sizeof(struct sep_des_private_context)); + sep_read_context(ta_ctx, &msg_offset, + &sctx->aes_private_ctx, + sizeof(struct sep_aes_private_context)); - sep_dump(sctx->sep_used, "ctx init aes", - &bctx->aes_private_ctx, 20); + sep_dump(ta_ctx->sep_used, "ctx init aes", + &sctx->aes_private_ctx, 20); } - /* We are done with init. Now send out the data */ - /* first release the sep */ + sep_dump_ivs(req, "after sending key to sep\n"); + + /* key sent went okay; release sep, and set are_we_done_yet */ sctx->key_sent = 1; - sep_crypto_release(sctx, -EINPROGRESS); - - spin_lock_irq(&queue_lock); - int_error = crypto_enqueue_request(&sep_queue, &req->base); - spin_unlock_irq(&queue_lock); - - if ((int_error != 0) && (int_error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "spe cypher post op cant queue\n"); - sep_crypto_release(sctx, int_error); - return int_error; - } - - /* schedule the data send */ - int_error = sep_submit_work(sep->workqueue, sep_dequeuer, - (void *)&sep_queue); - - if (int_error) { - dev_warn(&sep->pdev->dev, - "cant submit work sep_crypto_block\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } + sep_crypto_release(sctx, ta_ctx, -EINPROGRESS); } else { /** * This is the result of a block request */ - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "crypto_post_op block response\n"); - u32_error = sep_verify_op(sctx, bctx->block_opcode, + u32_error = sep_verify_op(ta_ctx, ta_ctx->block_opcode, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep block error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return -EINVAL; } - if (bctx->block_opcode == SEP_DES_BLOCK_OPCODE) { + if (ta_ctx->block_opcode == SEP_DES_BLOCK_OPCODE) { - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "post op for DES\n"); /* special case for 1 block des */ if (sep->current_cypher_req->nbytes == crypto_ablkcipher_blocksize(tfm)) { - sep_read_msg(sctx, small_buf, + sep_read_msg(ta_ctx, small_buf, crypto_ablkcipher_blocksize(tfm), crypto_ablkcipher_blocksize(tfm) * 2, &msg_offset, 1); - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "reading in block des\n"); copy_result = sg_copy_from_buffer( - sctx->dst_sg, - sep_sg_nents(sctx->dst_sg), + ta_ctx->dst_sg, + sep_sg_nents(ta_ctx->dst_sg), small_buf, crypto_ablkcipher_blocksize(tfm)); if (copy_result != crypto_ablkcipher_blocksize(tfm)) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "des block copy faild\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, + -ENOMEM); return -ENOMEM; } } /* Read Context */ - sep_read_context(sctx, &msg_offset, - &bctx->des_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->des_private_ctx, sizeof(struct sep_des_private_context)); } else { - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "post op for AES\n"); /* Skip the MAC Output */ msg_offset += (sizeof(u32) * 4); /* Read Context */ - sep_read_context(sctx, &msg_offset, - &bctx->aes_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->aes_private_ctx, sizeof(struct sep_aes_private_context)); } - sep_dump_sg(sctx->sep_used, - "block sg out", sctx->dst_sg); + sep_dump_sg(ta_ctx->sep_used, + "block sg out", ta_ctx->dst_sg); /* Copy to correct sg if this block had oddball pages */ - if (sctx->dst_sg_hold) - sep_copy_sg(sctx->sep_used, - sctx->dst_sg, - sctx->current_cypher_req->dst, - sctx->current_cypher_req->nbytes); + if (ta_ctx->dst_sg_hold) + sep_copy_sg(ta_ctx->sep_used, + ta_ctx->dst_sg, + ta_ctx->current_cypher_req->dst, + ta_ctx->current_cypher_req->nbytes); + + /** + * Copy the iv's back to the walk.iv + * This is required for dm_crypt + */ + sep_dump_ivs(req, "got data block from sep\n"); + if ((ta_ctx->current_request == DES_CBC) && + (ta_ctx->des_opmode == SEP_DES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "returning result iv to walk on DES\n"); + des_internal = (struct sep_des_internal_context *) + sctx->des_private_ctx.ctx_buf; + memcpy(ta_ctx->walk.iv, + (void *)des_internal->iv_context, + crypto_ablkcipher_ivsize(tfm)); + } else if ((ta_ctx->current_request == AES_CBC) && + (ta_ctx->aes_opmode == SEP_AES_CBC)) { + + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "returning result iv to walk on AES\n"); + aes_internal = (struct sep_aes_internal_context *) + sctx->aes_private_ctx.cbuff; + memcpy(ta_ctx->walk.iv, + (void *)aes_internal->aes_ctx_iv, + crypto_ablkcipher_ivsize(tfm)); + } /* finished, release everything */ - sep_crypto_release(sctx, 0); + sep_crypto_release(sctx, ta_ctx, 0); } + pr_debug("crypto_post_op done\n"); + pr_debug("key_sent is %d tfm is %p sctx is %p ta_ctx is %p\n", + sctx->key_sent, tfm, sctx, ta_ctx); + return 0; } @@ -1584,35 +1808,33 @@ static u32 hash_init_post_op(struct sep_device *sep) u32 u32_error; u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct sep_hash_ctx *ctx = ahash_request_ctx(sep->current_hash_req); + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash init post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_INIT_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_INIT_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, "hash init error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash init error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Read Context */ - sep_read_context(sctx, &msg_offset, - &ctx->hash_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); /* Signal to crypto infrastructure and clear out */ - dev_dbg(&sctx->sep_used->pdev->dev, "hash init post op done\n"); - sep_crypto_release(sctx, 0); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash init post op done\n"); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1621,33 +1843,69 @@ static u32 hash_update_post_op(struct sep_device *sep) u32 u32_error; u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); - struct sep_hash_ctx *ctx = ahash_request_ctx(sep->current_hash_req); + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash update post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_UPDATE_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_UPDATE_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, "hash init error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash init error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Read Context */ - sep_read_context(sctx, &msg_offset, - &ctx->hash_private_ctx, + sep_read_context(ta_ctx, &msg_offset, + &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); - sep_crypto_release(sctx, 0); + /** + * Following is only for finup; if we just completd the + * data portion of finup, we now need to kick off the + * finish portion of finup. + */ + + if (ta_ctx->sep_used->current_hash_stage == HASH_FINUP_DATA) { + + /* first reset stage to HASH_FINUP_FINISH */ + ta_ctx->sep_used->current_hash_stage = HASH_FINUP_FINISH; + + /* now enqueue the finish operation */ + spin_lock_irq(&queue_lock); + u32_error = crypto_enqueue_request(&sep_queue, + &ta_ctx->sep_used->current_hash_req->base); + spin_unlock_irq(&queue_lock); + + if ((u32_error != 0) && (u32_error != -EINPROGRESS)) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "spe cypher post op cant queue\n"); + sep_crypto_release(sctx, ta_ctx, u32_error); + return u32_error; + } + + /* schedule the data send */ + u32_error = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + + if (u32_error) { + dev_warn(&ta_ctx->sep_used->pdev->dev, + "cant submit work sep_crypto_block\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return -EINVAL; + } + } + + /* Signal to crypto infrastructure and clear out */ + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash update post op done\n"); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1658,45 +1916,44 @@ static u32 hash_final_post_op(struct sep_device *sep) u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash final post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_FINISH_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_FINISH_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, "hash finish error %x\n", + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash finish error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Grab the result */ - if (sctx->current_hash_req->result == NULL) { + if (ta_ctx->current_hash_req->result == NULL) { /* Oops, null buffer; error out here */ - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash finish null buffer\n"); - sep_crypto_release(sctx, (u32)-ENOMEM); + sep_crypto_release(sctx, ta_ctx, (u32)-ENOMEM); return -ENOMEM; } max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / sizeof(u32)) * sizeof(u32); - sep_read_msg(sctx, - sctx->current_hash_req->result, + sep_read_msg(ta_ctx, + ta_ctx->current_hash_req->result, crypto_ahash_digestsize(tfm), max_length, &msg_offset, 0); /* Signal to crypto infrastructure and clear out */ - dev_dbg(&sctx->sep_used->pdev->dev, "hash finish post op done\n"); - sep_crypto_release(sctx, 0); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash finish post op done\n"); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1707,48 +1964,47 @@ static u32 hash_digest_post_op(struct sep_device *sep) u32 msg_offset; struct crypto_ahash *tfm = crypto_ahash_reqtfm(sep->current_hash_req); struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, + struct this_task_ctx *ta_ctx = ahash_request_ctx(sep->current_hash_req); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash digest post op\n"); - sctx->done_with_transaction = 1; - /* first bring msg from shared area to local area */ - memcpy(sctx->msg, sep->shared_addr, + memcpy(ta_ctx->msg, sep->shared_addr, SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES); - u32_error = sep_verify_op(sctx, SEP_HASH_SINGLE_OPCODE, + u32_error = sep_verify_op(ta_ctx, SEP_HASH_SINGLE_OPCODE, &msg_offset); if (u32_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash digest finish error %x\n", u32_error); - sep_crypto_release(sctx, u32_error); + sep_crypto_release(sctx, ta_ctx, u32_error); return u32_error; } /* Grab the result */ - if (sctx->current_hash_req->result == NULL) { + if (ta_ctx->current_hash_req->result == NULL) { /* Oops, null buffer; error out here */ - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash digest finish null buffer\n"); - sep_crypto_release(sctx, (u32)-ENOMEM); + sep_crypto_release(sctx, ta_ctx, (u32)-ENOMEM); return -ENOMEM; } max_length = (((SEP_HASH_RESULT_SIZE_WORDS * sizeof(u32)) + 3) / sizeof(u32)) * sizeof(u32); - sep_read_msg(sctx, - sctx->current_hash_req->result, + sep_read_msg(ta_ctx, + ta_ctx->current_hash_req->result, crypto_ahash_digestsize(tfm), max_length, &msg_offset, 0); /* Signal to crypto infrastructure and clear out */ - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "hash digest finish post op done\n"); - sep_crypto_release(sctx, 0); + sep_crypto_release(sctx, ta_ctx, 0); return 0; } @@ -1759,7 +2015,6 @@ static u32 hash_digest_post_op(struct sep_device *sep) */ static void sep_finish(unsigned long data) { - unsigned long flags; struct sep_device *sep_dev; int res; @@ -1776,18 +2031,15 @@ static void sep_finish(unsigned long data) return; } - spin_lock_irqsave(&sep_dev->busy_lock, flags); if (sep_dev->in_kernel == (u32)0) { - spin_unlock_irqrestore(&sep_dev->busy_lock, flags); dev_warn(&sep_dev->pdev->dev, "sep_finish; not in kernel operation\n"); return; } - spin_unlock_irqrestore(&sep_dev->busy_lock, flags); /* Did we really do a sep command prior to this? */ if (0 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET, - &sep_dev->sctx->call_status.status)) { + &sep_dev->ta_ctx->call_status.status)) { dev_warn(&sep_dev->pdev->dev, "[PID%d] sendmsg not called\n", current->pid); @@ -1856,8 +2108,10 @@ static void sep_finish(unsigned long data) res = hash_init_post_op(sep_dev); break; case HASH_UPDATE: + case HASH_FINUP_DATA: res = hash_update_post_op(sep_dev); break; + case HASH_FINUP_FINISH: case HASH_FINISH: res = hash_final_post_op(sep_dev); break; @@ -1865,43 +2119,31 @@ static void sep_finish(unsigned long data) res = hash_digest_post_op(sep_dev); break; default: - dev_warn(&sep_dev->pdev->dev, - "invalid stage for hash finish\n"); + pr_debug("sep - invalid stage for hash finish\n"); } break; default: - dev_warn(&sep_dev->pdev->dev, - "invalid request for finish\n"); + pr_debug("sep - invalid request for finish\n"); } - if (res) { - dev_warn(&sep_dev->pdev->dev, - "finish returned error %x\n", res); - } + if (res) + pr_debug("sep - finish returned error %x\n", res); } static int sep_hash_cra_init(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); const char *alg_name = crypto_tfm_alg_name(tfm); - sctx->sep_used = sep_dev; - - dev_dbg(&sctx->sep_used->pdev->dev, - "sep_hash_cra_init name is %s\n", alg_name); + pr_debug("sep_hash_cra_init name is %s\n", alg_name); crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), - sizeof(struct sep_hash_ctx)); + sizeof(struct this_task_ctx)); return 0; } static void sep_hash_cra_exit(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); - - dev_dbg(&sctx->sep_used->pdev->dev, - "sep_hash_cra_exit\n"); - sctx->sep_used = NULL; + pr_debug("sep_hash_cra_exit\n"); } static void sep_hash_init(void *data) @@ -1910,60 +2152,49 @@ static void sep_hash_init(void *data) int result; struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; + unsigned long end_time; + int are_we_done_yet; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; - dev_dbg(&sctx->sep_used->pdev->dev, + ta_ctx->are_we_done_yet = &are_we_done_yet; + + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_init\n"); - sctx->current_hash_stage = HASH_INIT; + ta_ctx->current_hash_stage = HASH_INIT; /* opcode and mode */ - sep_make_header(sctx, &msg_offset, SEP_HASH_INIT_OPCODE); - sep_write_msg(sctx, &ctx->hash_opmode, + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_INIT_OPCODE); + sep_write_msg(ta_ctx, &ta_ctx->hash_opmode, sizeof(u32), sizeof(u32), &msg_offset, 0); - sep_end_msg(sctx, msg_offset); + sep_end_msg(ta_ctx, msg_offset); - sctx->done_with_transaction = 0; - - result = sep_crypto_take_sep(sctx); + are_we_done_yet = 0; + result = sep_crypto_take_sep(ta_ctx); if (result) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_init take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_init never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash init never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } static void sep_hash_update(void *data) @@ -1975,6 +2206,8 @@ static void sep_hash_update(void *data) u32 block_size; u32 head_len; u32 tail_len; + int are_we_done_yet; + static u32 msg[10]; static char small_buf[100]; void *src_ptr; @@ -1982,184 +2215,174 @@ static void sep_hash_update(void *data) ssize_t copy_result; struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; + unsigned long end_time; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; + + ta_ctx->are_we_done_yet = &are_we_done_yet; /* length for queue status */ - sctx->nbytes = req->nbytes; + ta_ctx->nbytes = req->nbytes; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_update\n"); - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->current_hash_stage = HASH_UPDATE; len = req->nbytes; block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); tail_len = req->nbytes % block_size; - dev_dbg(&sctx->sep_used->pdev->dev, "length is %x\n", len); - dev_dbg(&sctx->sep_used->pdev->dev, "block_size is %x\n", block_size); - dev_dbg(&sctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "length is %x\n", len); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); /* Compute header/tail sizes */ - int_ctx = (struct sep_hash_internal_context *)&ctx-> + int_ctx = (struct sep_hash_internal_context *)&sctx-> hash_private_ctx.internal_context; head_len = (block_size - int_ctx->prev_update_bytes) % block_size; tail_len = (req->nbytes - head_len) % block_size; /* Make sure all pages are even block */ - int_error = sep_oddball_pages(sctx->sep_used, req->src, + int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, req->nbytes, block_size, &new_sg, 1); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball pages error in crash update\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } else if (int_error == 1) { - sctx->src_sg = new_sg; - sctx->src_sg_hold = new_sg; + ta_ctx->src_sg = new_sg; + ta_ctx->src_sg_hold = new_sg; } else { - sctx->src_sg = req->src; - sctx->src_sg_hold = NULL; + ta_ctx->src_sg = req->src; + ta_ctx->src_sg_hold = NULL; } - src_ptr = sg_virt(sctx->src_sg); + src_ptr = sg_virt(ta_ctx->src_sg); - if ((!req->nbytes) || (!ctx->sg)) { + if ((!req->nbytes) || (!ta_ctx->src_sg)) { /* null data */ src_ptr = NULL; } - sep_dump_sg(sctx->sep_used, "hash block sg in", sctx->src_sg); + sep_dump_sg(ta_ctx->sep_used, "hash block sg in", ta_ctx->src_sg); - sctx->dcb_input_data.app_in_address = src_ptr; - sctx->dcb_input_data.data_in_size = req->nbytes - (head_len + tail_len); - sctx->dcb_input_data.app_out_address = NULL; - sctx->dcb_input_data.block_size = block_size; - sctx->dcb_input_data.tail_block_size = 0; - sctx->dcb_input_data.is_applet = 0; - sctx->dcb_input_data.src_sg = sctx->src_sg; - sctx->dcb_input_data.dst_sg = NULL; + ta_ctx->dcb_input_data.app_in_address = src_ptr; + ta_ctx->dcb_input_data.data_in_size = + req->nbytes - (head_len + tail_len); + ta_ctx->dcb_input_data.app_out_address = NULL; + ta_ctx->dcb_input_data.block_size = block_size; + ta_ctx->dcb_input_data.tail_block_size = 0; + ta_ctx->dcb_input_data.is_applet = 0; + ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; + ta_ctx->dcb_input_data.dst_sg = NULL; int_error = sep_create_dcb_dmatables_context_kernel( - sctx->sep_used, - &sctx->dcb_region, - &sctx->dmatables_region, - &sctx->dma_ctx, - &sctx->dcb_input_data, + ta_ctx->sep_used, + &ta_ctx->dcb_region, + &ta_ctx->dmatables_region, + &ta_ctx->dma_ctx, + &ta_ctx->dcb_input_data, 1); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash update dma table create failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); return; } /* Construct message to SEP */ - sep_make_header(sctx, &msg_offset, SEP_HASH_UPDATE_OPCODE); + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_UPDATE_OPCODE); msg[0] = (u32)0; msg[1] = (u32)0; msg[2] = (u32)0; - sep_write_msg(sctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, + sep_write_msg(ta_ctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, &msg_offset, 0); /* Handle remainders */ /* Head */ - sep_write_msg(sctx, &head_len, sizeof(u32), + sep_write_msg(ta_ctx, &head_len, sizeof(u32), sizeof(u32), &msg_offset, 0); if (head_len) { copy_result = sg_copy_to_buffer( req->src, - sep_sg_nents(sctx->src_sg), + sep_sg_nents(ta_ctx->src_sg), small_buf, head_len); if (copy_result != head_len) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sg head copy failure in hash block\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } - sep_write_msg(sctx, small_buf, head_len, + sep_write_msg(ta_ctx, small_buf, head_len, sizeof(u32) * 32, &msg_offset, 1); } else { msg_offset += sizeof(u32) * 32; } /* Tail */ - sep_write_msg(sctx, &tail_len, sizeof(u32), + sep_write_msg(ta_ctx, &tail_len, sizeof(u32), sizeof(u32), &msg_offset, 0); if (tail_len) { copy_result = sep_copy_offset_sg( - sctx->sep_used, - sctx->src_sg, + ta_ctx->sep_used, + ta_ctx->src_sg, req->nbytes - tail_len, small_buf, tail_len); if (copy_result != tail_len) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sg tail copy failure in hash block\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } - sep_write_msg(sctx, small_buf, tail_len, + sep_write_msg(ta_ctx, small_buf, tail_len, sizeof(u32) * 32, &msg_offset, 1); } else { msg_offset += sizeof(u32) * 32; } /* Context */ - sep_write_context(sctx, &msg_offset, &ctx->hash_private_ctx, + sep_write_context(ta_ctx, &msg_offset, &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); - sep_end_msg(sctx, msg_offset); - sctx->done_with_transaction = 0; - int_error = sep_crypto_take_sep(sctx); + sep_end_msg(ta_ctx, msg_offset); + are_we_done_yet = 0; + int_error = sep_crypto_take_sep(ta_ctx); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_update take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_update never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash update never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } static void sep_hash_final(void *data) @@ -2167,63 +2390,53 @@ static void sep_hash_final(void *data) u32 msg_offset; struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; int result; + unsigned long end_time; + int are_we_done_yet; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_final\n"); - sctx->current_hash_stage = HASH_FINISH; + ta_ctx->current_hash_stage = HASH_FINISH; + + ta_ctx->are_we_done_yet = &are_we_done_yet; /* opcode and mode */ - sep_make_header(sctx, &msg_offset, SEP_HASH_FINISH_OPCODE); + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_FINISH_OPCODE); /* Context */ - sep_write_context(sctx, &msg_offset, &ctx->hash_private_ctx, + sep_write_context(ta_ctx, &msg_offset, &sctx->hash_private_ctx, sizeof(struct sep_hash_private_context)); - sep_end_msg(sctx, msg_offset); - sctx->done_with_transaction = 0; - result = sep_crypto_take_sep(sctx); + sep_end_msg(ta_ctx, msg_offset); + are_we_done_yet = 0; + result = sep_crypto_take_sep(ta_ctx); if (result) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_final take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_final never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash final job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } static void sep_hash_digest(void *data) @@ -2234,6 +2447,7 @@ static void sep_hash_digest(void *data) u32 msg[10]; size_t copy_result; int result; + int are_we_done_yet; u32 tail_len; static char small_buf[100]; struct scatterlist *new_sg; @@ -2241,152 +2455,140 @@ static void sep_hash_digest(void *data) struct ahash_request *req; struct crypto_ahash *tfm; - struct sep_hash_ctx *ctx; + struct this_task_ctx *ta_ctx; struct sep_system_ctx *sctx; + unsigned long end_time; req = (struct ahash_request *)data; tfm = crypto_ahash_reqtfm(req); - ctx = ahash_request_ctx(req); sctx = crypto_ahash_ctx(tfm); + ta_ctx = ahash_request_ctx(req); + ta_ctx->sep_used = sep_dev; - dev_dbg(&sctx->sep_used->pdev->dev, + dev_dbg(&ta_ctx->sep_used->pdev->dev, "sep_hash_digest\n"); - sctx->current_hash_stage = HASH_DIGEST; + ta_ctx->current_hash_stage = HASH_DIGEST; + + ta_ctx->are_we_done_yet = &are_we_done_yet; /* length for queue status */ - sctx->nbytes = req->nbytes; + ta_ctx->nbytes = req->nbytes; block_size = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); tail_len = req->nbytes % block_size; - dev_dbg(&sctx->sep_used->pdev->dev, "length is %x\n", req->nbytes); - dev_dbg(&sctx->sep_used->pdev->dev, "block_size is %x\n", block_size); - dev_dbg(&sctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "length is %x\n", req->nbytes); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "block_size is %x\n", block_size); + dev_dbg(&ta_ctx->sep_used->pdev->dev, "tail len is %x\n", tail_len); /* Make sure all pages are even block */ - int_error = sep_oddball_pages(sctx->sep_used, req->src, + int_error = sep_oddball_pages(ta_ctx->sep_used, req->src, req->nbytes, block_size, &new_sg, 1); if (int_error < 0) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball pages error in crash update\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } else if (int_error == 1) { - sctx->src_sg = new_sg; - sctx->src_sg_hold = new_sg; + ta_ctx->src_sg = new_sg; + ta_ctx->src_sg_hold = new_sg; } else { - sctx->src_sg = req->src; - sctx->src_sg_hold = NULL; + ta_ctx->src_sg = req->src; + ta_ctx->src_sg_hold = NULL; } - src_ptr = sg_virt(sctx->src_sg); + src_ptr = sg_virt(ta_ctx->src_sg); - if ((!req->nbytes) || (!ctx->sg)) { + if ((!req->nbytes) || (!ta_ctx->src_sg)) { /* null data */ src_ptr = NULL; } - sep_dump_sg(sctx->sep_used, "hash block sg in", sctx->src_sg); + sep_dump_sg(ta_ctx->sep_used, "hash block sg in", ta_ctx->src_sg); - sctx->dcb_input_data.app_in_address = src_ptr; - sctx->dcb_input_data.data_in_size = req->nbytes - tail_len; - sctx->dcb_input_data.app_out_address = NULL; - sctx->dcb_input_data.block_size = block_size; - sctx->dcb_input_data.tail_block_size = 0; - sctx->dcb_input_data.is_applet = 0; - sctx->dcb_input_data.src_sg = sctx->src_sg; - sctx->dcb_input_data.dst_sg = NULL; + ta_ctx->dcb_input_data.app_in_address = src_ptr; + ta_ctx->dcb_input_data.data_in_size = req->nbytes - tail_len; + ta_ctx->dcb_input_data.app_out_address = NULL; + ta_ctx->dcb_input_data.block_size = block_size; + ta_ctx->dcb_input_data.tail_block_size = 0; + ta_ctx->dcb_input_data.is_applet = 0; + ta_ctx->dcb_input_data.src_sg = ta_ctx->src_sg; + ta_ctx->dcb_input_data.dst_sg = NULL; int_error = sep_create_dcb_dmatables_context_kernel( - sctx->sep_used, - &sctx->dcb_region, - &sctx->dmatables_region, - &sctx->dma_ctx, - &sctx->dcb_input_data, + ta_ctx->sep_used, + &ta_ctx->dcb_region, + &ta_ctx->dmatables_region, + &ta_ctx->dma_ctx, + &ta_ctx->dcb_input_data, 1); if (int_error) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "hash update dma table create failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); return; } /* Construct message to SEP */ - sep_make_header(sctx, &msg_offset, SEP_HASH_SINGLE_OPCODE); - sep_write_msg(sctx, &ctx->hash_opmode, + sep_make_header(ta_ctx, &msg_offset, SEP_HASH_SINGLE_OPCODE); + sep_write_msg(ta_ctx, &ta_ctx->hash_opmode, sizeof(u32), sizeof(u32), &msg_offset, 0); msg[0] = (u32)0; msg[1] = (u32)0; msg[2] = (u32)0; - sep_write_msg(sctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, + sep_write_msg(ta_ctx, msg, sizeof(u32) * 3, sizeof(u32) * 3, &msg_offset, 0); /* Tail */ - sep_write_msg(sctx, &tail_len, sizeof(u32), + sep_write_msg(ta_ctx, &tail_len, sizeof(u32), sizeof(u32), &msg_offset, 0); if (tail_len) { copy_result = sep_copy_offset_sg( - sctx->sep_used, - sctx->src_sg, + ta_ctx->sep_used, + ta_ctx->src_sg, req->nbytes - tail_len, small_buf, tail_len); if (copy_result != tail_len) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sg tail copy failure in hash block\n"); - sep_crypto_release(sctx, -ENOMEM); + sep_crypto_release(sctx, ta_ctx, -ENOMEM); return; } - sep_write_msg(sctx, small_buf, tail_len, + sep_write_msg(ta_ctx, small_buf, tail_len, sizeof(u32) * 32, &msg_offset, 1); } else { msg_offset += sizeof(u32) * 32; } - sep_end_msg(sctx, msg_offset); + sep_end_msg(ta_ctx, msg_offset); - sctx->done_with_transaction = 0; - - result = sep_crypto_take_sep(sctx); + are_we_done_yet = 0; + result = sep_crypto_take_sep(ta_ctx); if (result) { - dev_warn(&sctx->sep_used->pdev->dev, + dev_warn(&ta_ctx->sep_used->pdev->dev, "sep_hash_digest take sep failed\n"); - sep_crypto_release(sctx, -EINVAL); + sep_crypto_release(sctx, ta_ctx, -EINVAL); } - /** - * Sep is now working. Lets wait up to 5 seconds - * for completion. If it does not complete, we will do - * a crypto release with -EINVAL to release the - * kernel crypto infrastructure and let the system - * continue to boot up - * We have to wait this long because some crypto - * operations can take a while - */ - dev_dbg(&sctx->sep_used->pdev->dev, - "waiting for done with transaction\n"); - - sctx->end_time = jiffies + (SEP_TRANSACTION_WAIT_TIME * HZ); - while ((time_before(jiffies, sctx->end_time)) && - (!sctx->done_with_transaction)) + /* now we sit and wait up to a fixed time for completion */ + end_time = jiffies + (WAIT_TIME * HZ); + while ((time_before(jiffies, end_time)) && (are_we_done_yet == 0)) schedule(); - dev_dbg(&sctx->sep_used->pdev->dev, - "done waiting for done with transaction\n"); - - /* are we done? */ - if (!sctx->done_with_transaction) { - /* Nope, lets release and tell crypto no */ - dev_warn(&sctx->sep_used->pdev->dev, - "[PID%d] sep_hash_digest never finished\n", - current->pid); - sep_crypto_release(sctx, -EINVAL); + /* Done waiting; still not done yet? */ + if (are_we_done_yet == 0) { + dev_dbg(&ta_ctx->sep_used->pdev->dev, + "hash digest job never got done\n"); + sep_crypto_release(sctx, ta_ctx, -EINVAL); + return; } + } /** @@ -2404,6 +2606,7 @@ static void sep_dequeuer(void *data) struct ahash_request *hash_req; struct sep_system_ctx *sctx; struct crypto_ahash *hash_tfm; + struct this_task_ctx *ta_ctx; this_queue = (struct crypto_queue *)data; @@ -2481,22 +2684,32 @@ static void sep_dequeuer(void *data) return; } - if (sctx->current_hash_stage == HASH_INIT) { + ta_ctx = ahash_request_ctx(hash_req); + + if (ta_ctx->current_hash_stage == HASH_INIT) { pr_debug("sep crypto queue hash init\n"); sep_hash_init((void *)hash_req); return; - } else if (sctx->current_hash_stage == HASH_UPDATE) { + } else if (ta_ctx->current_hash_stage == HASH_UPDATE) { pr_debug("sep crypto queue hash update\n"); sep_hash_update((void *)hash_req); return; - } else if (sctx->current_hash_stage == HASH_FINISH) { + } else if (ta_ctx->current_hash_stage == HASH_FINISH) { pr_debug("sep crypto queue hash final\n"); sep_hash_final((void *)hash_req); return; - } else if (sctx->current_hash_stage == HASH_DIGEST) { + } else if (ta_ctx->current_hash_stage == HASH_DIGEST) { pr_debug("sep crypto queue hash digest\n"); sep_hash_digest((void *)hash_req); return; + } else if (ta_ctx->current_hash_stage == HASH_FINUP_DATA) { + pr_debug("sep crypto queue hash digest\n"); + sep_hash_update((void *)hash_req); + return; + } else if (ta_ctx->current_hash_stage == HASH_FINUP_FINISH) { + pr_debug("sep crypto queue hash digest\n"); + sep_hash_final((void *)hash_req); + return; } else { pr_debug("sep crypto queue hash oops nothing\n"); return; @@ -2507,605 +2720,671 @@ static void sep_dequeuer(void *data) static int sep_sha1_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 init\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_INIT; + pr_debug("sep - doing sha1 init\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_INIT; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha1_update(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 update\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_INIT; + pr_debug("sep - doing sha1 update\n"); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_UPDATE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha1_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 final\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha1 final\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_FINISH; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_FINISH; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; - + /* We return result of crypto enqueue */ + return error; } static int sep_sha1_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha1 digest\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha1 digest\n"); - sctx->current_request = SHA1; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA1; - sctx->current_hash_stage = HASH_DIGEST; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha1 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_sha1_finup(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha1 finup\n"); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha1 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA1; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA1; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_md5_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 init\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing md5 init\n"); - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_INIT; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_INIT; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep md5 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; - + /* We return result of crypto enqueue */ + return error; } static int sep_md5_update(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 update\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing md5 update\n"); - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_UPDATE; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_md5_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 final\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing md5 final\n"); - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_FINISH; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_FINISH; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep md5 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; - + /* We return result of crypto enqueue */ + return error; } static int sep_md5_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing md5 digest\n"); - sctx->current_request = MD5; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_MD5; - sctx->current_hash_stage = HASH_DIGEST; + pr_debug("sep - doing md5 digest\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep md5 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_md5_finup(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "md5 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + pr_debug("sep - doing md5 finup\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = MD5; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_MD5; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha224_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 init\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha224 init\n"); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_INIT; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_INIT; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha224 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha224_update(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 update\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha224 update\n"); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_UPDATE; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha224 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha224_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha224 final\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha224 final\n"); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_FINISH; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_FINISH; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha224 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha224_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing 224 digest\n"); - sctx->current_request = SHA224; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA224; - sctx->current_hash_stage = HASH_DIGEST; + pr_debug("sep - doing sha224 digest\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha224 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_sha224_finup(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + pr_debug("sep - doing sha224 finup\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA224; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA224; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_sha256_init(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 init\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha256 init\n"); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_INIT; + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_INIT; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 init cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 init cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha256_update(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 update\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha256 update\n"); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_UPDATE; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_UPDATE; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 update cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 update cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha256_final(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 final\n"); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); + pr_debug("sep - doing sha256 final\n"); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_FINISH; + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_FINISH; + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 final cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 final cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_sha256_digest(struct ahash_request *req) { int error; - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct sep_hash_ctx *ctx = ahash_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ahash_ctx(tfm); + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "doing sha256 digest\n"); - sctx->current_request = SHA256; - sctx->current_hash_req = req; - sctx->current_cypher_req = NULL; - ctx->hash_opmode = SEP_HASH_SHA256; - sctx->current_hash_stage = HASH_DIGEST; + pr_debug("sep - doing sha256 digest\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_DIGEST; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; +} - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep sha256 digest cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } +static int sep_sha256_finup(struct ahash_request *req) +{ + int error; + int error1; + struct this_task_ctx *ta_ctx = ahash_request_ctx(req); - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sha256 digest cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + pr_debug("sep - doing sha256 finup\n"); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = SHA256; + ta_ctx->current_hash_req = req; + ta_ctx->current_cypher_req = NULL; + ta_ctx->hash_opmode = SEP_HASH_SHA256; + ta_ctx->current_hash_stage = HASH_FINUP_DATA; + + /* lock necessary so that only one entity touches the queues */ + spin_lock_irq(&queue_lock); + error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); + spin_unlock_irq(&queue_lock); + /* We return result of crypto enqueue */ + return error; } static int sep_crypto_init(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); const char *alg_name = crypto_tfm_alg_name(tfm); - sctx->sep_used = sep_dev; - if (alg_name == NULL) - dev_dbg(&sctx->sep_used->pdev->dev, "alg is NULL\n"); + pr_debug("sep_crypto_init alg is NULL\n"); else - dev_dbg(&sctx->sep_used->pdev->dev, "alg is %s\n", alg_name); + pr_debug("sep_crypto_init alg is %s\n", alg_name); - tfm->crt_ablkcipher.reqsize = sizeof(struct sep_block_ctx); - dev_dbg(&sctx->sep_used->pdev->dev, "sep_crypto_init\n"); + tfm->crt_ablkcipher.reqsize = sizeof(struct this_task_ctx); return 0; } static void sep_crypto_exit(struct crypto_tfm *tfm) { - struct sep_system_ctx *sctx = crypto_tfm_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "sep_crypto_exit\n"); - sctx->sep_used = NULL; + pr_debug("sep_crypto_exit\n"); } static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, @@ -3113,8 +3392,9 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, { struct sep_system_ctx *sctx = crypto_ablkcipher_ctx(tfm); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes setkey\n"); + pr_debug("sep aes setkey\n"); + pr_debug("tfm is %p sctx is %p\n", tfm, sctx); switch (keylen) { case SEP_AES_KEY_128_SIZE: sctx->aes_key_size = AES_128; @@ -3129,7 +3409,7 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->aes_key_size = AES_512; break; default: - dev_warn(&sctx->sep_used->pdev->dev, "sep aes key size %x\n", + pr_debug("invalid sep aes key size %x\n", keylen); return -EINVAL; } @@ -3140,7 +3420,6 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->keylen = keylen; /* Indicate to encrypt/decrypt function to send key to SEP */ sctx->key_sent = 0; - sctx->last_block = 0; return 0; } @@ -3148,153 +3427,159 @@ static int sep_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int sep_aes_ecb_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes ecb encrypt\n"); - sctx->current_request = AES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_ENCRYPT; - bctx->aes_opmode = SEP_AES_ECB; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + pr_debug("sep - doing aes ecb encrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_ENCRYPT; + ta_ctx->aes_opmode = SEP_AES_ECB; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_aes_ecb_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes ecb decrypt\n"); - sctx->current_request = AES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_DECRYPT; - bctx->aes_opmode = SEP_AES_ECB; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + pr_debug("sep - doing aes ecb decrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_DECRYPT; + ta_ctx->aes_opmode = SEP_AES_ECB; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_ecb_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_aes_cbc_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( crypto_ablkcipher_reqtfm(req)); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes cbc encrypt\n"); - sctx->current_request = AES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_ENCRYPT; - bctx->aes_opmode = SEP_AES_CBC; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + pr_debug("sep - doing aes cbc encrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + pr_debug("tfm is %p sctx is %p and ta_ctx is %p\n", + crypto_ablkcipher_reqtfm(req), sctx, ta_ctx); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_ENCRYPT; + ta_ctx->aes_opmode = SEP_AES_CBC; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_aes_cbc_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( crypto_ablkcipher_reqtfm(req)); - dev_dbg(&sctx->sep_used->pdev->dev, "sep aes cbc decrypt\n"); - sctx->current_request = AES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->aes_encmode = SEP_AES_DECRYPT; - bctx->aes_opmode = SEP_AES_CBC; - bctx->init_opcode = SEP_AES_INIT_OPCODE; - bctx->block_opcode = SEP_AES_BLOCK_OPCODE; + pr_debug("sep - doing aes cbc decrypt\n"); + pr_debug("tfm is %p sctx is %p and ta_ctx is %p\n", + crypto_ablkcipher_reqtfm(req), sctx, ta_ctx); + + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = AES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->aes_encmode = SEP_AES_DECRYPT; + ta_ctx->aes_opmode = SEP_AES_CBC; + ta_ctx->init_opcode = SEP_AES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_AES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_aes_cbc_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, @@ -3304,7 +3589,7 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, struct crypto_tfm *ctfm = crypto_ablkcipher_tfm(tfm); u32 *flags = &ctfm->crt_flags; - dev_dbg(&sctx->sep_used->pdev->dev, "sep des setkey\n"); + pr_debug("sep des setkey\n"); switch (keylen) { case DES_KEY_SIZE: @@ -3317,7 +3602,7 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->des_nbr_keys = DES_KEY_3; break; default: - dev_dbg(&sctx->sep_used->pdev->dev, "invalid key size %x\n", + pr_debug("invalid key size %x\n", keylen); return -EINVAL; } @@ -3326,7 +3611,7 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, (sep_weak_key(key, keylen))) { *flags |= CRYPTO_TFM_RES_WEAK_KEY; - dev_warn(&sctx->sep_used->pdev->dev, "weak key\n"); + pr_debug("weak key\n"); return -EINVAL; } @@ -3335,7 +3620,6 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, sctx->keylen = keylen; /* Indicate to encrypt/decrypt function to send key to SEP */ sctx->key_sent = 0; - sctx->last_block = 0; return 0; } @@ -3343,153 +3627,149 @@ static int sep_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int sep_des_ebc_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des ecb encrypt\n"); - sctx->current_request = DES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_ENCRYPT; - bctx->des_opmode = SEP_DES_ECB; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + pr_debug("sep - doing des ecb encrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_ENCRYPT; + ta_ctx->des_opmode = SEP_DES_ECB; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_des_ebc_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des ecb decrypt\n"); - sctx->current_request = DES_ECB; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_DECRYPT; - bctx->des_opmode = SEP_DES_ECB; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + pr_debug("sep - doing des ecb decrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_ECB; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_DECRYPT; + ta_ctx->des_opmode = SEP_DES_ECB; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_ecb_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_des_cbc_encrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des cbc encrypt\n"); - sctx->current_request = DES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_ENCRYPT; - bctx->des_opmode = SEP_DES_CBC; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + pr_debug("sep - doing des cbc encrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_ENCRYPT; + ta_ctx->des_opmode = SEP_DES_CBC; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_encrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_encrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static int sep_des_cbc_decrypt(struct ablkcipher_request *req) { int error; - struct sep_block_ctx *bctx = ablkcipher_request_ctx(req); - struct sep_system_ctx *sctx = crypto_ablkcipher_ctx( - crypto_ablkcipher_reqtfm(req)); + int error1; + struct this_task_ctx *ta_ctx = ablkcipher_request_ctx(req); - dev_dbg(&sctx->sep_used->pdev->dev, "sep des cbc decrypt\n"); - sctx->current_request = DES_CBC; - sctx->current_hash_req = NULL; - sctx->current_cypher_req = req; - bctx->des_encmode = SEP_DES_DECRYPT; - bctx->des_opmode = SEP_DES_CBC; - bctx->init_opcode = SEP_DES_INIT_OPCODE; - bctx->block_opcode = SEP_DES_BLOCK_OPCODE; + pr_debug("sep - doing des ecb decrypt\n"); + /* Clear out task context */ + memset(ta_ctx, 0, sizeof(struct this_task_ctx)); + + ta_ctx->sep_used = sep_dev; + ta_ctx->current_request = DES_CBC; + ta_ctx->current_hash_req = NULL; + ta_ctx->current_cypher_req = req; + ta_ctx->des_encmode = SEP_DES_DECRYPT; + ta_ctx->des_opmode = SEP_DES_CBC; + ta_ctx->init_opcode = SEP_DES_INIT_OPCODE; + ta_ctx->block_opcode = SEP_DES_BLOCK_OPCODE; + + /* lock necessary so that only one entity touches the queues */ spin_lock_irq(&queue_lock); error = crypto_enqueue_request(&sep_queue, &req->base); + + if ((error != 0) && (error != -EINPROGRESS)) + pr_debug(" sep - crypto enqueue failed: %x\n", + error); + error1 = sep_submit_work(ta_ctx->sep_used->workqueue, + sep_dequeuer, (void *)&sep_queue); + if (error1) + pr_debug(" sep - workqueue submit failed: %x\n", + error1); spin_unlock_irq(&queue_lock); - - if ((error != 0) && (error != -EINPROGRESS)) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_decrypt cant enqueue\n"); - sep_crypto_release(sctx, error); - return error; - } - - error = sep_submit_work(sctx->sep_used->workqueue, sep_dequeuer, - (void *)&sep_queue); - if (error) { - dev_warn(&sctx->sep_used->pdev->dev, - "sep_des_cbc_decrypt cannot submit queue\n"); - sep_crypto_release(sctx, -EINVAL); - return -EINVAL; - } - return -EINPROGRESS; + /* We return result of crypto enqueue */ + return error; } static struct ahash_alg hash_algs[] = { @@ -3498,6 +3778,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_sha1_update, .final = sep_sha1_final, .digest = sep_sha1_digest, + .finup = sep_sha1_finup, .halg = { .digestsize = SHA1_DIGEST_SIZE, .base = { @@ -3520,6 +3801,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_md5_update, .final = sep_md5_final, .digest = sep_md5_digest, + .finup = sep_md5_finup, .halg = { .digestsize = MD5_DIGEST_SIZE, .base = { @@ -3542,6 +3824,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_sha224_update, .final = sep_sha224_final, .digest = sep_sha224_digest, + .finup = sep_sha224_finup, .halg = { .digestsize = SHA224_DIGEST_SIZE, .base = { @@ -3564,6 +3847,7 @@ static struct ahash_alg hash_algs[] = { .update = sep_sha256_update, .final = sep_sha256_final, .digest = sep_sha256_digest, + .finup = sep_sha256_finup, .halg = { .digestsize = SHA256_DIGEST_SIZE, .base = { @@ -3621,6 +3905,7 @@ static struct crypto_alg crypto_algs[] = { .max_keysize = AES_MAX_KEY_SIZE, .setkey = sep_aes_setkey, .encrypt = sep_aes_cbc_encrypt, + .ivsize = AES_BLOCK_SIZE, .decrypt = sep_aes_cbc_decrypt, } }, @@ -3661,6 +3946,7 @@ static struct crypto_alg crypto_algs[] = { .max_keysize = DES_KEY_SIZE, .setkey = sep_des_setkey, .encrypt = sep_des_cbc_encrypt, + .ivsize = DES_BLOCK_SIZE, .decrypt = sep_des_cbc_decrypt, } }, @@ -3714,7 +4000,8 @@ int sep_crypto_setup(void) crypto_init_queue(&sep_queue, SEP_QUEUE_LENGTH); - sep_dev->workqueue = create_workqueue("sep_crypto_workqueue"); + sep_dev->workqueue = create_singlethread_workqueue( + "sep_crypto_workqueue"); if (!sep_dev->workqueue) { dev_warn(&sep_dev->pdev->dev, "cant create workqueue\n"); return -ENOMEM; @@ -3723,7 +4010,6 @@ int sep_crypto_setup(void) i = 0; j = 0; - spin_lock_init(&sep_dev->busy_lock); spin_lock_init(&queue_lock); err = 0; diff --git a/drivers/staging/sep/sep_crypto.h b/drivers/staging/sep/sep_crypto.h index 52c58c483c5..155c3c9b87c 100644 --- a/drivers/staging/sep/sep_crypto.h +++ b/drivers/staging/sep/sep_crypto.h @@ -117,7 +117,7 @@ #define SEP_TRANSACTION_WAIT_TIME 5 -#define SEP_QUEUE_LENGTH 10 +#define SEP_QUEUE_LENGTH 2 /* Macros */ #ifndef __LITTLE_ENDIAN #define CHG_ENDIAN(val) \ @@ -270,9 +270,26 @@ struct sep_hash_private_context { u8 internal_context[sizeof(struct sep_hash_internal_context)]; }; +union key_t { + struct sep_des_key des; + u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS]; +}; + /* Context structures for crypto API */ -struct sep_block_ctx { - struct sep_device *sep; +/** + * Structure for this current task context + * This same structure is used for both hash + * and crypt in order to reduce duplicate code + * for stuff that is done for both hash operations + * and crypto operations. We cannot trust that the + * system context is not pulled out from under + * us during operation to operation, so all + * critical stuff such as data pointers must + * be in in a context that is exclusive for this + * particular task at hand. + */ +struct this_task_ctx { + struct sep_device *sep_used; u32 done; unsigned char iv[100]; enum des_enc_mode des_encmode; @@ -284,36 +301,7 @@ struct sep_block_ctx { size_t data_length; size_t ivlen; struct ablkcipher_walk walk; - struct sep_des_private_context des_private_ctx; - struct sep_aes_private_context aes_private_ctx; - }; - -struct sep_hash_ctx { - u32 done; - unsigned char *buf; - size_t buflen; - unsigned char *dgst; - int digest_size_words; - int digest_size_bytes; - int block_size_words; - int block_size_bytes; - struct scatterlist *sg; - enum hash_op_mode hash_opmode; - struct sep_hash_private_context hash_private_ctx; - }; - -struct sep_system_ctx { - struct sep_device *sep_used; - union key_t { - struct sep_des_key des; - u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS]; - } key; int i_own_sep; /* Do I have custody of the sep? */ - size_t keylen; - enum des_numkey des_nbr_keys; - enum aes_keysize aes_key_size; - u32 key_sent; /* Indicate if key is sent to sep */ - u32 last_block; /* Indicate that this is the final block */ struct sep_call_status call_status; struct build_dcb_struct_kernel dcb_input_data; struct sep_dma_context *dma_ctx; @@ -331,11 +319,34 @@ struct sep_system_ctx { struct ahash_request *current_hash_req; struct ablkcipher_request *current_cypher_req; enum type_of_request current_request; + int digest_size_words; + int digest_size_bytes; + int block_size_words; + int block_size_bytes; + enum hash_op_mode hash_opmode; enum hash_stage current_hash_stage; - int done_with_transaction; + /** + * Not that this is a pointer. The are_we_done_yet variable is + * allocated by the task function. This way, even if the kernel + * crypto infrastructure has grabbed the task structure out from + * under us, the task function can still see this variable. + */ + int *are_we_done_yet; unsigned long end_time; }; +struct sep_system_ctx { + union key_t key; + size_t keylen; + int key_sent; + enum des_numkey des_nbr_keys; + enum aes_keysize aes_key_size; + unsigned long end_time; + struct sep_des_private_context des_private_ctx; + struct sep_aes_private_context aes_private_ctx; + struct sep_hash_private_context hash_private_ctx; + }; + /* work queue structures */ struct sep_work_struct { struct work_struct work; diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h index 66d8e95523b..5f6a07f59dd 100644 --- a/drivers/staging/sep/sep_dev.h +++ b/drivers/staging/sep/sep_dev.h @@ -93,8 +93,7 @@ struct sep_device { enum hash_stage current_hash_stage; struct ahash_request *current_hash_req; struct ablkcipher_request *current_cypher_req; - struct sep_system_ctx *sctx; - spinlock_t busy_lock; + struct this_task_ctx *ta_ctx; struct workqueue_struct *workqueue; };