Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c6788a6 authored by Zhen Kong's avatar Zhen Kong
Browse files

crypto: msm: fix rfc4309(ccm(aes)) issue on msm-4.4



In newer kernel (msm-4.4 or later), for AEAD ciphering, crypto api has
been re-worked and the assoclen defines the length of association data
and iv together. But for rfc4309(ccm(aes)), iv is not part of AAD.
Therefore, change qcrypto driver to remove the iv, by subtract 8 from
assoclen for rfc4309(ccm(aes)).

Change-Id: I37eb1934d7817b5b5c33440122b68e5d37854960
Signed-off-by: default avatarZhen Kong <zkong@codeaurora.org>
parent 64a6d728
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -439,6 +439,7 @@ struct qcrypto_cipher_req_ctx {
	u8 rfc4309_iv[QCRYPTO_MAX_IV_LENGTH];
	unsigned int ivsize;
	int  aead;
	int  ccmtype;			/* default: 0, rfc4309: 1 */
	struct scatterlist asg;		/* Formatted associated data sg  */
	unsigned char *adata;		/* Pointer to formatted assoc data */
	enum qce_cipher_alg_enum alg;
@@ -1936,9 +1937,8 @@ static int aead_ccm_set_msg_len(u8 *block, unsigned int msglen, int csize)
	return 0;
}

static int qccrypto_set_aead_ccm_nonce(struct qce_req *qreq)
static int qccrypto_set_aead_ccm_nonce(struct qce_req *qreq, uint32_t assoclen)
{
	struct aead_request *areq = (struct aead_request *) qreq->areq;
	unsigned int i = ((unsigned int)qreq->iv[0]) + 1;

	memcpy(&qreq->nonce[0], qreq->iv, qreq->ivsize);
@@ -1947,7 +1947,7 @@ static int qccrypto_set_aead_ccm_nonce(struct qce_req *qreq)
	 * NIST Special Publication 800-38C
	 */
	qreq->nonce[0] |= (8 * ((qreq->authsize - 2) / 2));
	if (areq->assoclen)
	if (assoclen)
		qreq->nonce[0] |= 64;

	if (i > MAX_NONCE)
@@ -2153,24 +2153,31 @@ static int _qcrypto_process_aead(struct crypto_engine *pengine,
	qreq.flags = cipher_ctx->flags;

	if (qreq.mode == QCE_MODE_CCM) {
		uint32_t assoclen;

		if (qreq.dir == QCE_ENCRYPT)
			qreq.cryptlen = req->cryptlen;
		else
			qreq.cryptlen = req->cryptlen -
						qreq.authsize;

		/* if rfc4309 ccm, adjust assoclen */
		assoclen = req->assoclen;
		if (rctx->ccmtype)
			assoclen -= 8;
		/* Get NONCE */
		ret = qccrypto_set_aead_ccm_nonce(&qreq);
		ret = qccrypto_set_aead_ccm_nonce(&qreq, assoclen);
		if (ret)
			return ret;

		if (req->assoclen) {
			rctx->adata = kzalloc((req->assoclen + 0x64),
		if (assoclen) {
			rctx->adata = kzalloc((assoclen + 0x64),
								GFP_ATOMIC);
			if (!rctx->adata)
				return -ENOMEM;
			/* Format Associated data    */
			ret = qcrypto_aead_ccm_format_adata(&qreq,
						req->assoclen,
						assoclen,
						req->src,
						rctx->adata);
		} else {
@@ -2633,6 +2640,7 @@ static int _qcrypto_aead_encrypt_aes_ccm(struct aead_request *req)
	rctx->dir = QCE_ENCRYPT;
	rctx->mode = QCE_MODE_CCM;
	rctx->iv = req->iv;
	rctx->ccmtype = 0;

	pstat->aead_ccm_aes_enc++;
	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
@@ -2647,6 +2655,8 @@ static int _qcrypto_aead_rfc4309_enc_aes_ccm(struct aead_request *req)

	pstat = &_qcrypto_stat;

	if (req->assoclen != 16 && req->assoclen != 20)
		return -EINVAL;
	rctx = aead_request_ctx(req);
	rctx->aead = 1;
	rctx->alg = CIPHER_ALG_AES;
@@ -2656,6 +2666,7 @@ static int _qcrypto_aead_rfc4309_enc_aes_ccm(struct aead_request *req)
	rctx->rfc4309_iv[0] = 3; /* L -1 */
	memcpy(&rctx->rfc4309_iv[1], ctx->ccm4309_nonce, 3);
	memcpy(&rctx->rfc4309_iv[4], req->iv, 8);
	rctx->ccmtype = 1;
	rctx->iv = rctx->rfc4309_iv;
	pstat->aead_rfc4309_ccm_aes_enc++;
	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
@@ -2963,6 +2974,7 @@ static int _qcrypto_aead_decrypt_aes_ccm(struct aead_request *req)
	rctx->dir = QCE_DECRYPT;
	rctx->mode = QCE_MODE_CCM;
	rctx->iv = req->iv;
	rctx->ccmtype = 0;

	pstat->aead_ccm_aes_dec++;
	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
@@ -2976,6 +2988,8 @@ static int _qcrypto_aead_rfc4309_dec_aes_ccm(struct aead_request *req)
	struct crypto_stat *pstat;

	pstat = &_qcrypto_stat;
	if (req->assoclen != 16 && req->assoclen != 20)
		return -EINVAL;
	rctx = aead_request_ctx(req);
	rctx->aead = 1;
	rctx->alg = CIPHER_ALG_AES;
@@ -2985,6 +2999,7 @@ static int _qcrypto_aead_rfc4309_dec_aes_ccm(struct aead_request *req)
	rctx->rfc4309_iv[0] = 3; /* L -1 */
	memcpy(&rctx->rfc4309_iv[1], ctx->ccm4309_nonce, 3);
	memcpy(&rctx->rfc4309_iv[4], req->iv, 8);
	rctx->ccmtype = 1;
	rctx->iv = rctx->rfc4309_iv;
	pstat->aead_rfc4309_ccm_aes_dec++;
	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);