Пример #1
0
static struct aead_request *crypto_rfc4543_crypt(struct aead_request *req,
						 int enc)
{
	struct crypto_aead *aead = crypto_aead_reqtfm(req);
	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
	struct crypto_rfc4543_req_ctx *rctx = crypto_rfc4543_reqctx(req);
	struct aead_request *subreq = &rctx->subreq;
	struct scatterlist *dst = req->dst;
	struct scatterlist *cipher = rctx->cipher;
	struct scatterlist *payload = rctx->payload;
	struct scatterlist *assoc = rctx->assoc;
	unsigned int authsize = crypto_aead_authsize(aead);
	unsigned int assoclen = req->assoclen;
	struct page *dstp;
	u8 *vdst;
	u8 *iv = PTR_ALIGN((u8 *)(rctx + 1) + crypto_aead_reqsize(ctx->child),
			   crypto_aead_alignmask(ctx->child) + 1);

	memcpy(iv, ctx->nonce, 4);
	memcpy(iv + 4, req->iv, 8);

	/* construct cipher/plaintext */
	if (enc)
		memset(rctx->auth_tag, 0, authsize);
	else
		scatterwalk_map_and_copy(rctx->auth_tag, dst,
					 req->cryptlen - authsize,
					 authsize, 0);

	sg_init_one(cipher, rctx->auth_tag, authsize);

	/* construct the aad */
	dstp = sg_page(dst);
	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;

	sg_init_table(payload, 2);
	sg_set_buf(payload, req->iv, 8);
	scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2);
	assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);

	sg_init_table(assoc, 2);
	sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
		    req->assoc->offset);
	scatterwalk_crypto_chain(assoc, payload, 0, 2);

	aead_request_set_tfm(subreq, ctx->child);
	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
				  req->base.data);
	aead_request_set_crypt(subreq, cipher, cipher, enc ? 0 : authsize, iv);
	aead_request_set_assoc(subreq, assoc, assoclen);

	return subreq;
}
Пример #2
0
static void chain_to_walk(struct scatterlist *sg, struct scatter_walk *walk)
{
	struct scatterlist *src = walk->sg;
	int diff = walk->offset - src->offset;

	sg_set_page(sg, sg_page(src),
		    src->length - diff, walk->offset);

	scatterwalk_crypto_chain(sg, sg_next(src), 2);
}
Пример #3
0
struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
				     struct scatterlist *src,
				     unsigned int len)
{
	for (;;) {
		if (!len)
			return src;

		if (src->length > len)
			break;

		len -= src->length;
		src = sg_next(src);
	}

	sg_init_table(dst, 2);
	sg_set_page(dst, sg_page(src), src->length - len, src->offset + len);
	scatterwalk_crypto_chain(dst, sg_next(src), 0, 2);

	return dst;
}
Пример #4
0
static struct aead_request *crypto_rfc4543_crypt(struct aead_request *req,
        bool enc)
{
    struct crypto_aead *aead = crypto_aead_reqtfm(req);
    struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
    struct crypto_rfc4543_req_ctx *rctx = crypto_rfc4543_reqctx(req);
    struct aead_request *subreq = &rctx->subreq;
    struct scatterlist *src = req->src;
    struct scatterlist *cipher = rctx->cipher;
    struct scatterlist *payload = rctx->payload;
    struct scatterlist *assoc = rctx->assoc;
    unsigned int authsize = crypto_aead_authsize(aead);
    unsigned int assoclen = req->assoclen;
    struct page *srcp;
    u8 *vsrc;
    u8 *iv = PTR_ALIGN((u8 *)(rctx + 1) + crypto_aead_reqsize(ctx->child),
                       crypto_aead_alignmask(ctx->child) + 1);

    memcpy(iv, ctx->nonce, 4);
    memcpy(iv + 4, req->iv, 8);

    /* construct cipher/plaintext */
    if (enc)
        memset(rctx->auth_tag, 0, authsize);
    else
        scatterwalk_map_and_copy(rctx->auth_tag, src,
                                 req->cryptlen - authsize,
                                 authsize, 0);

    sg_init_one(cipher, rctx->auth_tag, authsize);

    /* construct the aad */
    srcp = sg_page(src);
    vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;

    sg_init_table(payload, 2);
    sg_set_buf(payload, req->iv, 8);
    scatterwalk_crypto_chain(payload, src, vsrc == req->iv + 8, 2);
    assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);

    if (req->assoc->length == req->assoclen) {
        sg_init_table(assoc, 2);
        sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
                    req->assoc->offset);
    } else {
        BUG_ON(req->assoclen > sizeof(rctx->assocbuf));

        scatterwalk_map_and_copy(rctx->assocbuf, req->assoc, 0,
                                 req->assoclen, 0);

        sg_init_table(assoc, 2);
        sg_set_buf(assoc, rctx->assocbuf, req->assoclen);
    }
    scatterwalk_crypto_chain(assoc, payload, 0, 2);

    aead_request_set_tfm(subreq, ctx->child);
    aead_request_set_callback(subreq, req->base.flags, crypto_rfc4543_done,
                              req);
    aead_request_set_crypt(subreq, cipher, cipher, enc ? 0 : authsize, iv);
    aead_request_set_assoc(subreq, assoc, assoclen);

    return subreq;
}
Пример #5
0
static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
{
	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
	struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
	struct ablkcipher_request *subreq;
	crypto_completion_t complete;
	void *data;
	struct scatterlist *osrc, *odst;
	struct scatterlist *dst;
	struct page *srcp;
	struct page *dstp;
	u8 *giv;
	u8 *vsrc;
	u8 *vdst;
	__be64 seq;
	unsigned int ivsize;
	unsigned int len;
	int err;

	subreq = (void *)(reqctx->tail + ctx->reqoff);
	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));

	giv = req->giv;
	complete = req->creq.base.complete;
	data = req->creq.base.data;

	osrc = req->creq.src;
	odst = req->creq.dst;
	srcp = sg_page(osrc);
	dstp = sg_page(odst);
	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + osrc->offset;
	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + odst->offset;

	ivsize = crypto_ablkcipher_ivsize(geniv);

	if (vsrc != giv + ivsize && vdst != giv + ivsize) {
		giv = PTR_ALIGN((u8 *)reqctx->tail,
				crypto_ablkcipher_alignmask(geniv) + 1);
		complete = eseqiv_complete;
		data = req;
	}

	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
					data);

	sg_init_table(reqctx->src, 2);
	sg_set_buf(reqctx->src, giv, ivsize);
	scatterwalk_crypto_chain(reqctx->src, osrc, vsrc == giv + ivsize, 2);

	dst = reqctx->src;
	if (osrc != odst) {
		sg_init_table(reqctx->dst, 2);
		sg_set_buf(reqctx->dst, giv, ivsize);
		scatterwalk_crypto_chain(reqctx->dst, odst, vdst == giv + ivsize, 2);

		dst = reqctx->dst;
	}

	ablkcipher_request_set_crypt(subreq, reqctx->src, dst,
				     req->creq.nbytes + ivsize,
				     req->creq.info);

	memcpy(req->creq.info, ctx->salt, ivsize);

	len = ivsize;
	if (ivsize > sizeof(u64)) {
		memset(req->giv, 0, ivsize - sizeof(u64));
		len = sizeof(u64);
	}
	seq = cpu_to_be64(req->seq);
	memcpy(req->giv + ivsize - len, &seq, len);

	err = crypto_ablkcipher_encrypt(subreq);
	if (err)
		goto out;

	if (giv != req->giv)
		eseqiv_complete2(req);

out:
	return err;
}