VOS_STATUS vos_decrypt_AES(v_U32_t cryptHandle, v_U8_t *pText, v_U8_t *pDecrypted, v_U8_t *pKey) { struct ecb_aes_result result; struct ablkcipher_request *req; struct crypto_ablkcipher *tfm; int ret = 0; char iv[IV_SIZE_AES_128]; struct scatterlist sg_in; struct scatterlist sg_out; init_completion(&result.completion); tfm = wcnss_wlan_crypto_alloc_ablkcipher( "cbc(aes)", 0, 0); if (IS_ERR(tfm)) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ablkcipher failed"); ret = PTR_ERR(tfm); goto err_tfm; } req = ablkcipher_request_alloc(tfm, GFP_KERNEL); if (!req) { VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "Failed to allocate request for cbc(aes)"); ret = -ENOMEM; goto err_req; } ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, ecb_aes_complete, &result); crypto_ablkcipher_clear_flags(tfm, ~0); ret = crypto_ablkcipher_setkey(tfm, pKey, KEY_SIZE_AES_128); if (ret) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_cipher_setkey failed"); goto err_setkey; } memset(iv, 0, IV_SIZE_AES_128); sg_init_one(&sg_in, pText, AES_BLOCK_SIZE); sg_init_one(&sg_out, pDecrypted, AES_BLOCK_SIZE); ablkcipher_request_set_crypt(req, &sg_in, &sg_out, AES_BLOCK_SIZE, iv); crypto_ablkcipher_decrypt(req); err_setkey: wcnss_wlan_ablkcipher_request_free(req); err_req: wcnss_wlan_crypto_free_ablkcipher(tfm); err_tfm: if (ret != 0) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"%s() call failed", __func__); return VOS_STATUS_E_FAULT; } return VOS_STATUS_SUCCESS; }
static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, u8 len) { struct mmc_request mrq = {NULL}; struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct scatterlist sg; u8 *data_buf; u8 *test_buf; int i, err; static u8 testdata_8bit[8] = { 0x55, 0xaa, 0, 0, 0, 0, 0, 0 }; static u8 testdata_4bit[4] = { 0x5a, 0, 0, 0 }; /* dma onto stack is unsafe/nonportable, but callers to this * routine normally provide temporary on-stack buffers ... */ data_buf = kmalloc(len, GFP_KERNEL); if (!data_buf) return -ENOMEM; if (len == 8) test_buf = testdata_8bit; else if (len == 4) test_buf = testdata_4bit; else { pr_err("%s: Invalid bus_width %d\n", mmc_hostname(host), len); kfree(data_buf); return -EINVAL; } if (opcode == MMC_BUS_TEST_W) memcpy(data_buf, test_buf, len); mrq.cmd = &cmd; mrq.data = &data; cmd.opcode = opcode; cmd.arg = 0; /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we * rely on callers to never use this with "native" calls for reading * CSD or CID. Native versions of those commands use the R2 type, * not R1 plus a data block. */ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; data.blksz = len; data.blocks = 1; if (opcode == MMC_BUS_TEST_R) data.flags = MMC_DATA_READ; else data.flags = MMC_DATA_WRITE; data.sg = &sg; data.sg_len = 1; sg_init_one(&sg, data_buf, len); mmc_wait_for_req(host, &mrq); err = 0; if (opcode == MMC_BUS_TEST_R) { for (i = 0; i < len / 4; i++) if ((test_buf[i] ^ data_buf[i]) != 0xff) { err = -EIO; break; } } kfree(data_buf); if (cmd.error) return cmd.error; if (data.error) return data.error; return err; }
static int tegra_crypt_rsa(struct tegra_crypto_ctx *ctx, struct tegra_rsa_req *rsa_req) { struct crypto_ahash *tfm = NULL; struct ahash_request *req = NULL; struct scatterlist sg[1]; char *result = NULL; void *hash_buff; int ret = 0; unsigned long *xbuf[XBUFSIZE]; struct tegra_crypto_completion rsa_complete; switch (rsa_req->algo) { case TEGRA_RSA512: req = ahash_request_alloc(ctx->rsa512_tfm, GFP_KERNEL); if (!req) { pr_err("alg: hash: Failed to allocate request for rsa512\n"); goto req_fail; } tfm = ctx->rsa512_tfm; break; case TEGRA_RSA1024: req = ahash_request_alloc(ctx->rsa1024_tfm, GFP_KERNEL); if (!req) { pr_err("alg: hash: Failed to allocate request for rsa1024\n"); goto req_fail; } tfm = ctx->rsa1024_tfm; break; case TEGRA_RSA1536: req = ahash_request_alloc(ctx->rsa1536_tfm, GFP_KERNEL); if (!req) { pr_err("alg: hash: Failed to allocate request for rsa1536\n"); goto req_fail; } tfm = ctx->rsa1536_tfm; break; case TEGRA_RSA2048: req = ahash_request_alloc(ctx->rsa2048_tfm, GFP_KERNEL); if (!req) { pr_err("alg: hash: Failed to allocate request for rsa2048\n"); goto req_fail; } tfm = ctx->rsa2048_tfm; break; default: goto req_fail; } ret = alloc_bufs(xbuf); if (ret < 0) { pr_err("alloc_bufs failed"); goto buf_fail; } init_completion(&rsa_complete.restart); result = kzalloc(rsa_req->keylen >> 16, GFP_KERNEL); if (!result) { pr_err("\nresult alloc fail\n"); goto result_fail; } hash_buff = xbuf[0]; memcpy(hash_buff, rsa_req->message, rsa_req->msg_len); sg_init_one(&sg[0], hash_buff, rsa_req->msg_len); if (!(rsa_req->keylen)) goto rsa_fail; if (!rsa_req->skip_key) { ret = crypto_ahash_setkey(tfm, rsa_req->key, rsa_req->keylen); if (ret) { pr_err("alg: hash: setkey failed\n"); goto rsa_fail; } } ahash_request_set_crypt(req, sg, result, rsa_req->msg_len); ret = crypto_ahash_digest(req); if (ret == -EINPROGRESS || ret == -EBUSY) { ret = wait_for_completion_interruptible(&rsa_complete.restart); if (!ret) ret = rsa_complete.req_err; INIT_COMPLETION(rsa_complete.restart); } if (ret) { pr_err("alg: hash: digest failed\n"); goto rsa_fail; } ret = copy_to_user((void __user *)rsa_req->result, (const void *)result, crypto_ahash_digestsize(tfm)); if (ret) { ret = -EFAULT; pr_err("alg: hash: copy_to_user failed (%d)\n", ret); } rsa_fail: kfree(result); result_fail: free_bufs(xbuf); buf_fail: ahash_request_free(req); req_fail: return ret; }
/** * iscsi_tcp_segment_done - check whether the segment is complete * @tcp_conn: iscsi tcp connection * @segment: iscsi segment to check * @recv: set to one of this is called from the recv path * @copied: number of bytes copied * * Check if we're done receiving this segment. If the receive * buffer is full but we expect more data, move on to the * next entry in the scatterlist. * * If the amount of data we received isn't a multiple of 4, * we will transparently receive the pad bytes, too. * * This function must be re-entrant. */ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, struct iscsi_segment *segment, int recv, unsigned copied) { struct scatterlist sg; unsigned int pad; ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copied %u %u size %u %s\n", segment->copied, copied, segment->size, recv ? "recv" : "xmit"); if (segment->hash && copied) { /* * If a segment is kmapd we must unmap it before sending * to the crypto layer since that will try to kmap it again. */ iscsi_tcp_segment_unmap(segment); if (!segment->data) { sg_init_table(&sg, 1); sg_set_page(&sg, sg_page(segment->sg), copied, segment->copied + segment->sg_offset + segment->sg->offset); } else sg_init_one(&sg, segment->data + segment->copied, copied); crypto_hash_update(segment->hash, &sg, copied); } segment->copied += copied; if (segment->copied < segment->size) { iscsi_tcp_segment_map(segment, recv); return 0; } segment->total_copied += segment->copied; segment->copied = 0; segment->size = 0; /* Unmap the current scatterlist page, if there is one. */ iscsi_tcp_segment_unmap(segment); /* Do we have more scatterlist entries? */ ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "total copied %u total size %u\n", segment->total_copied, segment->total_size); if (segment->total_copied < segment->total_size) { /* Proceed to the next entry in the scatterlist. */ iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg), 0); iscsi_tcp_segment_map(segment, recv); BUG_ON(segment->size == 0); return 0; } /* Do we need to handle padding? */ if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) { pad = iscsi_padding(segment->total_copied); if (pad != 0) { ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "consume %d pad bytes\n", pad); segment->total_size += pad; segment->size = pad; segment->data = segment->padbuf; return 0; } } /* * Set us up for transferring the data digest. hdr digest * is completely handled in hdr done function. */ if (segment->hash) { crypto_hash_final(segment->hash, segment->digest); iscsi_tcp_segment_splice_digest(segment, recv ? segment->recv_digest : segment->digest); return 0; } return 1; }
static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e, int (*iterator) (struct pohmelfs_crypto_engine *e, struct scatterlist *dst, struct scatterlist *src)) { void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size; unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size; struct netfs_cmd *cmd = data; unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx; struct scatterlist sg_src, sg_dst; int err; while (size) { cmd = data; cmd_cmd = __be16_to_cpu(cmd->cmd); csize = __be32_to_cpu(cmd->size); cmd->iv = __cpu_to_be64(e->iv); if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE) csize = __be16_to_cpu(cmd->ext); sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd); // dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n", ; data += sz; size -= sz; sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd)); sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd)); err = iterator(e, &sg_dst, &sg_src); if (err) return err; } if (!pages) return 0; dpage_idx = 0; for (i = 0; i < t->page_num; ++i) { struct page *page = t->pages[i]; struct page *dpage = e->pages[dpage_idx]; if (!page) continue; sg_init_table(&sg_src, 1); sg_init_table(&sg_dst, 1); sg_set_page(&sg_src, page, page_private(page), 0); sg_set_page(&sg_dst, dpage, page_private(page), 0); err = iterator(e, &sg_dst, &sg_src); if (err) return err; pages--; if (!pages) break; dpage_idx++; } return 0; }
static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, struct rpmsg_hdr *msg, unsigned int len) { struct rpmsg_endpoint *ept; struct scatterlist sg; int err; dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n", msg->src, msg->dst, msg->len, msg->flags, msg->reserved); print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, msg, sizeof(*msg) + msg->len, true); /* * We currently use fixed-sized buffers, so trivially sanitize * the reported payload length. */ if (len > RPMSG_BUF_SIZE || msg->len > (len - sizeof(struct rpmsg_hdr))) { dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); return -EINVAL; } /* use the dst addr to fetch the callback of the appropriate user */ mutex_lock(&vrp->endpoints_lock); ept = idr_find(&vrp->endpoints, msg->dst); /* let's make sure no one deallocates ept while we use it */ if (ept) kref_get(&ept->refcount); mutex_unlock(&vrp->endpoints_lock); if (ept) { /* make sure ept->cb doesn't go away while we use it */ mutex_lock(&ept->cb_lock); if (ept->cb) ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src); mutex_unlock(&ept->cb_lock); /* farewell, ept, we don't need you anymore */ kref_put(&ept->refcount, __ept_release); } else dev_warn(dev, "msg received with no recipient\n"); /* publish the real size of the buffer */ sg_init_one(&sg, msg, RPMSG_BUF_SIZE); /* add the buffer back to the remote processor's virtqueue */ err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, msg, GFP_KERNEL); if (err < 0) { dev_err(dev, "failed to add a virtqueue buffer: %d\n", err); return err; } return 0; }
static int simple_sd_ioctl_multi_rw(struct msdc_ioctl *msdc_ctl) { char l_buf[512]; struct scatterlist msdc_sg; struct mmc_data msdc_data; struct mmc_command msdc_cmd; struct mmc_command msdc_stop; int ret = 0; #ifdef MTK_MSDC_USE_CMD23 struct mmc_command msdc_sbc; #endif struct mmc_request msdc_mrq; struct msdc_host *host_ctl; if(!msdc_ctl) return -EINVAL; if(msdc_ctl->total_size <= 0) return -EINVAL; host_ctl = mtk_msdc_host[msdc_ctl->host_num]; BUG_ON(!host_ctl); BUG_ON(!host_ctl->mmc); BUG_ON(!host_ctl->mmc->card); mmc_claim_host(host_ctl->mmc); #if DEBUG_MMC_IOCTL pr_debug("user want access %d partition\n", msdc_ctl->partition); #endif ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf); if (ret) { pr_debug("mmc_send_ext_csd error, multi rw\n"); goto multi_end; } #ifdef CONFIG_MTK_EMMC_SUPPORT switch (msdc_ctl->partition) { case EMMC_PART_BOOT1: if (0x1 != (l_buf[179] & 0x7)) { /* change to access boot partition 1 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x1; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; case EMMC_PART_BOOT2: if (0x2 != (l_buf[179] & 0x7)) { /* change to access boot partition 2 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x2; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; default: /* make sure access partition is user data area */ if (0 != (l_buf[179] & 0x7)) { /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; } #endif if(msdc_ctl->total_size > host_ctl->mmc->max_seg_size) { //64*1024){ msdc_ctl->result = -1; goto multi_end; } memset(&msdc_data, 0, sizeof(struct mmc_data)); memset(&msdc_mrq, 0, sizeof(struct mmc_request)); memset(&msdc_cmd, 0, sizeof(struct mmc_command)); memset(&msdc_stop, 0, sizeof(struct mmc_command)); #ifdef MTK_MSDC_USE_CMD23 memset(&msdc_sbc, 0, sizeof(struct mmc_command)); #endif msdc_mrq.cmd = &msdc_cmd; msdc_mrq.data = &msdc_data; if (msdc_ctl->trans_type) dma_force[host_ctl->id] = FORCE_IN_DMA; else dma_force[host_ctl->id] = FORCE_IN_PIO; if (msdc_ctl->iswrite) { msdc_data.flags = MMC_DATA_WRITE; msdc_cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_from_user(sg_msdc_multi_buffer, msdc_ctl->buffer, msdc_ctl->total_size)) { dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto multi_end; } } else { /* called from other kernel module */ memcpy(sg_msdc_multi_buffer, msdc_ctl->buffer, msdc_ctl->total_size); } } else { msdc_data.flags = MMC_DATA_READ; msdc_cmd.opcode = MMC_READ_MULTIPLE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; memset(sg_msdc_multi_buffer, 0, msdc_ctl->total_size); } #ifdef MTK_MSDC_USE_CMD23 if ((mmc_card_mmc(host_ctl->mmc->card) || (mmc_card_sd(host_ctl->mmc->card) && host_ctl->mmc->card->scr.cmds & SD_SCR_CMD23_SUPPORT)) && !(host_ctl->mmc->card->quirks & MMC_QUIRK_BLK_NO_CMD23)) { msdc_mrq.sbc = &msdc_sbc; msdc_mrq.sbc->opcode = MMC_SET_BLOCK_COUNT; #ifdef MTK_MSDC_USE_CACHE /* if ioctl access cacheable partition data, there is on flush mechanism in msdc driver * so do reliable write .*/ if (mmc_card_mmc(host_ctl->mmc->card) && (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1) && (msdc_cmd.opcode == MMC_WRITE_MULTIPLE_BLOCK)) msdc_mrq.sbc->arg = msdc_data.blocks | (1 << 31); else msdc_mrq.sbc->arg = msdc_data.blocks; #else msdc_mrq.sbc->arg = msdc_data.blocks; #endif msdc_mrq.sbc->flags = MMC_RSP_R1 | MMC_CMD_AC; } #endif msdc_cmd.arg = msdc_ctl->address; if (!mmc_card_blockaddr(host_ctl->mmc->card)) { pr_debug("this device use byte address!!\n"); msdc_cmd.arg <<= 9; } msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; msdc_stop.opcode = MMC_STOP_TRANSMISSION; msdc_stop.arg = 0; msdc_stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; msdc_data.stop = &msdc_stop; msdc_data.blksz = 512; msdc_data.sg = &msdc_sg; msdc_data.sg_len = 1; #if DEBUG_MMC_IOCTL pr_debug("total size is %d\n", msdc_ctl->total_size); #endif sg_init_one(&msdc_sg, sg_msdc_multi_buffer, msdc_ctl->total_size); mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card); mmc_wait_for_req(host_ctl->mmc, &msdc_mrq); if (!msdc_ctl->iswrite) { if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_to_user(msdc_ctl->buffer, sg_msdc_multi_buffer, msdc_ctl->total_size)) { dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto multi_end; } } else { /* called from other kernel module */ memcpy(msdc_ctl->buffer, sg_msdc_multi_buffer, msdc_ctl->total_size); } } /* clear the global buffer of R/W IOCTL */ memset(sg_msdc_multi_buffer, 0 , msdc_ctl->total_size); if (msdc_ctl->partition) { ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf); if (ret) { pr_debug("mmc_send_ext_csd error, multi rw2\n"); goto multi_end; } if (l_buf[179] & 0x7) { /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } } multi_end: mmc_release_host(host_ctl->mmc); if (ret) msdc_ctl->result = ret; if (msdc_cmd.error) msdc_ctl->result = msdc_cmd.error; if (msdc_data.error) { msdc_ctl->result = msdc_data.error; } else { msdc_ctl->result = 0; } dma_force[host_ctl->id] = FORCE_NOTHING; return msdc_ctl->result; }
static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { unsigned int digestsize = crypto_ahash_digestsize(tfm); struct qce_sha_ctx *ctx = crypto_tfm_ctx(&tfm->base); struct qce_ahash_result result; struct ahash_request *req; struct scatterlist sg; unsigned int blocksize; struct crypto_ahash *ahash_tfm; u8 *buf; int ret; const char *alg_name; blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); memset(ctx->authkey, 0, sizeof(ctx->authkey)); if (keylen <= blocksize) { memcpy(ctx->authkey, key, keylen); return 0; } if (digestsize == SHA1_DIGEST_SIZE) alg_name = "sha1-qce"; else if (digestsize == SHA256_DIGEST_SIZE) alg_name = "sha256-qce"; else return -EINVAL; ahash_tfm = crypto_alloc_ahash(alg_name, CRYPTO_ALG_TYPE_AHASH, CRYPTO_ALG_TYPE_AHASH_MASK); if (IS_ERR(ahash_tfm)) return PTR_ERR(ahash_tfm); req = ahash_request_alloc(ahash_tfm, GFP_KERNEL); if (!req) { ret = -ENOMEM; goto err_free_ahash; } init_completion(&result.completion); ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, qce_digest_complete, &result); crypto_ahash_clear_flags(ahash_tfm, ~0); buf = kzalloc(keylen + QCE_MAX_ALIGN_SIZE, GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto err_free_req; } memcpy(buf, key, keylen); sg_init_one(&sg, buf, keylen); ahash_request_set_crypt(req, &sg, ctx->authkey, keylen); ret = crypto_ahash_digest(req); if (ret == -EINPROGRESS || ret == -EBUSY) { ret = wait_for_completion_interruptible(&result.completion); if (!ret) ret = result.error; } if (ret) crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); kfree(buf); err_free_req: ahash_request_free(req); err_free_ahash: crypto_free_ahash(ahash_tfm); return ret; }
/* * CC-MAC function WUSB1.0[6.5] * * Take a data string and produce the encrypted CBC Counter-mode MIC * * Note the names for most function arguments are made to (more or * less) match those used in the pseudo-function definition given in * WUSB1.0[6.5]. * * @tfm_cbc: CBC(AES) blkcipher handle (initialized) * * @tfm_aes: AES cipher handle (initialized) * * @mic: buffer for placing the computed MIC (Message Integrity * Code). This is exactly 8 bytes, and we expect the buffer to * be at least eight bytes in length. * * @key: 128 bit symmetric key * * @n: CCM nonce * * @a: ASCII string, 14 bytes long (I guess zero padded if needed; * we use exactly 14 bytes). * * @b: data stream to be processed; cannot be a global or const local * (will confuse the scatterlists) * * @blen: size of b... * * Still not very clear how this is done, but looks like this: we * create block B0 (as WUSB1.0[6.5] says), then we AES-crypt it with * @key. We bytewise xor B0 with B1 (1) and AES-crypt that. Then we * take the payload and divide it in blocks (16 bytes), xor them with * the previous crypto result (16 bytes) and crypt it, repeat the next * block with the output of the previous one, rinse wash (I guess this * is what AES CBC mode means...but I truly have no idea). So we use * the CBC(AES) blkcipher, that does precisely that. The IV (Initial * Vector) is 16 bytes and is set to zero, so * * See rfc3610. Linux crypto has a CBC implementation, but the * documentation is scarce, to say the least, and the example code is * so intricated that is difficult to understand how things work. Most * of this is guess work -- bite me. * * (1) Created as 6.5 says, again, using as l(a) 'Blen + 14', and * using the 14 bytes of @a to fill up * b1.{mac_header,e0,security_reserved,padding}. * <<<<<<< HEAD * NOTE: The definition of l(a) in WUSB1.0[6.5] vs the definition of ======= * NOTE: The definiton of l(a) in WUSB1.0[6.5] vs the definition of >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a * l(m) is orthogonal, they bear no relationship, so it is not * in conflict with the parameter's relation that * WUSB1.0[6.4.2]) defines. * * NOTE: WUSB1.0[A.1]: Host Nonce is missing a nibble? (1e); fixed in * first errata released on 2005/07. * * NOTE: we need to clean IV to zero at each invocation to make sure * we start with a fresh empty Initial Vector, so that the CBC * works ok. * * NOTE: blen is not aligned to a block size, we'll pad zeros, that's * what sg[4] is for. Maybe there is a smarter way to do this. */ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, struct crypto_cipher *tfm_aes, void *mic, const struct aes_ccm_nonce *n, const struct aes_ccm_label *a, const void *b, size_t blen) { int result = 0; struct blkcipher_desc desc; struct aes_ccm_b0 b0; struct aes_ccm_b1 b1; struct aes_ccm_a ax; struct scatterlist sg[4], sg_dst; void *iv, *dst_buf; size_t ivsize, dst_size; const u8 bzero[16] = { 0 }; size_t zero_padding; /* * These checks should be compile time optimized out * ensure @a fills b1's mac_header and following fields */ WARN_ON(sizeof(*a) != sizeof(b1) - sizeof(b1.la)); WARN_ON(sizeof(b0) != sizeof(struct aes_ccm_block)); WARN_ON(sizeof(b1) != sizeof(struct aes_ccm_block)); WARN_ON(sizeof(ax) != sizeof(struct aes_ccm_block)); result = -ENOMEM; zero_padding = sizeof(struct aes_ccm_block) - blen % sizeof(struct aes_ccm_block); zero_padding = blen % sizeof(struct aes_ccm_block); if (zero_padding) zero_padding = sizeof(struct aes_ccm_block) - zero_padding; dst_size = blen + sizeof(b0) + sizeof(b1) + zero_padding; dst_buf = kzalloc(dst_size, GFP_KERNEL); if (dst_buf == NULL) { printk(KERN_ERR "E: can't alloc destination buffer\n"); goto error_dst_buf; } iv = crypto_blkcipher_crt(tfm_cbc)->iv; ivsize = crypto_blkcipher_ivsize(tfm_cbc); memset(iv, 0, ivsize); /* Setup B0 */ b0.flags = 0x59; /* Format B0 */ b0.ccm_nonce = *n; b0.lm = cpu_to_be16(0); /* WUSB1.0[6.5] sez l(m) is 0 */ /* Setup B1 * * The WUSB spec is anything but clear! WUSB1.0[6.5] * says that to initialize B1 from A with 'l(a) = blen + * 14'--after clarification, it means to use A's contents * for MAC Header, EO, sec reserved and padding. */ b1.la = cpu_to_be16(blen + 14); memcpy(&b1.mac_header, a, sizeof(*a)); sg_init_table(sg, ARRAY_SIZE(sg)); sg_set_buf(&sg[0], &b0, sizeof(b0)); sg_set_buf(&sg[1], &b1, sizeof(b1)); sg_set_buf(&sg[2], b, blen); /* 0 if well behaved :) */ sg_set_buf(&sg[3], bzero, zero_padding); sg_init_one(&sg_dst, dst_buf, dst_size); desc.tfm = tfm_cbc; desc.flags = 0; result = crypto_blkcipher_encrypt(&desc, &sg_dst, sg, dst_size); if (result < 0) { printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n", result); goto error_cbc_crypt; } /* Now we crypt the MIC Tag (*iv) with Ax -- values per WUSB1.0[6.5] * The procedure is to AES crypt the A0 block and XOR the MIC <<<<<<< HEAD * Tag against it; we only do the first 8 bytes and place it ======= * Tag agains it; we only do the first 8 bytes and place it >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a * directly in the destination buffer. * * POS Crypto API: size is assumed to be AES's block size. * Thanks for documenting it -- tip taken from airo.c */ ax.flags = 0x01; /* as per WUSB 1.0 spec */ ax.ccm_nonce = *n; ax.counter = 0; crypto_cipher_encrypt_one(tfm_aes, (void *)&ax, (void *)&ax); bytewise_xor(mic, &ax, iv, 8); result = 8; error_cbc_crypt: kfree(dst_buf); error_dst_buf: return result; }
int mmc_send_tuning(struct mmc_host *host) { struct mmc_request mrq = {NULL}; struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct scatterlist sg; struct mmc_ios *ios = &host->ios; const u8 *tuning_block_pattern; int size, err = 0; u8 *data_buf; u32 opcode; if (ios->bus_width == MMC_BUS_WIDTH_8) { tuning_block_pattern = tuning_blk_pattern_8bit; size = sizeof(tuning_blk_pattern_8bit); opcode = MMC_SEND_TUNING_BLOCK_HS200; } else if (ios->bus_width == MMC_BUS_WIDTH_4) { tuning_block_pattern = tuning_blk_pattern_4bit; size = sizeof(tuning_blk_pattern_4bit); opcode = MMC_SEND_TUNING_BLOCK; } else return -EINVAL; data_buf = kzalloc(size, GFP_KERNEL); if (!data_buf) return -ENOMEM; mrq.cmd = &cmd; mrq.data = &data; cmd.opcode = opcode; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; data.blksz = size; data.blocks = 1; data.flags = MMC_DATA_READ; /* * According to the tuning specs, Tuning process * is normally shorter 40 executions of CMD19, * and timeout value should be shorter than 150 ms */ data.timeout_ns = 150 * NSEC_PER_MSEC; data.sg = &sg; data.sg_len = 1; sg_init_one(&sg, data_buf, size); mmc_wait_for_req(host, &mrq); if (cmd.error) { err = cmd.error; goto out; } if (data.error) { err = data.error; goto out; } if (memcmp(data_buf, tuning_block_pattern, size)) err = -EIO; out: kfree(data_buf); return err; }
static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb) { sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr)); }
/*---------------------------------------------------------------------------*/ static int xio_server_main(void *data) { char **argv = (char **)data; struct xio_server *server; /* server portal */ struct server_data *server_data; char url[256]; struct xio_context_params ctx_params; struct xio_context *ctx; int i; struct xio_vmsg *omsg; void *buf = NULL; unsigned long data_len = 0; atomic_add(2, &module_state); server_data = vzalloc(sizeof(*server_data)); if (!server_data) { /*pr_err("server_data alloc failed\n");*/ return 0; } /* create thread context for the server */ memset(&ctx_params, 0, sizeof(ctx_params)); ctx_params.flags = XIO_LOOP_GIVEN_THREAD; ctx_params.worker = current; ctx = xio_context_create(&ctx_params, 0, -1); if (!ctx) { vfree(server_data); pr_err("context open filed\n"); return 0; } server_data->ctx = ctx; /* create "hello world" message */ if (argv[3] != NULL && kstrtoul(argv[3], 0, &data_len)) { /* check, convert and assign data_len */ data_len = 0; } for (i = 0; i < QUEUE_DEPTH; i++) { xio_reinit_msg(&server_data->rsp[i]); omsg = &server_data->rsp[i].out; /* header */ server_data->rsp[i].out.header.iov_base = kstrdup("hello world header rsp 1", GFP_KERNEL); server_data->rsp[i].out.header.iov_len = strlen((const char *) server_data->rsp[i].out.header.iov_base) + 1; /* iovec[0]*/ sg_alloc_table(&omsg->data_tbl, 64, GFP_KERNEL); /* currently only one entry */ xio_init_vmsg(omsg, 1); /* one entry (max_nents) */ if (data_len < max_data_len) { /* small msgs */ buf = kstrdup("hello world iovec rsp", GFP_KERNEL); } else { /* big msgs */ if (!buf) { pr_info("allocating xio memory...\n"); buf = kmalloc(data_len, GFP_KERNEL); memcpy(buf, "hello world iovec rsp", 22); } } sg_init_one(omsg->data_tbl.sgl, buf, strlen(buf) + 1); /* orig_nents is 64 */ vmsg_sglist_set_nents(omsg, 1); } /* create url to connect to */ sprintf(url, "%s://%s:%s", argv[4], argv[1], argv[2]); /* bind a listener server to a portal/url */ server = xio_bind(ctx, &server_ops, url, NULL, 0, server_data); if (server) { pr_info("listen to %s\n", url); g_server_data = server_data; if (atomic_add_unless(&module_state, 4, 0x83)) xio_context_run_loop(ctx); atomic_sub(4, &module_state); /* normal exit phase */ pr_info("exit signaled\n"); /* free the server */ xio_unbind(server); } /* free the message */ for (i = 0; i < QUEUE_DEPTH; i++) { kfree(server_data->rsp[i].out.header.iov_base); if (data_len < max_data_len) { /* Currently need to release only one entry */ kfree(sg_virt(server_data->rsp[i].out.data_tbl.sgl)); } xio_fini_vmsg(&server_data->rsp[i].out); } if (buf){ pr_info("freeing xio memory...\n"); kfree(buf); buf = NULL; } /* free the context */ xio_context_destroy(ctx); vfree(server_data); complete_and_exit(&cleanup_complete, 0); return 0; }
static int run_test_case(const struct eme2_test_case *c, unsigned int number) { int err = 0; int failed = 0; struct crypto_ablkcipher *cipher = NULL; struct ablkcipher_request *req = NULL; u8 *buffer = NULL; struct scatterlist sg[1]; buffer = kmalloc(c->plaintext_len, GFP_KERNEL); if (!buffer) { printk("eme2_test: ERROR allocating buffer!\n"); goto out; } sg_init_one(sg, buffer, c->plaintext_len); cipher = crypto_alloc_ablkcipher("eme2(aes)", 0, 0); if (IS_ERR(cipher)) { printk("eme2_test: ERROR allocating cipher!\n"); err = PTR_ERR(cipher); cipher = NULL; goto out; } err = crypto_ablkcipher_setkey(cipher, c->key, c->key_len); if (err) { printk("eme2_test: ERROR setting key!\n"); goto out; } req = ablkcipher_request_alloc(cipher, GFP_KERNEL); if (IS_ERR(req)) { printk("eme2_test: ERROR allocating request!\n"); err = PTR_ERR(req); req = NULL; goto out; } ablkcipher_request_set_tfm(req, cipher); ablkcipher_request_set_crypt(req, sg, sg, c->plaintext_len, (u8 *)c->assoc_data); memcpy(buffer, c->plaintext, c->plaintext_len); err = eme2_encrypt_sync(req, c->assoc_data_len); if (err) { printk("eme2_test: ERROR encrypting!\n"); goto out; } if (memcmp(buffer, c->ciphertext, c->plaintext_len) != 0) { failed += 1; printk("eme2_test: encryption-%u: Testcase failed!\n", number); } memcpy(buffer, c->ciphertext, c->plaintext_len); err = eme2_decrypt_sync(req, c->assoc_data_len); if (err) { printk("eme2_test: ERROR decrypting!\n"); goto out; } if (memcmp(buffer, c->plaintext, c->plaintext_len) != 0) { failed += 1; printk("eme2_test: decryption-%u: Testcase failed!\n", number); } out: if (buffer) kfree(buffer); if (cipher) crypto_free_ablkcipher(cipher); if (req) ablkcipher_request_free(req); return err < 0 ? err : failed; }
u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype) { s32 checksum_type; char tokhdrbuf[25]; char cksumdata[16]; struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf}; int tokenlen = 0; unsigned char *ptr; s32 now; int ctxelen = 0, ctxzbit = 0; int md5elen = 0, md5zbit = 0; now = jiffies; if (ctx->ctx_id.len != 16) { dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n", ctx->ctx_id.len); goto out_err; } if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { dprintk("RPC: gss_spkm3_seal: unsupported I-ALG " "algorithm. only support hmac-md5 I-ALG.\n"); goto out_err; } else checksum_type = CKSUMTYPE_HMAC_MD5; if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) { dprintk("RPC: gss_spkm3_seal: unsupported C-ALG " "algorithm\n"); goto out_err; } if (toktype == SPKM_MIC_TOK) { /* Calculate checksum over the mic-header */ asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, ctxelen, ctxzbit); if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key, (char *)mic_hdr.data, mic_hdr.len, text, 0, &md5cksum)) goto out_err; asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit); tokenlen = 10 + ctxelen + 1 + md5elen + 1; /* Create token header using generic routines */ token->len = g_token_size(&ctx->mech_used, tokenlen + 2); ptr = token->data; g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr); spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit); } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */ dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK " "not supported\n"); goto out_err; } return GSS_S_COMPLETE; out_err: token->data = NULL; token->len = 0; return GSS_S_FAILURE; } static int spkm3_checksummer(struct scatterlist *sg, void *data) { struct hash_desc *desc = data; return crypto_hash_update(desc, sg, sg->length); } /* checksum the plaintext data and hdrlen bytes of the token header */ s32 make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header, unsigned int hdrlen, struct xdr_buf *body, unsigned int body_offset, struct xdr_netobj *cksum) { char *cksumname; struct hash_desc desc; struct scatterlist sg[1]; int err; switch (cksumtype) { case CKSUMTYPE_HMAC_MD5: cksumname = "hmac(md5)"; break; default: dprintk("RPC: spkm3_make_checksum:" " unsupported checksum %d", cksumtype); return GSS_S_FAILURE; } if (key->data == NULL || key->len <= 0) return GSS_S_FAILURE; desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(desc.tfm)) return GSS_S_FAILURE; cksum->len = crypto_hash_digestsize(desc.tfm); desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; err = crypto_hash_setkey(desc.tfm, key->data, key->len); if (err) goto out; err = crypto_hash_init(&desc); if (err) goto out; sg_init_one(sg, header, hdrlen); crypto_hash_update(&desc, sg, sg->length); xdr_process_buf(body, body_offset, body->len - body_offset, spkm3_checksummer, &desc); crypto_hash_final(&desc, cksum->data); out: crypto_free_hash(desc.tfm); return err ? GSS_S_FAILURE : 0; }
int fmp_run_AES_CBC_MCT(struct fmp_info *info, struct fcrypt *fcr, struct kernel_crypt_op *kcop) { struct device *dev = info->dev; struct csession *ses_ptr; struct crypt_op *cop = &kcop->cop; char **Ct = 0; char **Pt = 0; int ret = 0, k = 0; if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) { dev_err(dev, "invalid operation op=%u\n", cop->op); return -EINVAL; } /* this also enters ses_ptr->sem */ ses_ptr = fmp_get_session_by_sid(fcr, cop->ses); if (unlikely(!ses_ptr)) { dev_err(dev, "invalid session ID=0x%08X\n", cop->ses); return -EINVAL; } if (cop->len > PAGE_SIZE) { dev_err(dev, "Invalid input length. len = %d\n", cop->len); return -EINVAL; } if (ses_ptr->cdata.init != 0) { int blocksize = ses_ptr->cdata.blocksize; if (unlikely(cop->len % blocksize)) { dev_err(dev, "data size (%u) isn't a multiple " "of block size (%u)\n", cop->len, blocksize); ret = -EINVAL; goto out_unlock; } fmpdev_cipher_set_iv(info, &ses_ptr->cdata, kcop->iv, 16); } if (likely(cop->len)) { if (cop->flags & COP_FLAG_AES_CBC_MCT) { // do MCT here char *data; char __user *src, *dst, *secondLast; struct scatterlist sg; size_t nbytes, bufsize; int ret = 0; int y = 0; nbytes = cop->len; data = (char *)__get_free_page(GFP_KERNEL); if (unlikely(!data)) { dev_err(dev, "Error getting free page.\n"); return -ENOMEM; } Pt = (char**)kmalloc(1000 * sizeof(char*), GFP_KERNEL); for (k=0; k<1000; k++) Pt[k]= (char*)kmalloc(nbytes, GFP_KERNEL); Ct = (char**)kmalloc(1000 * sizeof(char*), GFP_KERNEL); for (k=0; k<1000; k++) Ct[k]= (char*)kmalloc(nbytes, GFP_KERNEL); bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes; src = cop->src; dst = cop->dst; secondLast = cop->secondLastEncodedData; if (unlikely(copy_from_user(data, src, nbytes))) { printk(KERN_ERR "Error copying %d bytes from user address %p.\n", (int)nbytes, src); ret = -EFAULT; goto out_err; } sg_init_one(&sg, data, nbytes); for (y = 0; y < 1000; y++) { memcpy(Pt[y], data, nbytes); ret = fmp_n_crypt(info, ses_ptr, cop, &sg, &sg, nbytes); memcpy(Ct[y], data, nbytes); if (y == 998) { if (unlikely(copy_to_user(secondLast, data, nbytes))) printk(KERN_ERR "unable to copy second last data for AES_CBC_MCT\n"); else printk(KERN_ERR "KAMAL copied secondlast data\n"); } if( y == 0) { memcpy(data, kcop->iv, kcop->ivlen); } else { if(y != 999) memcpy(data, Ct[y-1], nbytes); } if (unlikely(ret)) { printk(KERN_ERR "fmp_n_crypt failed.\n"); goto out_err; } if (cop->op == COP_ENCRYPT) fmpdev_cipher_set_iv(info, &ses_ptr->cdata, Ct[y], 16); else if (cop->op == COP_DECRYPT) fmpdev_cipher_set_iv(info, &ses_ptr->cdata, Pt[y], 16); } // for loop if (ses_ptr->cdata.init != 0) { if (unlikely(copy_to_user(dst, data, nbytes))) { printk(KERN_ERR "could not copy to user.\n"); ret = -EFAULT; goto out_err; } } for (k=0; k<1000; k++) { kfree(Ct[k]); kfree(Pt[k]); } kfree(Ct); kfree(Pt); free_page((unsigned long)data); } else goto out_unlock; } out_unlock: fmp_put_session(ses_ptr); return ret; out_err: fmp_put_session(ses_ptr); dev_info(dev, "CryptoAPI failure: %d\n", ret); return ret; }
static int chap_server_compute_md5( struct iscsi_conn *conn, struct iscsi_node_auth *auth, char *nr_in_ptr, char *nr_out_ptr, unsigned int *nr_out_len) { char *endptr; unsigned long id; unsigned char id_as_uchar; unsigned char digest[MD5_SIGNATURE_SIZE]; unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2]; unsigned char identifier[10], *challenge = NULL; unsigned char *challenge_binhex = NULL; unsigned char client_digest[MD5_SIGNATURE_SIZE]; unsigned char server_digest[MD5_SIGNATURE_SIZE]; unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; struct iscsi_chap *chap = conn->auth_protocol; struct crypto_hash *tfm; struct hash_desc desc; struct scatterlist sg; int auth_ret = -1, ret, challenge_len; memset(identifier, 0, 10); memset(chap_n, 0, MAX_CHAP_N_SIZE); memset(chap_r, 0, MAX_RESPONSE_LENGTH); memset(digest, 0, MD5_SIGNATURE_SIZE); memset(response, 0, MD5_SIGNATURE_SIZE * 2 + 2); memset(client_digest, 0, MD5_SIGNATURE_SIZE); memset(server_digest, 0, MD5_SIGNATURE_SIZE); challenge = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL); if (!challenge) { pr_err("Unable to allocate challenge buffer\n"); goto out; } challenge_binhex = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL); if (!challenge_binhex) { pr_err("Unable to allocate challenge_binhex buffer\n"); goto out; } /* * Extract CHAP_N. */ if (extract_param(nr_in_ptr, "CHAP_N", MAX_CHAP_N_SIZE, chap_n, &type) < 0) { pr_err("Could not find CHAP_N.\n"); goto out; } if (type == HEX) { pr_err("Could not find CHAP_N.\n"); goto out; } if (memcmp(chap_n, auth->userid, strlen(auth->userid)) != 0) { pr_err("CHAP_N values do not match!\n"); goto out; } pr_debug("[server] Got CHAP_N=%s\n", chap_n); /* * Extract CHAP_R. */ if (extract_param(nr_in_ptr, "CHAP_R", MAX_RESPONSE_LENGTH, chap_r, &type) < 0) { pr_err("Could not find CHAP_R.\n"); goto out; } if (type != HEX) { pr_err("Could not find CHAP_R.\n"); goto out; } pr_debug("[server] Got CHAP_R=%s\n", chap_r); chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { pr_err("Unable to allocate struct crypto_hash\n"); goto out; } desc.tfm = tfm; desc.flags = 0; ret = crypto_hash_init(&desc); if (ret < 0) { pr_err("crypto_hash_init() failed\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, &chap->id, 1); ret = crypto_hash_update(&desc, &sg, 1); if (ret < 0) { pr_err("crypto_hash_update() failed for id\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, &auth->password, strlen(auth->password)); ret = crypto_hash_update(&desc, &sg, strlen(auth->password)); if (ret < 0) { pr_err("crypto_hash_update() failed for password\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, chap->challenge, CHAP_CHALLENGE_LENGTH); ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH); if (ret < 0) { pr_err("crypto_hash_update() failed for challenge\n"); crypto_free_hash(tfm); goto out; } ret = crypto_hash_final(&desc, server_digest); if (ret < 0) { pr_err("crypto_hash_final() failed for server digest\n"); crypto_free_hash(tfm); goto out; } crypto_free_hash(tfm); chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); pr_debug("[server] MD5 Server Digest: %s\n", response); if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) { pr_debug("[server] MD5 Digests do not match!\n\n"); goto out; } else pr_debug("[server] MD5 Digests match, CHAP connetication" " successful.\n\n"); /* * One way authentication has succeeded, return now if mutual * authentication is not enabled. */ if (!auth->authenticate_target) { kfree(challenge); kfree(challenge_binhex); return 0; } /* * Get CHAP_I. */ if (extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type) < 0) { pr_err("Could not find CHAP_I.\n"); goto out; } if (type == HEX) id = simple_strtoul(&identifier[2], &endptr, 0); else id = simple_strtoul(identifier, &endptr, 0); if (id > 255) { pr_err("chap identifier: %lu greater than 255\n", id); goto out; } /* * RFC 1994 says Identifier is no more than octet (8 bits). */ pr_debug("[server] Got CHAP_I=%lu\n", id); /* * Get CHAP_C. */ if (extract_param(nr_in_ptr, "CHAP_C", CHAP_CHALLENGE_STR_LEN, challenge, &type) < 0) { pr_err("Could not find CHAP_C.\n"); goto out; } if (type != HEX) { pr_err("Could not find CHAP_C.\n"); goto out; } pr_debug("[server] Got CHAP_C=%s\n", challenge); challenge_len = chap_string_to_hex(challenge_binhex, challenge, strlen(challenge)); if (!challenge_len) { pr_err("Unable to convert incoming challenge\n"); goto out; } /* * Generate CHAP_N and CHAP_R for mutual authentication. */ tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { pr_err("Unable to allocate struct crypto_hash\n"); goto out; } desc.tfm = tfm; desc.flags = 0; ret = crypto_hash_init(&desc); if (ret < 0) { pr_err("crypto_hash_init() failed\n"); crypto_free_hash(tfm); goto out; } /* To handle both endiannesses */ id_as_uchar = id; sg_init_one(&sg, &id_as_uchar, 1); ret = crypto_hash_update(&desc, &sg, 1); if (ret < 0) { pr_err("crypto_hash_update() failed for id\n"); crypto_free_hash(tfm); goto out; } sg_init_one(&sg, auth->password_mutual, strlen(auth->password_mutual)); ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual)); if (ret < 0) { pr_err("crypto_hash_update() failed for" " password_mutual\n"); crypto_free_hash(tfm); goto out; } /* * Convert received challenge to binary hex. */ sg_init_one(&sg, challenge_binhex, challenge_len); ret = crypto_hash_update(&desc, &sg, challenge_len); if (ret < 0) { pr_err("crypto_hash_update() failed for ma challenge\n"); crypto_free_hash(tfm); goto out; } ret = crypto_hash_final(&desc, digest); if (ret < 0) { pr_err("crypto_hash_final() failed for ma digest\n"); crypto_free_hash(tfm); goto out; } crypto_free_hash(tfm); /* * Generate CHAP_N and CHAP_R. */ *nr_out_len = sprintf(nr_out_ptr, "CHAP_N=%s", auth->userid_mutual); *nr_out_len += 1; pr_debug("[server] Sending CHAP_N=%s\n", auth->userid_mutual); /* * Convert response from binary hex to ascii hext. */ chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE); *nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s", response); *nr_out_len += 1; pr_debug("[server] Sending CHAP_R=0x%s\n", response); auth_ret = 0; out: kfree(challenge); kfree(challenge_binhex); return auth_ret; }
/** * rpmsg_send_offchannel_raw() - send a message across to the remote processor * @rpdev: the rpmsg channel * @src: source address * @dst: destination address * @data: payload of message * @len: length of payload * @wait: indicates whether caller should block in case no TX buffers available * * This function is the base implementation for all of the rpmsg sending API. * * It will send @data of length @len to @dst, and say it's from @src. The * message will be sent to the remote processor which the @rpdev channel * belongs to. * * The message is sent using one of the TX buffers that are available for * communication with this remote processor. * * If @wait is true, the caller will be blocked until either a TX buffer is * available, or 15 seconds elapses (we don't want callers to * sleep indefinitely due to misbehaving remote processors), and in that * case -ERESTARTSYS is returned. The number '15' itself was picked * arbitrarily; there's little point in asking drivers to provide a timeout * value themselves. * * Otherwise, if @wait is false, and there are no TX buffers available, * the function will immediately fail, and -ENOMEM will be returned. * * Normally drivers shouldn't use this function directly; instead, drivers * should use the appropriate rpmsg_{try}send{to, _offchannel} API * (see include/linux/rpmsg.h). * * Returns 0 on success and an appropriate error value on failure. */ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst, void *data, int len, bool wait) { struct virtproc_info *vrp = rpdev->vrp; struct device *dev = &rpdev->dev; struct scatterlist sg; struct rpmsg_hdr *msg; int err; /* bcasting isn't allowed */ if (src == RPMSG_ADDR_ANY || dst == RPMSG_ADDR_ANY) { dev_err(dev, "invalid addr (src 0x%x, dst 0x%x)\n", src, dst); return -EINVAL; } /* * We currently use fixed-sized buffers, and therefore the payload * length is limited. * * One of the possible improvements here is either to support * user-provided buffers (and then we can also support zero-copy * messaging), or to improve the buffer allocator, to support * variable-length buffer sizes. */ if (len > RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) { dev_err(dev, "message is too big (%d)\n", len); return -EMSGSIZE; } /* grab a buffer */ msg = get_a_tx_buf(vrp); if (!msg && !wait) return -ENOMEM; /* no free buffer ? wait for one (but bail after 15 seconds) */ while (!msg) { /* enable "tx-complete" interrupts, if not already enabled */ rpmsg_upref_sleepers(vrp); /* * sleep until a free buffer is available or 15 secs elapse. * the timeout period is not configurable because there's * little point in asking drivers to specify that. * if later this happens to be required, it'd be easy to add. */ err = wait_event_interruptible_timeout(vrp->sendq, (msg = get_a_tx_buf(vrp)), msecs_to_jiffies(15000)); /* disable "tx-complete" interrupts if we're the last sleeper */ rpmsg_downref_sleepers(vrp); /* timeout ? */ if (!err) { dev_err(dev, "timeout waiting for a tx buffer\n"); return -ERESTARTSYS; } } msg->len = len; msg->flags = 0; msg->src = src; msg->dst = dst; msg->reserved = 0; memcpy(msg->data, data, len); dev_dbg(dev, "TX From 0x%x, To 0x%x, Len %d, Flags %d, Reserved %d\n", msg->src, msg->dst, msg->len, msg->flags, msg->reserved); print_hex_dump(KERN_DEBUG, "rpmsg_virtio TX: ", DUMP_PREFIX_NONE, 16, 1, msg, sizeof(*msg) + msg->len, true); sg_init_one(&sg, msg, sizeof(*msg) + len); mutex_lock(&vrp->tx_lock); /* add message to the remote processor's virtqueue */ err = virtqueue_add_outbuf(vrp->svq, &sg, 1, msg, GFP_KERNEL); if (err) { /* * need to reclaim the buffer here, otherwise it's lost * (memory won't leak, but rpmsg won't use it again for TX). * this will wait for a buffer management overhaul. */ dev_err(dev, "virtqueue_add_outbuf failed: %d\n", err); goto out; } /* tell the remote processor it has a pending message to read */ virtqueue_kick(vrp->svq); out: mutex_unlock(&vrp->tx_lock); return err; }
static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) { int err; u32 blocks; struct mmc_request mrq; struct mmc_command cmd; struct mmc_data data; unsigned int timeout_us; struct scatterlist sg; memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = MMC_APP_CMD; cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(card->host, &cmd, 0); if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) return (u32)-1; memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; memset(&data, 0, sizeof(struct mmc_data)); data.timeout_ns = card->csd.tacc_ns * 100; data.timeout_clks = card->csd.tacc_clks * 100; timeout_us = data.timeout_ns / 1000; timeout_us += data.timeout_clks * 1000 / (card->host->ios.clock / 1000); if (timeout_us > 100000) { data.timeout_ns = 100000000; data.timeout_clks = 0; } data.blksz = 4; data.blocks = 1; data.flags = MMC_DATA_READ; data.sg = &sg; data.sg_len = 1; memset(&mrq, 0, sizeof(struct mmc_request)); mrq.cmd = &cmd; mrq.data = &data; sg_init_one(&sg, &blocks, 4); mmc_wait_for_req(card->host, &mrq); if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) return (u32)-1; blocks = ntohl(blocks); return blocks; }
static int rpmsg_probe(struct virtio_device *vdev) { vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done }; const char *names[] = { "input", "output" }; struct virtqueue *vqs[2]; struct virtproc_info *vrp; void *bufs_va; int err = 0, i; vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); if (!vrp) return -ENOMEM; vrp->vdev = vdev; idr_init(&vrp->endpoints); mutex_init(&vrp->endpoints_lock); mutex_init(&vrp->tx_lock); init_waitqueue_head(&vrp->sendq); /* We expect two virtqueues, rx and tx (and in this order) */ err = vdev->config->find_vqs(vdev, 2, vqs, vq_cbs, names); if (err) goto free_vrp; vrp->rvq = vqs[0]; vrp->svq = vqs[1]; /* allocate coherent memory for the buffers */ bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, &vrp->bufs_dma, GFP_KERNEL); if (!bufs_va) { err = -ENOMEM; goto vqs_del; } dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%llx\n", bufs_va, (unsigned long long)vrp->bufs_dma); /* half of the buffers is dedicated for RX */ vrp->rbufs = bufs_va; /* and half is dedicated for TX */ vrp->sbufs = bufs_va + RPMSG_TOTAL_BUF_SPACE / 2; /* set up the receive buffers */ for (i = 0; i < RPMSG_NUM_BUFS / 2; i++) { struct scatterlist sg; void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE; sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE); err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr, GFP_KERNEL); WARN_ON(err); /* sanity check; this can't really happen */ } /* suppress "tx-complete" interrupts */ virtqueue_disable_cb(vrp->svq); vdev->priv = vrp; /* if supported by the remote processor, enable the name service */ if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) { /* a dedicated endpoint handles the name service msgs */ vrp->ns_ept = __rpmsg_create_ept(vrp, NULL, rpmsg_ns_cb, vrp, RPMSG_NS_ADDR); if (!vrp->ns_ept) { dev_err(&vdev->dev, "failed to create the ns ept\n"); err = -ENOMEM; goto free_coherent; } } /* tell the remote processor it can start sending messages */ virtqueue_kick(vrp->rvq); dev_info(&vdev->dev, "rpmsg host is online\n"); return 0; free_coherent: dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE, bufs_va, vrp->bufs_dma); vqs_del: vdev->config->del_vqs(vrp->vdev); free_vrp: kfree(vrp); return err; }
static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead); struct crypto_ablkcipher *ctr = ctx->ctr; struct { be128 hash; u8 iv[8]; struct crypto_gcm_setkey_result result; struct scatterlist sg[1]; struct ablkcipher_request req; } *data; int err; crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK); crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) & CRYPTO_TFM_REQ_MASK); err = crypto_ablkcipher_setkey(ctr, key, keylen); if (err) return err; crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) & CRYPTO_TFM_RES_MASK); data = kzalloc(sizeof(*data) + crypto_ablkcipher_reqsize(ctr), GFP_KERNEL); if (!data) return -ENOMEM; init_completion(&data->result.completion); sg_init_one(data->sg, &data->hash, sizeof(data->hash)); ablkcipher_request_set_tfm(&data->req, ctr); ablkcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, crypto_gcm_setkey_done, &data->result); ablkcipher_request_set_crypt(&data->req, data->sg, data->sg, sizeof(data->hash), data->iv); err = crypto_ablkcipher_encrypt(&data->req); if (err == -EINPROGRESS || err == -EBUSY) { err = wait_for_completion_interruptible( &data->result.completion); if (!err) err = data->result.err; } if (err) goto out; if (ctx->gf128 != NULL) gf128mul_free_4k(ctx->gf128); ctx->gf128 = gf128mul_init_4k_lle(&data->hash); if (ctx->gf128 == NULL) err = -ENOMEM; out: kfree(data); return err; }
static int simple_sd_ioctl_single_rw(struct msdc_ioctl *msdc_ctl) { char l_buf[512]; struct scatterlist msdc_sg; struct mmc_data msdc_data; struct mmc_command msdc_cmd; struct mmc_request msdc_mrq; struct msdc_host *host_ctl; int ret = 0; if(!msdc_ctl) return -EINVAL; if(msdc_ctl->total_size <= 0) return -EINVAL; host_ctl = mtk_msdc_host[msdc_ctl->host_num]; BUG_ON(!host_ctl); BUG_ON(!host_ctl->mmc); BUG_ON(!host_ctl->mmc->card); #ifdef MTK_MSDC_USE_CACHE if (msdc_ctl->iswrite && mmc_card_mmc(host_ctl->mmc->card) && (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1)) return simple_sd_ioctl_multi_rw(msdc_ctl); #endif mmc_claim_host(host_ctl->mmc); #if DEBUG_MMC_IOCTL pr_debug("user want access %d partition\n", msdc_ctl->partition); #endif ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf); if (ret) { pr_debug("mmc_send_ext_csd error, single rw\n"); goto single_end; } #ifdef CONFIG_MTK_EMMC_SUPPORT switch (msdc_ctl->partition) { case EMMC_PART_BOOT1: if (0x1 != (l_buf[179] & 0x7)) { /* change to access boot partition 1 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x1; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; case EMMC_PART_BOOT2: if (0x2 != (l_buf[179] & 0x7)) { /* change to access boot partition 2 */ l_buf[179] &= ~0x7; l_buf[179] |= 0x2; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; default: /* make sure access partition is user data area */ if (0 != (l_buf[179] & 0x7)) { /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } break; } #endif if (msdc_ctl->total_size > 512) { msdc_ctl->result = -1; goto single_end; } #if DEBUG_MMC_IOCTL pr_debug("start MSDC_SINGLE_READ_WRITE !!\n"); #endif memset(&msdc_data, 0, sizeof(struct mmc_data)); memset(&msdc_mrq, 0, sizeof(struct mmc_request)); memset(&msdc_cmd, 0, sizeof(struct mmc_command)); msdc_mrq.cmd = &msdc_cmd; msdc_mrq.data = &msdc_data; if (msdc_ctl->trans_type) dma_force[host_ctl->id] = FORCE_IN_DMA; else dma_force[host_ctl->id] = FORCE_IN_PIO; if (msdc_ctl->iswrite) { msdc_data.flags = MMC_DATA_WRITE; msdc_cmd.opcode = MMC_WRITE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_from_user(sg_msdc_multi_buffer, msdc_ctl->buffer, 512)) { dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto single_end; } } else { /* called from other kernel module */ memcpy(sg_msdc_multi_buffer, msdc_ctl->buffer, 512); } } else { msdc_data.flags = MMC_DATA_READ; msdc_cmd.opcode = MMC_READ_SINGLE_BLOCK; msdc_data.blocks = msdc_ctl->total_size / 512; memset(sg_msdc_multi_buffer, 0, 512); } msdc_cmd.arg = msdc_ctl->address; if (!mmc_card_blockaddr(host_ctl->mmc->card)) { pr_debug("the device is used byte address!\n"); msdc_cmd.arg <<= 9; } msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; msdc_data.stop = NULL; msdc_data.blksz = 512; msdc_data.sg = &msdc_sg; msdc_data.sg_len = 1; #if DEBUG_MMC_IOCTL pr_debug("single block: ueser buf address is 0x%p!\n", msdc_ctl->buffer); #endif sg_init_one(&msdc_sg, sg_msdc_multi_buffer, msdc_ctl->total_size); mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card); mmc_wait_for_req(host_ctl->mmc, &msdc_mrq); if (!msdc_ctl->iswrite) { if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) { if (copy_to_user(msdc_ctl->buffer, sg_msdc_multi_buffer, 512)) { dma_force[host_ctl->id] = FORCE_NOTHING; ret = -EFAULT; goto single_end; } } else { /* called from other kernel module */ memcpy(msdc_ctl->buffer, sg_msdc_multi_buffer, 512); } } /* clear the global buffer of R/W IOCTL */ memset(sg_msdc_multi_buffer, 0 , 512); if (msdc_ctl->partition) { ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf); if (ret) { pr_debug("mmc_send_ext_csd error, single rw2\n"); goto single_end; } if (l_buf[179] & 0x7) { /* set back to access user area */ l_buf[179] &= ~0x7; l_buf[179] |= 0x0; mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000); } } single_end: mmc_release_host(host_ctl->mmc); if (ret) msdc_ctl->result = ret; if (msdc_cmd.error) msdc_ctl->result = msdc_cmd.error; if (msdc_data.error) msdc_ctl->result = msdc_data.error; else msdc_ctl->result = 0; dma_force[host_ctl->id] = FORCE_NOTHING; return msdc_ctl->result; }
static int init_vqs(struct virtio_balloon *vb) { struct virtqueue *vqs[VIRTIO_BALLOON_VQ_MAX]; vq_callback_t *callbacks[VIRTIO_BALLOON_VQ_MAX]; const char *names[VIRTIO_BALLOON_VQ_MAX]; int err; /* * Inflateq and deflateq are used unconditionally. The names[] * will be NULL if the related feature is not enabled, which will * cause no allocation for the corresponding virtqueue in find_vqs. */ callbacks[VIRTIO_BALLOON_VQ_INFLATE] = balloon_ack; names[VIRTIO_BALLOON_VQ_INFLATE] = "inflate"; callbacks[VIRTIO_BALLOON_VQ_DEFLATE] = balloon_ack; names[VIRTIO_BALLOON_VQ_DEFLATE] = "deflate"; names[VIRTIO_BALLOON_VQ_STATS] = NULL; names[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { names[VIRTIO_BALLOON_VQ_STATS] = "stats"; callbacks[VIRTIO_BALLOON_VQ_STATS] = stats_request; } if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { names[VIRTIO_BALLOON_VQ_FREE_PAGE] = "free_page_vq"; callbacks[VIRTIO_BALLOON_VQ_FREE_PAGE] = NULL; } err = vb->vdev->config->find_vqs(vb->vdev, VIRTIO_BALLOON_VQ_MAX, vqs, callbacks, names, NULL, NULL); if (err) return err; vb->inflate_vq = vqs[VIRTIO_BALLOON_VQ_INFLATE]; vb->deflate_vq = vqs[VIRTIO_BALLOON_VQ_DEFLATE]; if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { struct scatterlist sg; unsigned int num_stats; vb->stats_vq = vqs[VIRTIO_BALLOON_VQ_STATS]; /* * Prime this virtqueue with one buffer so the hypervisor can * use it to signal us later (it can't be broken yet!). */ num_stats = update_balloon_stats(vb); sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); err = virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL); if (err) { dev_warn(&vb->vdev->dev, "%s: add stat_vq failed\n", __func__); return err; } virtqueue_kick(vb->stats_vq); } if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) vb->free_page_vq = vqs[VIRTIO_BALLOON_VQ_FREE_PAGE]; return 0; }
int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv, void *data, struct page *page, unsigned int size) { int err; struct scatterlist sg; if (!e->cipher && !e->hash) return 0; // dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n", ; if (data) { sg_init_one(&sg, data, size); } else { sg_init_table(&sg, 1); sg_set_page(&sg, page, size, 0); } if (e->cipher) { struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash); u8 iv[32]; memset(iv, 0, sizeof(iv)); memcpy(iv, &cmd_iv, sizeof(cmd_iv)); ablkcipher_request_set_tfm(req, e->cipher); err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout); if (err) goto err_out_exit; } if (e->hash) { struct hash_desc desc; void *dst = e->data + e->size/2; desc.tfm = e->hash; desc.flags = 0; err = crypto_hash_init(&desc); if (err) goto err_out_exit; err = crypto_hash_update(&desc, &sg, size); if (err) goto err_out_exit; err = crypto_hash_final(&desc, dst); if (err) goto err_out_exit; err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash)); if (err) { #ifdef CONFIG_POHMELFS_DEBUG unsigned int i; unsigned char *recv = e->data, *calc = dst; // dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ", ; for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) { #if 0 dprintka("%02x ", recv[i]); if (recv[i] != calc[i]) { dprintka("| calc byte: %02x.\n", calc[i]); break; } #else dprintka("%02x/%02x ", recv[i], calc[i]); #endif } ; #endif goto err_out_exit; } else { // dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n", ; } } // dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n", ; return 0; err_out_exit: // dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n", ; return err; }
static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); be128 buf[8]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx), .tweak_fn = aesni_xts_tweak, .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx), .crypt_fn = lrw_xts_encrypt_callback, }; int ret; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; kernel_fpu_begin(); ret = xts_crypt(desc, dst, src, nbytes, &req); kernel_fpu_end(); return ret; } static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); be128 buf[8]; struct xts_crypt_req req = { .tbuf = buf, .tbuflen = sizeof(buf), .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx), .tweak_fn = aesni_xts_tweak, .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx), .crypt_fn = lrw_xts_decrypt_callback, }; int ret; desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; kernel_fpu_begin(); ret = xts_crypt(desc, dst, src, nbytes, &req); kernel_fpu_end(); return ret; } #endif #ifdef CONFIG_X86_64 static int rfc4106_init(struct crypto_tfm *tfm) { struct cryptd_aead *cryptd_tfm; struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *) PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN); struct crypto_aead *cryptd_child; struct aesni_rfc4106_gcm_ctx *child_ctx; cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0); if (IS_ERR(cryptd_tfm)) return PTR_ERR(cryptd_tfm); cryptd_child = cryptd_aead_child(cryptd_tfm); child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child); memcpy(child_ctx, ctx, sizeof(*ctx)); ctx->cryptd_tfm = cryptd_tfm; tfm->crt_aead.reqsize = sizeof(struct aead_request) + crypto_aead_reqsize(&cryptd_tfm->base); return 0; } static void rfc4106_exit(struct crypto_tfm *tfm) { struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *) PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN); if (!IS_ERR(ctx->cryptd_tfm)) cryptd_free_aead(ctx->cryptd_tfm); return; } static void rfc4106_set_hash_subkey_done(struct crypto_async_request *req, int err) { struct aesni_gcm_set_hash_subkey_result *result = req->data; if (err == -EINPROGRESS) return; result->err = err; complete(&result->completion); } static int rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len) { struct crypto_ablkcipher *ctr_tfm; struct ablkcipher_request *req; int ret = -EINVAL; struct aesni_hash_subkey_req_data *req_data; ctr_tfm = crypto_alloc_ablkcipher("ctr(aes)", 0, 0); if (IS_ERR(ctr_tfm)) return PTR_ERR(ctr_tfm); crypto_ablkcipher_clear_flags(ctr_tfm, ~0); ret = crypto_ablkcipher_setkey(ctr_tfm, key, key_len); if (ret) goto out_free_ablkcipher; ret = -ENOMEM; req = ablkcipher_request_alloc(ctr_tfm, GFP_KERNEL); if (!req) goto out_free_ablkcipher; req_data = kmalloc(sizeof(*req_data), GFP_KERNEL); if (!req_data) goto out_free_request; memset(req_data->iv, 0, sizeof(req_data->iv)); /* Clear the data in the hash sub key container to zero.*/ /* We want to cipher all zeros to create the hash sub key. */ memset(hash_subkey, 0, RFC4106_HASH_SUBKEY_SIZE); init_completion(&req_data->result.completion); sg_init_one(&req_data->sg, hash_subkey, RFC4106_HASH_SUBKEY_SIZE); ablkcipher_request_set_tfm(req, ctr_tfm); ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, rfc4106_set_hash_subkey_done, &req_data->result); ablkcipher_request_set_crypt(req, &req_data->sg, &req_data->sg, RFC4106_HASH_SUBKEY_SIZE, req_data->iv); ret = crypto_ablkcipher_encrypt(req); if (ret == -EINPROGRESS || ret == -EBUSY) { ret = wait_for_completion_interruptible (&req_data->result.completion); if (!ret) ret = req_data->result.err; } kfree(req_data); out_free_request: ablkcipher_request_free(req); out_free_ablkcipher: crypto_free_ablkcipher(ctr_tfm); return ret; } static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, unsigned int key_len) { int ret = 0; struct crypto_tfm *tfm = crypto_aead_tfm(parent); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); struct aesni_rfc4106_gcm_ctx *child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child); u8 *new_key_align, *new_key_mem = NULL; if (key_len < 4) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } /*Account for 4 byte nonce at the end.*/ key_len -= 4; if (key_len != AES_KEYSIZE_128) { crypto_tfm_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); return -EINVAL; } memcpy(ctx->nonce, key + key_len, sizeof(ctx->nonce)); /*This must be on a 16 byte boundary!*/ if ((unsigned long)(&(ctx->aes_key_expanded.key_enc[0])) % AESNI_ALIGN) return -EINVAL; if ((unsigned long)key % AESNI_ALIGN) { /*key is not aligned: use an auxuliar aligned pointer*/ new_key_mem = kmalloc(key_len+AESNI_ALIGN, GFP_KERNEL); if (!new_key_mem) return -ENOMEM; new_key_align = PTR_ALIGN(new_key_mem, AESNI_ALIGN); memcpy(new_key_align, key, key_len); key = new_key_align; } if (!irq_fpu_usable()) ret = crypto_aes_expand_key(&(ctx->aes_key_expanded), key, key_len); else { kernel_fpu_begin(); ret = aesni_set_key(&(ctx->aes_key_expanded), key, key_len); kernel_fpu_end(); } /*This must be on a 16 byte boundary!*/ if ((unsigned long)(&(ctx->hash_subkey[0])) % AESNI_ALIGN) { ret = -EINVAL; goto exit; } ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len); memcpy(child_ctx, ctx, sizeof(*ctx)); exit: kfree(new_key_mem); return ret; } /* This is the Integrity Check Value (aka the authentication tag length and can * be 8, 12 or 16 bytes long. */ static int rfc4106_set_authsize(struct crypto_aead *parent, unsigned int authsize) { struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); switch (authsize) { case 8: case 12: case 16: break; default: return -EINVAL; } crypto_aead_crt(parent)->authsize = authsize; crypto_aead_crt(cryptd_child)->authsize = authsize; return 0; } static int rfc4106_encrypt(struct aead_request *req) { int ret; struct crypto_aead *tfm = crypto_aead_reqtfm(req); struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm); if (!irq_fpu_usable()) { struct aead_request *cryptd_req = (struct aead_request *) aead_request_ctx(req); memcpy(cryptd_req, req, sizeof(*req)); aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base); return crypto_aead_encrypt(cryptd_req); } else { struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); kernel_fpu_begin(); ret = cryptd_child->base.crt_aead.encrypt(req); kernel_fpu_end(); return ret; } }
/* * NOTE: void *buf, caller for the buf is required to use DMA-capable * buffer or on-stack buffer (with some overhead in callee). */ static int mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, void *buf, unsigned len) { struct mmc_request mrq = {NULL}; struct mmc_command cmd = {0}; struct mmc_data data = {0}; struct scatterlist sg; void *data_buf; int is_on_stack; is_on_stack = object_is_on_stack(buf); if (is_on_stack) { /* * dma onto stack is unsafe/nonportable, but callers to this * routine normally provide temporary on-stack buffers ... */ data_buf = kmalloc(len, GFP_KERNEL); if (!data_buf) return -ENOMEM; } else data_buf = buf; mrq.cmd = &cmd; mrq.data = &data; cmd.opcode = opcode; cmd.arg = 0; /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we * rely on callers to never use this with "native" calls for reading * CSD or CID. Native versions of those commands use the R2 type, * not R1 plus a data block. */ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; data.blksz = len; data.blocks = 1; data.flags = MMC_DATA_READ; data.sg = &sg; data.sg_len = 1; sg_init_one(&sg, data_buf, len); if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) { /* * The spec states that CSR and CID accesses have a timeout * of 64 clock cycles. */ data.timeout_ns = 0; data.timeout_clks = 64; } else mmc_set_data_timeout(&data, card); mmc_wait_for_req(host, &mrq); if (is_on_stack) { memcpy(buf, data_buf, len); kfree(data_buf); } if (cmd.error) return cmd.error; if (data.error) return data.error; return 0; }
static int qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) { struct ablkcipher_request *req = ablkcipher_request_cast(async_req); struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); struct qce_device *qce = tmpl->qce; enum dma_data_direction dir_src, dir_dst; struct scatterlist *sg; bool diff_dst; gfp_t gfp; int ret; rctx->iv = req->info; rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher); rctx->cryptlen = req->nbytes; diff_dst = (req->src != req->dst) ? true : false; dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; rctx->src_nents = qce_countsg(req->src, req->nbytes, &rctx->src_chained); if (diff_dst) { rctx->dst_nents = qce_countsg(req->dst, req->nbytes, &rctx->dst_chained); } else { rctx->dst_nents = rctx->src_nents; rctx->dst_chained = rctx->src_chained; } rctx->dst_nents += 1; gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); if (ret) return ret; sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); if (IS_ERR(sg)) { ret = PTR_ERR(sg); goto error_free; } sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); if (IS_ERR(sg)) { ret = PTR_ERR(sg); goto error_free; } sg_mark_end(sg); rctx->dst_sg = rctx->dst_tbl.sgl; ret = qce_mapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst, rctx->dst_chained); if (ret < 0) goto error_free; if (diff_dst) { ret = qce_mapsg(qce->dev, req->src, rctx->src_nents, dir_src, rctx->src_chained); if (ret < 0) goto error_unmap_dst; rctx->src_sg = req->src; } else { rctx->src_sg = rctx->dst_sg; } ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, rctx->dst_sg, rctx->dst_nents, qce_ablkcipher_done, async_req); if (ret) goto error_unmap_src; qce_dma_issue_pending(&qce->dma); ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0); if (ret) goto error_terminate; return 0; error_terminate: qce_dma_terminate_all(&qce->dma); error_unmap_src: if (diff_dst) qce_unmapsg(qce->dev, req->src, rctx->src_nents, dir_src, rctx->src_chained); error_unmap_dst: qce_unmapsg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst, rctx->dst_chained); error_free: sg_free_table(&rctx->dst_tbl); return ret; }
static int process_crypt_req(struct tegra_crypto_ctx *ctx, struct tegra_crypt_req *crypt_req) { struct crypto_ablkcipher *tfm; struct ablkcipher_request *req = NULL; struct scatterlist in_sg; struct scatterlist out_sg; unsigned long *xbuf[NBUFS]; int ret = 0, size = 0; unsigned long total = 0; const u8 *key = NULL; struct tegra_crypto_completion tcrypt_complete; if (crypt_req->op & TEGRA_CRYPTO_ECB) { req = ablkcipher_request_alloc(ctx->ecb_tfm, GFP_KERNEL); tfm = ctx->ecb_tfm; } else if (crypt_req->op & TEGRA_CRYPTO_CBC) { req = ablkcipher_request_alloc(ctx->cbc_tfm, GFP_KERNEL); tfm = ctx->cbc_tfm; } else if ((crypt_req->op & TEGRA_CRYPTO_OFB) && (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2)) { req = ablkcipher_request_alloc(ctx->ofb_tfm, GFP_KERNEL); tfm = ctx->ofb_tfm; } else if ((crypt_req->op & TEGRA_CRYPTO_CTR) && (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2)) { req = ablkcipher_request_alloc(ctx->ctr_tfm, GFP_KERNEL); tfm = ctx->ctr_tfm; } if (!req) { pr_err("%s: Failed to allocate request\n", __func__); return -ENOMEM; } if ((crypt_req->keylen < 0) || (crypt_req->keylen > AES_MAX_KEY_SIZE)) { ret = -EINVAL; pr_err("crypt_req keylen invalid"); goto process_req_out; } crypto_ablkcipher_clear_flags(tfm, ~0); if (!ctx->use_ssk) key = crypt_req->key; if (!crypt_req->skip_key) { ret = crypto_ablkcipher_setkey(tfm, key, crypt_req->keylen); if (ret < 0) { pr_err("setkey failed"); goto process_req_out; } } ret = alloc_bufs(xbuf); if (ret < 0) { pr_err("alloc_bufs failed"); goto process_req_out; } init_completion(&tcrypt_complete.restart); ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tegra_crypt_complete, &tcrypt_complete); total = crypt_req->plaintext_sz; while (total > 0) { size = min(total, PAGE_SIZE); ret = copy_from_user((void *)xbuf[0], (void __user *)crypt_req->plaintext, size); if (ret) { ret = -EFAULT; pr_debug("%s: copy_from_user failed (%d)\n", __func__, ret); goto process_req_buf_out; } sg_init_one(&in_sg, xbuf[0], size); sg_init_one(&out_sg, xbuf[1], size); if (!crypt_req->skip_iv) ablkcipher_request_set_crypt(req, &in_sg, &out_sg, size, crypt_req->iv); else ablkcipher_request_set_crypt(req, &in_sg, &out_sg, size, NULL); INIT_COMPLETION(tcrypt_complete.restart); tcrypt_complete.req_err = 0; ret = crypt_req->encrypt ? crypto_ablkcipher_encrypt(req) : crypto_ablkcipher_decrypt(req); if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { /* crypto driver is asynchronous */ ret = wait_for_completion_interruptible(&tcrypt_complete.restart); if (ret < 0) goto process_req_buf_out; if (tcrypt_complete.req_err < 0) { ret = tcrypt_complete.req_err; goto process_req_buf_out; } } else if (ret < 0) { pr_debug("%scrypt failed (%d)\n", crypt_req->encrypt ? "en" : "de", ret); goto process_req_buf_out; } ret = copy_to_user((void __user *)crypt_req->result, (const void *)xbuf[1], size); if (ret) { ret = -EFAULT; pr_debug("%s: copy_to_user failed (%d)\n", __func__, ret); goto process_req_buf_out; } total -= size; crypt_req->result += size; crypt_req->plaintext += size; } process_req_buf_out: free_bufs(xbuf); process_req_out: ablkcipher_request_free(req); return ret; }
static int update_hash (struct hash_desc * desc, unsigned char * start_addr, unsigned int size) { struct scatterlist sg; unsigned char * buf = NULL; unsigned char * cur = NULL; unsigned int bytes_remaining; unsigned int bytes; int ret = -1; #if FIPS_FUNC_TEST == 2 static int total = 0; #endif buf = kmalloc (PAGE_SIZE, GFP_KERNEL); if (!buf) { printk(KERN_ERR "FIPS(%s): kmalloc failed", __FUNCTION__); return ret; } bytes_remaining = size; cur = start_addr; while (bytes_remaining > 0) { if (bytes_remaining >= PAGE_SIZE) bytes = PAGE_SIZE; else bytes = bytes_remaining; memcpy (buf, cur, bytes); sg_init_one (&sg, buf, bytes); #if FIPS_FUNC_TEST == 2 if (total == 0) { printk(KERN_INFO "FIPS : Failing Integrity Test"); buf[bytes / 2] += 1; } #endif ret = crypto_hash_update (desc, &sg, bytes); if (ret) { printk(KERN_ERR "FIPS(%s): crypto_hash_update failed", __FUNCTION__); kfree(buf); buf = 0; return -1; } cur += bytes; bytes_remaining -= bytes; #if FIPS_FUNC_TEST == 2 total += bytes; #endif } //printk(KERN_INFO "FIPS : total bytes = %d\n", total); if (buf) { kfree(buf); buf = 0; } return 0; }
static int tegra_crypto_sha(struct tegra_sha_req *sha_req) { struct crypto_ahash *tfm; struct scatterlist sg[1]; char result[64]; struct ahash_request *req; struct tegra_crypto_completion sha_complete; void *hash_buff; unsigned long *xbuf[XBUFSIZE]; int ret = -ENOMEM; tfm = crypto_alloc_ahash(sha_req->algo, 0, 0); if (IS_ERR(tfm)) { printk(KERN_ERR "alg: hash: Failed to load transform for %s: " "%ld\n", sha_req->algo, PTR_ERR(tfm)); goto out_alloc; } req = ahash_request_alloc(tfm, GFP_KERNEL); if (!req) { printk(KERN_ERR "alg: hash: Failed to allocate request for " "%s\n", sha_req->algo); goto out_noreq; } ret = alloc_bufs(xbuf); if (ret < 0) { pr_err("alloc_bufs failed"); goto out_buf; } init_completion(&sha_complete.restart); memset(result, 0, 64); hash_buff = xbuf[0]; memcpy(hash_buff, sha_req->plaintext, sha_req->plaintext_sz); sg_init_one(&sg[0], hash_buff, sha_req->plaintext_sz); if (sha_req->keylen) { crypto_ahash_clear_flags(tfm, ~0); ret = crypto_ahash_setkey(tfm, sha_req->key, sha_req->keylen); if (ret) { printk(KERN_ERR "alg: hash: setkey failed on " " %s: ret=%d\n", sha_req->algo, -ret); goto out; } } ahash_request_set_crypt(req, sg, result, sha_req->plaintext_sz); ret = sha_async_hash_op(req, &sha_complete, crypto_ahash_init(req)); if (ret) { pr_err("alg: hash: init failed on " "for %s: ret=%d\n", sha_req->algo, -ret); goto out; } ret = sha_async_hash_op(req, &sha_complete, crypto_ahash_update(req)); if (ret) { pr_err("alg: hash: update failed on " "for %s: ret=%d\n", sha_req->algo, -ret); goto out; } ret = sha_async_hash_op(req, &sha_complete, crypto_ahash_final(req)); if (ret) { pr_err("alg: hash: final failed on " "for %s: ret=%d\n", sha_req->algo, -ret); goto out; } ret = copy_to_user((void __user *)sha_req->result, (const void *)result, crypto_ahash_digestsize(tfm)); if (ret) { ret = -EFAULT; pr_err("alg: hash: copy_to_user failed (%d) for %s\n", ret, sha_req->algo); } out: free_bufs(xbuf); out_buf: ahash_request_free(req); out_noreq: crypto_free_ahash(tfm); out_alloc: return ret; }
int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, v_U8_t *output, v_U8_t outlen) { int ret = 0; struct crypto_ahash *tfm; struct scatterlist sg; struct ahash_request *req; struct hmac_md5_result tresult = {.err = 0}; void *hash_buff = NULL; unsigned char hash_result[64]; int i; memset(output, 0, outlen); init_completion(&tresult.completion); tfm = wcnss_wlan_crypto_alloc_ahash("hmac(md5)", CRYPTO_ALG_TYPE_AHASH, CRYPTO_ALG_TYPE_AHASH_MASK); if (IS_ERR(tfm)) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_alloc_ahash failed"); ret = PTR_ERR(tfm); goto err_tfm; } req = ahash_request_alloc(tfm, GFP_KERNEL); if (!req) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to allocate request for hmac(md5)"); ret = -ENOMEM; goto err_req; } ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, hmac_md5_complete, &tresult); hash_buff = kzalloc(psize, GFP_KERNEL); if (!hash_buff) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "failed to kzalloc hash_buff"); ret = -ENOMEM; goto err_hash_buf; } memset(hash_result, 0, 64); memcpy(hash_buff, plaintext, psize); sg_init_one(&sg, hash_buff, psize); if (ksize) { crypto_ahash_clear_flags(tfm, ~0); ret = wcnss_wlan_crypto_ahash_setkey(tfm, key, ksize); if (ret) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "crypto_ahash_setkey failed"); goto err_setkey; } } ahash_request_set_crypt(req, &sg, hash_result, psize); ret = wcnss_wlan_crypto_ahash_digest(req); VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); switch (ret) { case 0: for (i=0; i< outlen; i++) output[i] = hash_result[i]; break; case -EINPROGRESS: case -EBUSY: ret = wait_for_completion_interruptible(&tresult.completion); if (!ret && !tresult.err) { INIT_COMPLETION(tresult.completion); break; } else { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "wait_for_completion_interruptible failed"); if (!ret) ret = tresult.err; goto out; } default: goto out; } out: err_setkey: kfree(hash_buff); err_hash_buf: ahash_request_free(req); err_req: wcnss_wlan_crypto_free_ahash(tfm); err_tfm: return ret; } VOS_STATUS vos_md5_hmac_str(v_U32_t cryptHandle, v_U8_t *pText, v_U32_t textLen, v_U8_t *pKey, v_U32_t keyLen, v_U8_t digest[VOS_DIGEST_MD5_SIZE]) { int ret = 0; ret = hmac_md5( pKey, (v_U8_t) keyLen, (char *)pText, (v_U8_t) textLen, digest, VOS_DIGEST_MD5_SIZE ); if (ret != 0) { VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR,"hmac_md5() call failed"); return VOS_STATUS_E_FAULT; } return VOS_STATUS_SUCCESS; }