From patchwork Mon Jan 22 23:04:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junaid Shahid X-Patchwork-Id: 10179435 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 544A960224 for ; Mon, 22 Jan 2018 23:04:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 45B6F28518 for ; Mon, 22 Jan 2018 23:04:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3A84F285B5; Mon, 22 Jan 2018 23:04:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A149E28518 for ; Mon, 22 Jan 2018 23:04:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751030AbeAVXEL (ORCPT ); Mon, 22 Jan 2018 18:04:11 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:39601 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751049AbeAVXEK (ORCPT ); Mon, 22 Jan 2018 18:04:10 -0500 Received: by mail-pf0-f193.google.com with SMTP id e11so8251924pff.6 for ; Mon, 22 Jan 2018 15:04:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nfGhi/TRrWyaYFVWfajWSYosYJA75qFaKsNEMEam2B0=; b=Lyc0993gYFLm/HBGYk6GWRro5n86/wpfiJKc8f7xbeXqvp5YqiklJ8NmKSF+cMiqyk CHFf+vTq2Cyl9KoWgH8eekjsUxjtT3edxzJgwCxgPEheF8Hfh+qS+OaiXeJxH78NkuP7 sNI11oySOCBoYttpcsO3KJxUJEYxsKvul5a7BzB0f/6IMJMtxHha8RsUncYkEpC15x7L HACuqAJ3x24XyEpImsPmKuoriHNlom5pdeyDApwsKXJU9eblqVrsA98ncBAZZw68mfS3 ptnKArUkZMIPoXfMIkdscZ4nTyulX9wGMBfkAdkLfxdKo25XJeeeQW0M+gGP/Fj51ZaR LUnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nfGhi/TRrWyaYFVWfajWSYosYJA75qFaKsNEMEam2B0=; b=CDMxKgJoQDn7248lL86EP1vl1aTPGeWhAnjEXWqp7CV1gsR+uRqnCN+65xGbl210YX ApM8nr2zYulB4xJdaAIEVkh3y21NYzxK3x3VWWnR914fwVKBu4Ffb3k+qkTGMJbn83Vh rYNewYuXdawGC02gcENyfCknDI8gemx04YVyGNxUXDXPNxLRfGc/wS4O6Hq2tt90VEEm RVYSGGYajv3L95cuvCmj8S7wTivTnwxUGmoeqBX98ZQiayIDpUponZlWuteaVD3JJywh Y+q6zMgx24OnRfxevQXFT8iMD3zEz7M6EXcOJv9ZQnh+YKt0+oMKxAEXaApQN+AmT6EW IPug== X-Gm-Message-State: AKwxytfL9AbCn4kh072KWnFHtYqUkTYEl6OWpQZM7SNGOQJZaGS8Ulsk J+TQ5sBhL+873TESfesBElokrw== X-Google-Smtp-Source: AH8x224mmq+E/14p617+VXu3/ptJnMbu3HXey4YGpq5HRgDKsXPnoX/jpSIdqGIv+NN4wLinxlzm7g== X-Received: by 2002:a17:902:2845:: with SMTP id e63-v6mr3868422plb.438.1516662249579; Mon, 22 Jan 2018 15:04:09 -0800 (PST) Received: from js-desktop.svl.corp.google.com ([2620:15c:2cb:1:cdad:b4d5:21d1:e91e]) by smtp.gmail.com with ESMTPSA id c29sm1976297pfd.172.2018.01.22.15.04.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 22 Jan 2018 15:04:09 -0800 (PST) From: Junaid Shahid To: herbert@gondor.apana.org.au Cc: linux-crypto@vger.kernel.org, andreslc@google.com, davem@davemloft.net, gthelen@google.com, ebiggers3@gmail.com Subject: [PATCH 4/4] crypto: aesni - Use zero-copy for gcm(aes) even if the AAD/Data/AuthTag are separate Date: Mon, 22 Jan 2018 15:04:03 -0800 Message-Id: <20180122230403.52572-5-junaids@google.com> X-Mailer: git-send-email 2.16.0.rc1.238.g530d649a79-goog In-Reply-To: <20180122230403.52572-1-junaids@google.com> References: <20180122230403.52572-1-junaids@google.com> Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Enable the use of zero-copy even if the AAD and/or Auth Tag are in different buffers than the actual data, as long as each of them individually satisfies the zero-copy conditions (i.e. the entire buffer is either in low-mem or within a single high-mem page). Signed-off-by: Junaid Shahid --- arch/x86/crypto/aesni-intel_glue.c | 121 +++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 32 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 03892dd80a12..2a44285ed66c 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -756,42 +756,91 @@ static u8 *map_buffer(struct scatterlist *sgl) } /* - * Maps the sglist buffer and returns a pointer to the mapped buffer in - * data_buf. + * Maps the sglist buffer and returns pointers to the mapped buffers in assoc, + * data and (optionally) auth_tag. * * If direct mapping is not feasible, then allocates a bounce buffer if one - * isn't already available in bounce_buf, and returns a pointer to the bounce - * buffer in data_buf. + * isn't already available in bounce_buf, and returns pointers within the bounce + * buffer in assoc, data and auth_tag. * - * When the buffer is no longer needed, put_request_buffer() should be called on - * the data_buf and the bounce_buf should be freed using kfree(). + * When the buffers are no longer needed, put_request_buffers() should be called + * and the bounce_buf should be freed using kfree(). */ -static int get_request_buffer(struct scatterlist *sgl, - unsigned long bounce_buf_size, - u8 **data_buf, u8 **bounce_buf, bool *mapped) +static int get_request_buffers(struct scatterlist *sgl, + unsigned long assoc_len, unsigned long data_len, + unsigned long auth_tag_len, + u8 **assoc, u8 **data, u8 **auth_tag, + u8 **bounce_buf, bool *mapped) { - if (sg_is_last(sgl) && is_mappable(sgl, sgl->length)) { + struct scatterlist sgl_data_chain[2], sgl_auth_tag_chain[2]; + struct scatterlist *sgl_data, *sgl_auth_tag; + + sgl_data = scatterwalk_ffwd(sgl_data_chain, sgl, assoc_len); + sgl_auth_tag = scatterwalk_ffwd(sgl_auth_tag_chain, sgl, + assoc_len + data_len); + + if (is_mappable(sgl, assoc_len) && is_mappable(sgl_data, data_len) && + (auth_tag == NULL || is_mappable(sgl_auth_tag, auth_tag_len))) { *mapped = true; - *data_buf = map_buffer(sgl); + + *assoc = map_buffer(sgl); + + if (sgl->length >= assoc_len + data_len) + *data = *assoc + assoc_len; + else + *data = map_buffer(sgl_data); + + if (auth_tag != NULL) { + if (sgl_data->length >= data_len + auth_tag_len) + *auth_tag = *data + data_len; + else + *auth_tag = map_buffer(sgl_auth_tag); + } + return 0; } *mapped = false; if (*bounce_buf == NULL) { - *bounce_buf = kmalloc(bounce_buf_size, GFP_ATOMIC); + *bounce_buf = kmalloc(assoc_len + data_len + auth_tag_len, + GFP_ATOMIC); if (unlikely(*bounce_buf == NULL)) return -ENOMEM; } - *data_buf = *bounce_buf; + *assoc = *bounce_buf; + *data = *assoc + assoc_len; + + if (auth_tag != NULL) + *auth_tag = *data + data_len; + return 0; } -static void put_request_buffer(u8 *data_buf, bool mapped) +static void put_request_buffers(struct scatterlist *sgl, bool mapped, + u8 *assoc, u8 *data, u8 *auth_tag, + unsigned long assoc_len, + unsigned long data_len, + unsigned long auth_tag_len) { - if (mapped) - kunmap_atomic(data_buf); + struct scatterlist sgl_data_chain[2]; + struct scatterlist *sgl_data; + + if (!mapped) + return; + + sgl_data = scatterwalk_ffwd(sgl_data_chain, sgl, assoc_len); + + /* The unmaps need to be done in reverse order of the maps. */ + + if (auth_tag != NULL && sgl_data->length < data_len + auth_tag_len) + kunmap_atomic(auth_tag); + + if (sgl->length < assoc_len + data_len) + kunmap_atomic(data); + + kunmap_atomic(assoc); } /* @@ -803,34 +852,38 @@ static void put_request_buffer(u8 *data_buf, bool mapped) static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, u8 *hash_subkey, u8 *iv, void *aes_ctx, bool decrypt) { - u8 *src, *dst, *assoc, *bounce_buf = NULL; + u8 *src, *src_assoc; + u8 *dst, *dst_assoc; + u8 *auth_tag; + u8 *bounce_buf = NULL; bool src_mapped = false, dst_mapped = false; struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned long auth_tag_len = crypto_aead_authsize(tfm); unsigned long data_len = req->cryptlen - (decrypt ? auth_tag_len : 0); int retval = 0; - unsigned long bounce_buf_size = data_len + auth_tag_len + req->assoclen; if (auth_tag_len > 16) return -EINVAL; - retval = get_request_buffer(req->src, bounce_buf_size, &assoc, - &bounce_buf, &src_mapped); + retval = get_request_buffers(req->src, req->assoclen, data_len, + auth_tag_len, &src_assoc, &src, + (decrypt || req->src == req->dst) + ? &auth_tag : NULL, + &bounce_buf, &src_mapped); if (retval) goto exit; - src = assoc + req->assoclen; - if (req->src == req->dst) { + dst_assoc = src_assoc; dst = src; dst_mapped = src_mapped; } else { - retval = get_request_buffer(req->dst, bounce_buf_size, &dst, - &bounce_buf, &dst_mapped); + retval = get_request_buffers(req->dst, req->assoclen, data_len, + auth_tag_len, &dst_assoc, &dst, + decrypt ? NULL : &auth_tag, + &bounce_buf, &dst_mapped); if (retval) goto exit; - - dst += req->assoclen; } if (!src_mapped) @@ -843,16 +896,16 @@ static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, u8 gen_auth_tag[16]; aesni_gcm_dec_tfm(aes_ctx, dst, src, data_len, iv, - hash_subkey, assoc, assoclen, + hash_subkey, src_assoc, assoclen, gen_auth_tag, auth_tag_len); /* Compare generated tag with passed in tag. */ - if (crypto_memneq(src + data_len, gen_auth_tag, auth_tag_len)) + if (crypto_memneq(auth_tag, gen_auth_tag, auth_tag_len)) retval = -EBADMSG; } else aesni_gcm_enc_tfm(aes_ctx, dst, src, data_len, iv, - hash_subkey, assoc, assoclen, - dst + data_len, auth_tag_len); + hash_subkey, src_assoc, assoclen, + auth_tag, auth_tag_len); kernel_fpu_end(); @@ -862,9 +915,13 @@ static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, 1); exit: if (req->dst != req->src) - put_request_buffer(dst - req->assoclen, dst_mapped); + put_request_buffers(req->dst, dst_mapped, dst_assoc, dst, + decrypt ? NULL : auth_tag, + req->assoclen, data_len, auth_tag_len); - put_request_buffer(assoc, src_mapped); + put_request_buffers(req->src, src_mapped, src_assoc, src, + (decrypt || req->src == req->dst) ? auth_tag : NULL, + req->assoclen, data_len, auth_tag_len); kfree(bounce_buf); return retval;