示例#1
0
文件: gcm.c 项目: jtcriswell/linux256
static int crypto_gcm_decrypt(struct aead_request *req)
{
    struct crypto_aead *aead = crypto_aead_reqtfm(req);
    struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
    struct ablkcipher_request *abreq = &pctx->u.abreq;
    struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
    unsigned int authsize = crypto_aead_authsize(aead);
    unsigned int cryptlen = req->cryptlen;
    int err;

    if (cryptlen < authsize)
        return -EINVAL;
    cryptlen -= authsize;

    gctx->src = req->src;
    gctx->cryptlen = cryptlen;
    gctx->complete = gcm_dec_hash_done;

    err = gcm_hash(req, pctx);
    if (err)
        return err;

    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                    gcm_decrypt_done, req);
    crypto_gcm_init_crypt(abreq, req, cryptlen);
    err = crypto_ablkcipher_decrypt(abreq);
    if (err)
        return err;

    return crypto_gcm_verify(req, pctx);
}
示例#2
0
static int pcrypt_aead_givencrypt(struct aead_givcrypt_request *req)
{
	int err;
	struct aead_request *areq = &req->areq;
	struct pcrypt_request *preq = aead_request_ctx(areq);
	struct aead_givcrypt_request *creq = pcrypt_request_ctx(preq);
	struct padata_priv *padata = pcrypt_request_padata(preq);
	struct crypto_aead *aead = aead_givcrypt_reqtfm(req);
	struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
	u32 flags = aead_request_flags(areq);

	memset(padata, 0, sizeof(struct padata_priv));

	padata->parallel = pcrypt_aead_givenc;
	padata->serial = pcrypt_aead_giv_serial;

	aead_givcrypt_set_tfm(creq, ctx->child);
	aead_givcrypt_set_callback(creq, flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
				   pcrypt_aead_done, areq);
	aead_givcrypt_set_crypt(creq, areq->src, areq->dst,
				areq->cryptlen, areq->iv);
	aead_givcrypt_set_assoc(creq, areq->assoc, areq->assoclen);
	aead_givcrypt_set_giv(creq, req->giv, req->seq);

	err = pcrypt_do_parallel(padata, &ctx->cb_cpu, &pencrypt);
	if (!err)
		return -EINPROGRESS;

	return err;
}
示例#3
0
文件: gcm.c 项目: jtcriswell/linux256
static int crypto_gcm_encrypt(struct aead_request *req)
{
    struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
    struct ablkcipher_request *abreq = &pctx->u.abreq;
    struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
    int err;

    crypto_gcm_init_crypt(abreq, req, req->cryptlen);
    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
                                    gcm_encrypt_done, req);

    gctx->src = req->dst;
    gctx->cryptlen = req->cryptlen;
    gctx->complete = gcm_enc_hash_done;

    err = crypto_ablkcipher_encrypt(abreq);
    if (err)
        return err;

    err = gcm_hash(req, pctx);
    if (err)
        return err;

    crypto_xor(pctx->auth_tag, pctx->iauth_tag, 16);
    gcm_enc_copy_hash(req, pctx);

    return 0;
}
示例#4
0
static int crypto_gcm_decrypt(struct aead_request *req)
{
	struct crypto_aead *aead = crypto_aead_reqtfm(req);
	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
	struct ablkcipher_request *abreq = &pctx->abreq;
	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
	unsigned int cryptlen = req->cryptlen;
	unsigned int authsize = crypto_aead_authsize(aead);
	int err;

	if (cryptlen < authsize)
		return -EINVAL;
	cryptlen -= authsize;

	crypto_gcm_init_crypt(abreq, req, cryptlen);
	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
					crypto_gcm_decrypt_done, req);

	crypto_gcm_ghash_update_sg(ghash, req->src, cryptlen);

	err = crypto_ablkcipher_decrypt(abreq);
	if (err)
		return err;

	return crypto_gcm_verify(req);
}
示例#5
0
static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)
{
	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
	struct scatterlist *sg;
	u8 *iv = req->iv;
	int err;

	err = crypto_ccm_check_iv(iv);
	if (err)
		return err;

	pctx->flags = aead_request_flags(req);

	 /* Note: rfc 3610 and NIST 800-38C require counter of
	 * zero to encrypt auth tag.
	 */
	memset(iv + 15 - iv[0], 0, iv[0] + 1);

	sg_init_table(pctx->src, 3);
	sg_set_buf(pctx->src, tag, 16);
	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
	if (sg != pctx->src + 1)
		sg_chain(pctx->src, 2, sg);

	if (req->src != req->dst) {
		sg_init_table(pctx->dst, 3);
		sg_set_buf(pctx->dst, tag, 16);
		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
		if (sg != pctx->dst + 1)
			sg_chain(pctx->dst, 2, sg);
	}

	return 0;
}
示例#6
0
static int crypto_ccm_decrypt(struct aead_request *req)
{
	struct crypto_aead *aead = crypto_aead_reqtfm(req);
	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
	struct ablkcipher_request *abreq = &pctx->abreq;
	struct scatterlist *dst;
	unsigned int authsize = crypto_aead_authsize(aead);
	unsigned int cryptlen = req->cryptlen;
	u8 *authtag = pctx->auth_tag;
	u8 *odata = pctx->odata;
	u8 *iv = req->iv;
	int err;

	if (cryptlen < authsize)
		return -EINVAL;
	cryptlen -= authsize;

	err = crypto_ccm_check_iv(iv);
	if (err)
		return err;

	pctx->flags = aead_request_flags(req);

	scatterwalk_map_and_copy(authtag, req->src, cryptlen, authsize, 0);

	memset(iv + 15 - iv[0], 0, iv[0] + 1);

	sg_init_table(pctx->src, 2);
	sg_set_buf(pctx->src, authtag, 16);
	scatterwalk_sg_chain(pctx->src, 2, req->src);

	dst = pctx->src;
	if (req->src != req->dst) {
		sg_init_table(pctx->dst, 2);
		sg_set_buf(pctx->dst, authtag, 16);
		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
		dst = pctx->dst;
	}

	ablkcipher_request_set_tfm(abreq, ctx->ctr);
	ablkcipher_request_set_callback(abreq, pctx->flags,
					crypto_ccm_decrypt_done, req);
	ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
	err = crypto_ablkcipher_decrypt(abreq);
	if (err)
		return err;

	err = crypto_ccm_auth(req, req->dst, cryptlen);
	if (err)
		return err;

	/* verify */
	if (crypto_memneq(authtag, odata, authsize))
		return -EBADMSG;

	return err;
}
示例#7
0
文件: gcm.c 项目: jtcriswell/linux256
static int gcm_hash_final(struct aead_request *req,
                          struct crypto_gcm_req_priv_ctx *pctx)
{
    struct ahash_request *ahreq = &pctx->u.ahreq;

    ahash_request_set_callback(ahreq, aead_request_flags(req),
                               gcm_hash_final_done, req);
    ahash_request_set_crypt(ahreq, NULL, pctx->iauth_tag, 0);

    return crypto_ahash_final(ahreq);
}
示例#8
0
static int crypto_ccm_encrypt(struct aead_request *req)
{
	struct crypto_aead *aead = crypto_aead_reqtfm(req);
	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
	struct ablkcipher_request *abreq = &pctx->abreq;
	struct scatterlist *dst;
	unsigned int cryptlen = req->cryptlen;
	u8 *odata = pctx->odata;
	u8 *iv = req->iv;
	int err;

	err = crypto_ccm_check_iv(iv);
	if (err)
		return err;

	pctx->flags = aead_request_flags(req);

	err = crypto_ccm_auth(req, req->src, cryptlen);
	if (err)
		return err;

	 /* Note: rfc 3610 and NIST 800-38C require counter of
	 * zero to encrypt auth tag.
	 */
	memset(iv + 15 - iv[0], 0, iv[0] + 1);

	sg_init_table(pctx->src, 2);
	sg_set_buf(pctx->src, odata, 16);
	scatterwalk_sg_chain(pctx->src, 2, req->src);

	dst = pctx->src;
	if (req->src != req->dst) {
		sg_init_table(pctx->dst, 2);
		sg_set_buf(pctx->dst, odata, 16);
		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
		dst = pctx->dst;
	}

	ablkcipher_request_set_tfm(abreq, ctx->ctr);
	ablkcipher_request_set_callback(abreq, pctx->flags,
					crypto_ccm_encrypt_done, req);
	ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
	err = crypto_ablkcipher_encrypt(abreq);
	if (err)
		return err;

	/* copy authtag to end of dst */
	scatterwalk_map_and_copy(odata, req->dst, cryptlen,
				 crypto_aead_authsize(aead), 1);
	return err;
}
示例#9
0
文件: gcm.c 项目: jtcriswell/linux256
static int gcm_hash_remain(struct aead_request *req,
                           struct crypto_gcm_req_priv_ctx *pctx,
                           unsigned int remain,
                           crypto_completion_t compl)
{
    struct ahash_request *ahreq = &pctx->u.ahreq;

    ahash_request_set_callback(ahreq, aead_request_flags(req),
                               compl, req);
    sg_init_one(pctx->src, gcm_zeroes, remain);
    ahash_request_set_crypt(ahreq, pctx->src, NULL, remain);

    return crypto_ahash_update(ahreq);
}
示例#10
0
文件: gcm.c 项目: jtcriswell/linux256
static int gcm_hash_update(struct aead_request *req,
                           struct crypto_gcm_req_priv_ctx *pctx,
                           crypto_completion_t compl,
                           struct scatterlist *src,
                           unsigned int len)
{
    struct ahash_request *ahreq = &pctx->u.ahreq;

    ahash_request_set_callback(ahreq, aead_request_flags(req),
                               compl, req);
    ahash_request_set_crypt(ahreq, src, NULL, len);

    return crypto_ahash_update(ahreq);
}
示例#11
0
文件: gcm.c 项目: jtcriswell/linux256
static int gcm_hash(struct aead_request *req,
                    struct crypto_gcm_req_priv_ctx *pctx)
{
    struct ahash_request *ahreq = &pctx->u.ahreq;
    struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
    struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
    unsigned int remain;
    crypto_completion_t compl;
    int err;

    ahash_request_set_tfm(ahreq, ctx->ghash);

    ahash_request_set_callback(ahreq, aead_request_flags(req),
                               gcm_hash_init_done, req);
    err = crypto_ahash_init(ahreq);
    if (err)
        return err;
    remain = gcm_remain(req->assoclen);
    compl = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done;
    err = gcm_hash_update(req, pctx, compl, req->assoc, req->assoclen);
    if (err)
        return err;
    if (remain) {
        err = gcm_hash_remain(req, pctx, remain,
                              gcm_hash_assoc_remain_done);
        if (err)
            return err;
    }
    remain = gcm_remain(gctx->cryptlen);
    compl = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done;
    err = gcm_hash_update(req, pctx, compl, gctx->src, gctx->cryptlen);
    if (err)
        return err;
    if (remain) {
        err = gcm_hash_remain(req, pctx, remain,
                              gcm_hash_crypt_remain_done);
        if (err)
            return err;
    }
    err = gcm_hash_len(req, pctx);
    if (err)
        return err;
    err = gcm_hash_final(req, pctx);
    if (err)
        return err;

    return 0;
}
示例#12
0
static int crypto_gcm_encrypt(struct aead_request *req)
{
	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
	struct ablkcipher_request *abreq = &pctx->abreq;
	int err;

	crypto_gcm_init_crypt(abreq, req, req->cryptlen);
	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
					crypto_gcm_encrypt_done, req);

	err = crypto_ablkcipher_encrypt(abreq);
	if (err)
		return err;

	return crypto_gcm_hash(req);
}
示例#13
0
文件: gcm.c 项目: jtcriswell/linux256
static int gcm_hash_len(struct aead_request *req,
                        struct crypto_gcm_req_priv_ctx *pctx)
{
    struct ahash_request *ahreq = &pctx->u.ahreq;
    struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
    u128 lengths;

    lengths.a = cpu_to_be64(req->assoclen * 8);
    lengths.b = cpu_to_be64(gctx->cryptlen * 8);
    memcpy(pctx->iauth_tag, &lengths, 16);
    sg_init_one(pctx->src, pctx->iauth_tag, 16);
    ahash_request_set_callback(ahreq, aead_request_flags(req),
                               gcm_hash_len_done, req);
    ahash_request_set_crypt(ahreq, pctx->src,
                            NULL, sizeof(lengths));

    return crypto_ahash_update(ahreq);
}
示例#14
0
static void gcm_dec_hash_done(struct crypto_async_request *areq, int err)
{
	struct aead_request *req = areq->data;
	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
	struct ablkcipher_request *abreq = &pctx->u.abreq;
	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;

	if (!err) {
		ablkcipher_request_set_callback(abreq, aead_request_flags(req),
						gcm_decrypt_done, req);
		crypto_gcm_init_crypt(abreq, req, gctx->cryptlen);
		err = crypto_ablkcipher_decrypt(abreq);
		if (err == -EINPROGRESS || err == -EBUSY)
			return;
	}

	gcm_decrypt_done(areq, err);
}