Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3070158imu; Thu, 29 Nov 2018 15:04:34 -0800 (PST) X-Google-Smtp-Source: AFSGD/U5PdFAjZfgCC76IU3P//Cusip0HE7c86i58FRYect+us+bOmI36m/cBJdjCJlCPXYmwaze X-Received: by 2002:a17:902:c05:: with SMTP id 5mr3380756pls.155.1543532674481; Thu, 29 Nov 2018 15:04:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543532674; cv=none; d=google.com; s=arc-20160816; b=arTAvF1OdnurcewFCr6usyRb8nEq1TxUPaaAZz7Y9sYpueZMRB0G8REHjthkD5EWvY 3vGT0UyfPfNjt75MLrxS6udbTC9j1qRzc5OHVKDuQjDU02ekBUuY+yvm1FVA3pdBYNQS ie7MzqKuO9Aet/febMF8fZQrJsKWDd7gpbgAEM5NNSnlDe6JA714wgfDpAALuhLkr2Sy YPBQdMLZYPhIxojaBds+dDL58KpobmnLNl0r6VyEOb0tZI6/8vRx7NwMB5HZjRTeIqUp XWBDRTRDX9tSeQajfnkx0j+IAZKCFtrpPOcgPvQxNCrP+yHNpFnqZ6xmHtklsYr5iT1s D/3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=2/0aUawGdzJ/Pce1aPnPn7mbGJxiW6cc/9DEhMcbULQ=; b=rxYlO98mExkX7xVCOIb4mQl/+RfyIwDNOe4HC4QKIEPd8+zVELkJR3ZvW4YnZGhOK6 TlFjr5JMED75TRjtN6Ea29bGkwT7r4IDtxG6D/YOO2Xx4GeuQdMX8DUGjTRU8Q1taq3D GP6Dl2bKotHMzX2Db/qgJm7o6MdI881W0VJhpiY0h3pKhS3YfPSOkYmksT2oc/6tfXHh 3cpEdroGzMPTdU3K/pVl37tqBzWINI3WqF0ZKVkRBgcXg+OZUdRz9F2dflKsW4G1k6eW uRt53MjUL+58qGvq0NUA6c4mGfSO8/3It1cDokgj8SetfWqdzD+/0zBGQIha7Lf3zvt8 Ev4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fD3r8Gbf; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x141si3290566pgx.266.2018.11.29.15.04.19; Thu, 29 Nov 2018 15:04:34 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fD3r8Gbf; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727083AbeK3KKn (ORCPT + 99 others); Fri, 30 Nov 2018 05:10:43 -0500 Received: from mail.kernel.org ([198.145.29.99]:44940 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726891AbeK3KKf (ORCPT ); Fri, 30 Nov 2018 05:10:35 -0500 Received: from ebiggers.mtv.corp.google.com (unknown [104.132.1.85]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4372A21479; Thu, 29 Nov 2018 23:03:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543532607; bh=4CDUl/a/7tTBYk9YWg8I+Xk7pfT7SorGHncYTmI9D7w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fD3r8Gbf+SIQEGm33Kf5GfgTzHaP2sPTOORAX3mt55uNwpno+XiIrIiTkCpZzbU/a cWxdCURW7q9a5uVY6G8xYVEopt0s85Woz4lP9uYGgXeXzR1ktizlChoZ8MgxncyoJK 8PxJxfAYsZ7Y6KH5crch9pCrI5iW86u6TMtezfRM= From: Eric Biggers To: linux-crypto@vger.kernel.org Cc: Paul Crowley , Martin Willi , Milan Broz , "Jason A . Donenfeld" , linux-kernel@vger.kernel.org Subject: [PATCH v2 5/6] crypto: x86/chacha20 - refactor to allow varying number of rounds Date: Thu, 29 Nov 2018 15:02:16 -0800 Message-Id: <20181129230217.158038-6-ebiggers@kernel.org> X-Mailer: git-send-email 2.20.0.rc0.387.gc7a69e6b6c-goog In-Reply-To: <20181129230217.158038-1-ebiggers@kernel.org> References: <20181129230217.158038-1-ebiggers@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Eric Biggers In preparation for adding XChaCha12 support, rename/refactor the x86_64 SIMD implementations of ChaCha20 to support different numbers of rounds. Signed-off-by: Eric Biggers --- arch/x86/crypto/Makefile | 8 +- ...a20-avx2-x86_64.S => chacha-avx2-x86_64.S} | 33 ++-- ...12vl-x86_64.S => chacha-avx512vl-x86_64.S} | 35 ++-- ...0-ssse3-x86_64.S => chacha-ssse3-x86_64.S} | 41 ++--- .../crypto/{chacha20_glue.c => chacha_glue.c} | 150 +++++++++--------- 5 files changed, 136 insertions(+), 131 deletions(-) rename arch/x86/crypto/{chacha20-avx2-x86_64.S => chacha-avx2-x86_64.S} (97%) rename arch/x86/crypto/{chacha20-avx512vl-x86_64.S => chacha-avx512vl-x86_64.S} (97%) rename arch/x86/crypto/{chacha20-ssse3-x86_64.S => chacha-ssse3-x86_64.S} (96%) rename arch/x86/crypto/{chacha20_glue.c => chacha_glue.c} (51%) diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile index 0b31b16f49d8..45734e1cf967 100644 --- a/arch/x86/crypto/Makefile +++ b/arch/x86/crypto/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o -obj-$(CONFIG_CRYPTO_CHACHA20_X86_64) += chacha20-x86_64.o +obj-$(CONFIG_CRYPTO_CHACHA20_X86_64) += chacha-x86_64.o obj-$(CONFIG_CRYPTO_SERPENT_SSE2_X86_64) += serpent-sse2-x86_64.o obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o @@ -78,7 +78,7 @@ camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o -chacha20-x86_64-y := chacha20-ssse3-x86_64.o chacha20_glue.o +chacha-x86_64-y := chacha-ssse3-x86_64.o chacha_glue.o serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o aegis128-aesni-y := aegis128-aesni-asm.o aegis128-aesni-glue.o @@ -103,7 +103,7 @@ endif ifeq ($(avx2_supported),yes) camellia-aesni-avx2-y := camellia-aesni-avx2-asm_64.o camellia_aesni_avx2_glue.o - chacha20-x86_64-y += chacha20-avx2-x86_64.o + chacha-x86_64-y += chacha-avx2-x86_64.o serpent-avx2-y := serpent-avx2-asm_64.o serpent_avx2_glue.o morus1280-avx2-y := morus1280-avx2-asm.o morus1280-avx2-glue.o @@ -112,7 +112,7 @@ ifeq ($(avx2_supported),yes) endif ifeq ($(avx512_supported),yes) - chacha20-x86_64-y += chacha20-avx512vl-x86_64.o + chacha-x86_64-y += chacha-avx512vl-x86_64.o endif aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o diff --git a/arch/x86/crypto/chacha20-avx2-x86_64.S b/arch/x86/crypto/chacha-avx2-x86_64.S similarity index 97% rename from arch/x86/crypto/chacha20-avx2-x86_64.S rename to arch/x86/crypto/chacha-avx2-x86_64.S index b6ab082be657..32903fd450af 100644 --- a/arch/x86/crypto/chacha20-avx2-x86_64.S +++ b/arch/x86/crypto/chacha-avx2-x86_64.S @@ -1,5 +1,5 @@ /* - * ChaCha20 256-bit cipher algorithm, RFC7539, x64 AVX2 functions + * ChaCha 256-bit cipher algorithm, x64 AVX2 functions * * Copyright (C) 2015 Martin Willi * @@ -38,13 +38,14 @@ CTR4BL: .octa 0x00000000000000000000000000000002 .text -ENTRY(chacha20_2block_xor_avx2) +ENTRY(chacha_2block_xor_avx2) # %rdi: Input state matrix, s # %rsi: up to 2 data blocks output, o # %rdx: up to 2 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts two ChaCha20 blocks by loading the state + # This function encrypts two ChaCha blocks by loading the state # matrix twice across four AVX registers. It performs matrix operations # on four words in each matrix in parallel, but requires shuffling to # rearrange the words after each round. @@ -68,7 +69,6 @@ ENTRY(chacha20_2block_xor_avx2) vmovdqa ROT16(%rip),%ymm5 mov %rcx,%rax - mov $10,%ecx .Ldoubleround: @@ -138,7 +138,7 @@ ENTRY(chacha20_2block_xor_avx2) # x3 = shuffle32(x3, MASK(0, 3, 2, 1)) vpshufd $0x39,%ymm3,%ymm3 - dec %ecx + sub $2,%r8d jnz .Ldoubleround # o0 = i0 ^ (x0 + s0) @@ -228,15 +228,16 @@ ENTRY(chacha20_2block_xor_avx2) lea -8(%r10),%rsp jmp .Ldone2 -ENDPROC(chacha20_2block_xor_avx2) +ENDPROC(chacha_2block_xor_avx2) -ENTRY(chacha20_4block_xor_avx2) +ENTRY(chacha_4block_xor_avx2) # %rdi: Input state matrix, s # %rsi: up to 4 data blocks output, o # %rdx: up to 4 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts four ChaCha20 block by loading the state + # This function encrypts four ChaCha blocks by loading the state # matrix four times across eight AVX registers. It performs matrix # operations on four words in two matrices in parallel, sequentially # to the operations on the four words of the other two matrices. The @@ -269,7 +270,6 @@ ENTRY(chacha20_4block_xor_avx2) vmovdqa ROT16(%rip),%ymm9 mov %rcx,%rax - mov $10,%ecx .Ldoubleround4: @@ -389,7 +389,7 @@ ENTRY(chacha20_4block_xor_avx2) vpshufd $0x39,%ymm3,%ymm3 vpshufd $0x39,%ymm7,%ymm7 - dec %ecx + sub $2,%r8d jnz .Ldoubleround4 # o0 = i0 ^ (x0 + s0), first block @@ -533,15 +533,16 @@ ENTRY(chacha20_4block_xor_avx2) lea -8(%r10),%rsp jmp .Ldone4 -ENDPROC(chacha20_4block_xor_avx2) +ENDPROC(chacha_4block_xor_avx2) -ENTRY(chacha20_8block_xor_avx2) +ENTRY(chacha_8block_xor_avx2) # %rdi: Input state matrix, s # %rsi: up to 8 data blocks output, o # %rdx: up to 8 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts eight consecutive ChaCha20 blocks by loading + # This function encrypts eight consecutive ChaCha blocks by loading # the state matrix in AVX registers eight times. As we need some # scratch registers, we save the first four registers on the stack. The # algorithm performs each operation on the corresponding word of each @@ -588,8 +589,6 @@ ENTRY(chacha20_8block_xor_avx2) # x12 += counter values 0-3 vpaddd %ymm1,%ymm12,%ymm12 - mov $10,%ecx - .Ldoubleround8: # x0 += x4, x12 = rotl32(x12 ^ x0, 16) vpaddd 0x00(%rsp),%ymm4,%ymm0 @@ -775,7 +774,7 @@ ENTRY(chacha20_8block_xor_avx2) vpsrld $25,%ymm4,%ymm4 vpor %ymm0,%ymm4,%ymm4 - dec %ecx + sub $2,%r8d jnz .Ldoubleround8 # x0..15[0-3] += s[0..15] @@ -1023,4 +1022,4 @@ ENTRY(chacha20_8block_xor_avx2) jmp .Ldone8 -ENDPROC(chacha20_8block_xor_avx2) +ENDPROC(chacha_8block_xor_avx2) diff --git a/arch/x86/crypto/chacha20-avx512vl-x86_64.S b/arch/x86/crypto/chacha-avx512vl-x86_64.S similarity index 97% rename from arch/x86/crypto/chacha20-avx512vl-x86_64.S rename to arch/x86/crypto/chacha-avx512vl-x86_64.S index 55d34de29e3e..848f9c75fd4f 100644 --- a/arch/x86/crypto/chacha20-avx512vl-x86_64.S +++ b/arch/x86/crypto/chacha-avx512vl-x86_64.S @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * ChaCha20 256-bit cipher algorithm, RFC7539, x64 AVX-512VL functions + * ChaCha 256-bit cipher algorithm, x64 AVX-512VL functions * * Copyright (C) 2018 Martin Willi */ @@ -24,13 +24,14 @@ CTR8BL: .octa 0x00000003000000020000000100000000 .text -ENTRY(chacha20_2block_xor_avx512vl) +ENTRY(chacha_2block_xor_avx512vl) # %rdi: Input state matrix, s # %rsi: up to 2 data blocks output, o # %rdx: up to 2 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts two ChaCha20 blocks by loading the state + # This function encrypts two ChaCha blocks by loading the state # matrix twice across four AVX registers. It performs matrix operations # on four words in each matrix in parallel, but requires shuffling to # rearrange the words after each round. @@ -50,8 +51,6 @@ ENTRY(chacha20_2block_xor_avx512vl) vmovdqa %ymm2,%ymm10 vmovdqa %ymm3,%ymm11 - mov $10,%rax - .Ldoubleround: # x0 += x1, x3 = rotl32(x3 ^ x0, 16) @@ -108,7 +107,7 @@ ENTRY(chacha20_2block_xor_avx512vl) # x3 = shuffle32(x3, MASK(0, 3, 2, 1)) vpshufd $0x39,%ymm3,%ymm3 - dec %rax + sub $2,%r8d jnz .Ldoubleround # o0 = i0 ^ (x0 + s0) @@ -188,15 +187,16 @@ ENTRY(chacha20_2block_xor_avx512vl) jmp .Ldone2 -ENDPROC(chacha20_2block_xor_avx512vl) +ENDPROC(chacha_2block_xor_avx512vl) -ENTRY(chacha20_4block_xor_avx512vl) +ENTRY(chacha_4block_xor_avx512vl) # %rdi: Input state matrix, s # %rsi: up to 4 data blocks output, o # %rdx: up to 4 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts four ChaCha20 block by loading the state + # This function encrypts four ChaCha blocks by loading the state # matrix four times across eight AVX registers. It performs matrix # operations on four words in two matrices in parallel, sequentially # to the operations on the four words of the other two matrices. The @@ -225,8 +225,6 @@ ENTRY(chacha20_4block_xor_avx512vl) vmovdqa %ymm3,%ymm14 vmovdqa %ymm7,%ymm15 - mov $10,%rax - .Ldoubleround4: # x0 += x1, x3 = rotl32(x3 ^ x0, 16) @@ -321,7 +319,7 @@ ENTRY(chacha20_4block_xor_avx512vl) vpshufd $0x39,%ymm3,%ymm3 vpshufd $0x39,%ymm7,%ymm7 - dec %rax + sub $2,%r8d jnz .Ldoubleround4 # o0 = i0 ^ (x0 + s0), first block @@ -455,15 +453,16 @@ ENTRY(chacha20_4block_xor_avx512vl) jmp .Ldone4 -ENDPROC(chacha20_4block_xor_avx512vl) +ENDPROC(chacha_4block_xor_avx512vl) -ENTRY(chacha20_8block_xor_avx512vl) +ENTRY(chacha_8block_xor_avx512vl) # %rdi: Input state matrix, s # %rsi: up to 8 data blocks output, o # %rdx: up to 8 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts eight consecutive ChaCha20 blocks by loading + # This function encrypts eight consecutive ChaCha blocks by loading # the state matrix in AVX registers eight times. Compared to AVX2, this # mostly benefits from the new rotate instructions in VL and the # additional registers. @@ -508,8 +507,6 @@ ENTRY(chacha20_8block_xor_avx512vl) vmovdqa64 %ymm14,%ymm30 vmovdqa64 %ymm15,%ymm31 - mov $10,%eax - .Ldoubleround8: # x0 += x4, x12 = rotl32(x12 ^ x0, 16) vpaddd %ymm0,%ymm4,%ymm0 @@ -647,7 +644,7 @@ ENTRY(chacha20_8block_xor_avx512vl) vpxord %ymm9,%ymm4,%ymm4 vprold $7,%ymm4,%ymm4 - dec %eax + sub $2,%r8d jnz .Ldoubleround8 # x0..15[0-3] += s[0..15] @@ -836,4 +833,4 @@ ENTRY(chacha20_8block_xor_avx512vl) jmp .Ldone8 -ENDPROC(chacha20_8block_xor_avx512vl) +ENDPROC(chacha_8block_xor_avx512vl) diff --git a/arch/x86/crypto/chacha20-ssse3-x86_64.S b/arch/x86/crypto/chacha-ssse3-x86_64.S similarity index 96% rename from arch/x86/crypto/chacha20-ssse3-x86_64.S rename to arch/x86/crypto/chacha-ssse3-x86_64.S index 45e4ccdd9c98..613f80ae9857 100644 --- a/arch/x86/crypto/chacha20-ssse3-x86_64.S +++ b/arch/x86/crypto/chacha-ssse3-x86_64.S @@ -1,5 +1,5 @@ /* - * ChaCha20 256-bit cipher algorithm, RFC7539, x64 SSSE3 functions + * ChaCha 256-bit cipher algorithm, x64 SSSE3 functions * * Copyright (C) 2015 Martin Willi * @@ -24,7 +24,7 @@ CTRINC: .octa 0x00000003000000020000000100000000 .text /* - * chacha20_permute - permute one block + * chacha_permute - permute one block * * Permute one 64-byte block where the state matrix is in %xmm0-%xmm3. This * function performs matrix operations on four words in parallel, but requires @@ -32,13 +32,14 @@ CTRINC: .octa 0x00000003000000020000000100000000 * done with the slightly better performing SSSE3 byte shuffling, 7/12-bit word * rotation uses traditional shift+OR. * - * Clobbers: %ecx, %xmm4-%xmm7 + * The round count is given in %r8d. + * + * Clobbers: %r8d, %xmm4-%xmm7 */ -chacha20_permute: +chacha_permute: movdqa ROT8(%rip),%xmm4 movdqa ROT16(%rip),%xmm5 - mov $10,%ecx .Ldoubleround: # x0 += x1, x3 = rotl32(x3 ^ x0, 16) @@ -107,17 +108,18 @@ chacha20_permute: # x3 = shuffle32(x3, MASK(0, 3, 2, 1)) pshufd $0x39,%xmm3,%xmm3 - dec %ecx + sub $2,%r8d jnz .Ldoubleround ret -ENDPROC(chacha20_permute) +ENDPROC(chacha_permute) -ENTRY(chacha20_block_xor_ssse3) +ENTRY(chacha_block_xor_ssse3) # %rdi: Input state matrix, s # %rsi: up to 1 data block output, o # %rdx: up to 1 data block input, i # %rcx: input/output length in bytes + # %r8d: nrounds # x0..3 = s0..3 movdqa 0x00(%rdi),%xmm0 @@ -130,7 +132,7 @@ ENTRY(chacha20_block_xor_ssse3) movdqa %xmm3,%xmm11 mov %rcx,%rax - call chacha20_permute + call chacha_permute # o0 = i0 ^ (x0 + s0) paddd %xmm8,%xmm0 @@ -196,32 +198,35 @@ ENTRY(chacha20_block_xor_ssse3) lea -8(%r10),%rsp jmp .Ldone -ENDPROC(chacha20_block_xor_ssse3) +ENDPROC(chacha_block_xor_ssse3) -ENTRY(hchacha20_block_ssse3) +ENTRY(hchacha_block_ssse3) # %rdi: Input state matrix, s # %rsi: output (8 32-bit words) + # %edx: nrounds movdqa 0x00(%rdi),%xmm0 movdqa 0x10(%rdi),%xmm1 movdqa 0x20(%rdi),%xmm2 movdqa 0x30(%rdi),%xmm3 - call chacha20_permute + mov %edx,%r8d + call chacha_permute movdqu %xmm0,0x00(%rsi) movdqu %xmm3,0x10(%rsi) ret -ENDPROC(hchacha20_block_ssse3) +ENDPROC(hchacha_block_ssse3) -ENTRY(chacha20_4block_xor_ssse3) +ENTRY(chacha_4block_xor_ssse3) # %rdi: Input state matrix, s # %rsi: up to 4 data blocks output, o # %rdx: up to 4 data blocks input, i # %rcx: input/output length in bytes + # %r8d: nrounds - # This function encrypts four consecutive ChaCha20 blocks by loading the + # This function encrypts four consecutive ChaCha blocks by loading the # the state matrix in SSE registers four times. As we need some scratch # registers, we save the first four registers on the stack. The # algorithm performs each operation on the corresponding word of each @@ -274,8 +279,6 @@ ENTRY(chacha20_4block_xor_ssse3) # x12 += counter values 0-3 paddd %xmm1,%xmm12 - mov $10,%ecx - .Ldoubleround4: # x0 += x4, x12 = rotl32(x12 ^ x0, 16) movdqa 0x00(%rsp),%xmm0 @@ -493,7 +496,7 @@ ENTRY(chacha20_4block_xor_ssse3) psrld $25,%xmm4 por %xmm0,%xmm4 - dec %ecx + sub $2,%r8d jnz .Ldoubleround4 # x0[0-3] += s0[0] @@ -784,4 +787,4 @@ ENTRY(chacha20_4block_xor_ssse3) jmp .Ldone4 -ENDPROC(chacha20_4block_xor_ssse3) +ENDPROC(chacha_4block_xor_ssse3) diff --git a/arch/x86/crypto/chacha20_glue.c b/arch/x86/crypto/chacha_glue.c similarity index 51% rename from arch/x86/crypto/chacha20_glue.c rename to arch/x86/crypto/chacha_glue.c index 2bea425acb76..83cfb450b816 100644 --- a/arch/x86/crypto/chacha20_glue.c +++ b/arch/x86/crypto/chacha_glue.c @@ -1,5 +1,6 @@ /* - * ChaCha20 256-bit cipher algorithm, RFC7539, SIMD glue code + * x64 SIMD accelerated ChaCha and XChaCha stream ciphers, + * including ChaCha20 (RFC7539) * * Copyright (C) 2015 Martin Willi * @@ -17,120 +18,124 @@ #include #include -#define CHACHA20_STATE_ALIGN 16 +#define CHACHA_STATE_ALIGN 16 -asmlinkage void chacha20_block_xor_ssse3(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -asmlinkage void chacha20_4block_xor_ssse3(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -asmlinkage void hchacha20_block_ssse3(const u32 *state, u32 *out); +asmlinkage void chacha_block_xor_ssse3(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +asmlinkage void chacha_4block_xor_ssse3(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +asmlinkage void hchacha_block_ssse3(const u32 *state, u32 *out, int nrounds); #ifdef CONFIG_AS_AVX2 -asmlinkage void chacha20_2block_xor_avx2(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -asmlinkage void chacha20_4block_xor_avx2(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -asmlinkage void chacha20_8block_xor_avx2(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -static bool chacha20_use_avx2; +asmlinkage void chacha_2block_xor_avx2(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +asmlinkage void chacha_4block_xor_avx2(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +asmlinkage void chacha_8block_xor_avx2(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +static bool chacha_use_avx2; #ifdef CONFIG_AS_AVX512 -asmlinkage void chacha20_2block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -asmlinkage void chacha20_4block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -asmlinkage void chacha20_8block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src, - unsigned int len); -static bool chacha20_use_avx512vl; +asmlinkage void chacha_2block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +asmlinkage void chacha_4block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +asmlinkage void chacha_8block_xor_avx512vl(u32 *state, u8 *dst, const u8 *src, + unsigned int len, int nrounds); +static bool chacha_use_avx512vl; #endif #endif -static unsigned int chacha20_advance(unsigned int len, unsigned int maxblocks) +static unsigned int chacha_advance(unsigned int len, unsigned int maxblocks) { len = min(len, maxblocks * CHACHA_BLOCK_SIZE); return round_up(len, CHACHA_BLOCK_SIZE) / CHACHA_BLOCK_SIZE; } -static void chacha20_dosimd(u32 *state, u8 *dst, const u8 *src, - unsigned int bytes) +static void chacha_dosimd(u32 *state, u8 *dst, const u8 *src, + unsigned int bytes, int nrounds) { #ifdef CONFIG_AS_AVX2 #ifdef CONFIG_AS_AVX512 - if (chacha20_use_avx512vl) { + if (chacha_use_avx512vl) { while (bytes >= CHACHA_BLOCK_SIZE * 8) { - chacha20_8block_xor_avx512vl(state, dst, src, bytes); + chacha_8block_xor_avx512vl(state, dst, src, bytes, + nrounds); bytes -= CHACHA_BLOCK_SIZE * 8; src += CHACHA_BLOCK_SIZE * 8; dst += CHACHA_BLOCK_SIZE * 8; state[12] += 8; } if (bytes > CHACHA_BLOCK_SIZE * 4) { - chacha20_8block_xor_avx512vl(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 8); + chacha_8block_xor_avx512vl(state, dst, src, bytes, + nrounds); + state[12] += chacha_advance(bytes, 8); return; } if (bytes > CHACHA_BLOCK_SIZE * 2) { - chacha20_4block_xor_avx512vl(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 4); + chacha_4block_xor_avx512vl(state, dst, src, bytes, + nrounds); + state[12] += chacha_advance(bytes, 4); return; } if (bytes) { - chacha20_2block_xor_avx512vl(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 2); + chacha_2block_xor_avx512vl(state, dst, src, bytes, + nrounds); + state[12] += chacha_advance(bytes, 2); return; } } #endif - if (chacha20_use_avx2) { + if (chacha_use_avx2) { while (bytes >= CHACHA_BLOCK_SIZE * 8) { - chacha20_8block_xor_avx2(state, dst, src, bytes); + chacha_8block_xor_avx2(state, dst, src, bytes, nrounds); bytes -= CHACHA_BLOCK_SIZE * 8; src += CHACHA_BLOCK_SIZE * 8; dst += CHACHA_BLOCK_SIZE * 8; state[12] += 8; } if (bytes > CHACHA_BLOCK_SIZE * 4) { - chacha20_8block_xor_avx2(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 8); + chacha_8block_xor_avx2(state, dst, src, bytes, nrounds); + state[12] += chacha_advance(bytes, 8); return; } if (bytes > CHACHA_BLOCK_SIZE * 2) { - chacha20_4block_xor_avx2(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 4); + chacha_4block_xor_avx2(state, dst, src, bytes, nrounds); + state[12] += chacha_advance(bytes, 4); return; } if (bytes > CHACHA_BLOCK_SIZE) { - chacha20_2block_xor_avx2(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 2); + chacha_2block_xor_avx2(state, dst, src, bytes, nrounds); + state[12] += chacha_advance(bytes, 2); return; } } #endif while (bytes >= CHACHA_BLOCK_SIZE * 4) { - chacha20_4block_xor_ssse3(state, dst, src, bytes); + chacha_4block_xor_ssse3(state, dst, src, bytes, nrounds); bytes -= CHACHA_BLOCK_SIZE * 4; src += CHACHA_BLOCK_SIZE * 4; dst += CHACHA_BLOCK_SIZE * 4; state[12] += 4; } if (bytes > CHACHA_BLOCK_SIZE) { - chacha20_4block_xor_ssse3(state, dst, src, bytes); - state[12] += chacha20_advance(bytes, 4); + chacha_4block_xor_ssse3(state, dst, src, bytes, nrounds); + state[12] += chacha_advance(bytes, 4); return; } if (bytes) { - chacha20_block_xor_ssse3(state, dst, src, bytes); + chacha_block_xor_ssse3(state, dst, src, bytes, nrounds); state[12]++; } } -static int chacha20_simd_stream_xor(struct skcipher_request *req, - struct chacha_ctx *ctx, u8 *iv) +static int chacha_simd_stream_xor(struct skcipher_request *req, + struct chacha_ctx *ctx, u8 *iv) { u32 *state, state_buf[16 + 2] __aligned(8); struct skcipher_walk walk; int err; - BUILD_BUG_ON(CHACHA20_STATE_ALIGN != 16); - state = PTR_ALIGN(state_buf + 0, CHACHA20_STATE_ALIGN); + BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16); + state = PTR_ALIGN(state_buf + 0, CHACHA_STATE_ALIGN); err = skcipher_walk_virt(&walk, req, false); @@ -143,8 +148,8 @@ static int chacha20_simd_stream_xor(struct skcipher_request *req, nbytes = round_down(nbytes, walk.stride); kernel_fpu_begin(); - chacha20_dosimd(state, walk.dst.virt.addr, walk.src.virt.addr, - nbytes); + chacha_dosimd(state, walk.dst.virt.addr, walk.src.virt.addr, + nbytes, ctx->nrounds); kernel_fpu_end(); err = skcipher_walk_done(&walk, walk.nbytes - nbytes); @@ -153,7 +158,7 @@ static int chacha20_simd_stream_xor(struct skcipher_request *req, return err; } -static int chacha20_simd(struct skcipher_request *req) +static int chacha_simd(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); @@ -161,10 +166,10 @@ static int chacha20_simd(struct skcipher_request *req) if (req->cryptlen <= CHACHA_BLOCK_SIZE || !irq_fpu_usable()) return crypto_chacha_crypt(req); - return chacha20_simd_stream_xor(req, ctx, req->iv); + return chacha_simd_stream_xor(req, ctx, req->iv); } -static int xchacha20_simd(struct skcipher_request *req) +static int xchacha_simd(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); @@ -175,17 +180,18 @@ static int xchacha20_simd(struct skcipher_request *req) if (req->cryptlen <= CHACHA_BLOCK_SIZE || !irq_fpu_usable()) return crypto_xchacha_crypt(req); - BUILD_BUG_ON(CHACHA20_STATE_ALIGN != 16); - state = PTR_ALIGN(state_buf + 0, CHACHA20_STATE_ALIGN); + BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16); + state = PTR_ALIGN(state_buf + 0, CHACHA_STATE_ALIGN); crypto_chacha_init(state, ctx, req->iv); kernel_fpu_begin(); - hchacha20_block_ssse3(state, subctx.key); + hchacha_block_ssse3(state, subctx.key, ctx->nrounds); kernel_fpu_end(); + subctx.nrounds = ctx->nrounds; memcpy(&real_iv[0], req->iv + 24, 8); memcpy(&real_iv[8], req->iv + 16, 8); - return chacha20_simd_stream_xor(req, &subctx, real_iv); + return chacha_simd_stream_xor(req, &subctx, real_iv); } static struct skcipher_alg algs[] = { @@ -202,8 +208,8 @@ static struct skcipher_alg algs[] = { .ivsize = CHACHA_IV_SIZE, .chunksize = CHACHA_BLOCK_SIZE, .setkey = crypto_chacha20_setkey, - .encrypt = chacha20_simd, - .decrypt = chacha20_simd, + .encrypt = chacha_simd, + .decrypt = chacha_simd, }, { .base.cra_name = "xchacha20", .base.cra_driver_name = "xchacha20-simd", @@ -217,40 +223,40 @@ static struct skcipher_alg algs[] = { .ivsize = XCHACHA_IV_SIZE, .chunksize = CHACHA_BLOCK_SIZE, .setkey = crypto_chacha20_setkey, - .encrypt = xchacha20_simd, - .decrypt = xchacha20_simd, + .encrypt = xchacha_simd, + .decrypt = xchacha_simd, }, }; -static int __init chacha20_simd_mod_init(void) +static int __init chacha_simd_mod_init(void) { if (!boot_cpu_has(X86_FEATURE_SSSE3)) return -ENODEV; #ifdef CONFIG_AS_AVX2 - chacha20_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) && - boot_cpu_has(X86_FEATURE_AVX2) && - cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL); + chacha_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) && + boot_cpu_has(X86_FEATURE_AVX2) && + cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL); #ifdef CONFIG_AS_AVX512 - chacha20_use_avx512vl = chacha20_use_avx2 && - boot_cpu_has(X86_FEATURE_AVX512VL) && - boot_cpu_has(X86_FEATURE_AVX512BW); /* kmovq */ + chacha_use_avx512vl = chacha_use_avx2 && + boot_cpu_has(X86_FEATURE_AVX512VL) && + boot_cpu_has(X86_FEATURE_AVX512BW); /* kmovq */ #endif #endif return crypto_register_skciphers(algs, ARRAY_SIZE(algs)); } -static void __exit chacha20_simd_mod_fini(void) +static void __exit chacha_simd_mod_fini(void) { crypto_unregister_skciphers(algs, ARRAY_SIZE(algs)); } -module_init(chacha20_simd_mod_init); -module_exit(chacha20_simd_mod_fini); +module_init(chacha_simd_mod_init); +module_exit(chacha_simd_mod_fini); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Willi "); -MODULE_DESCRIPTION("chacha20 cipher algorithm, SIMD accelerated"); +MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (x64 SIMD accelerated)"); MODULE_ALIAS_CRYPTO("chacha20"); MODULE_ALIAS_CRYPTO("chacha20-simd"); MODULE_ALIAS_CRYPTO("xchacha20"); -- 2.20.0.rc0.387.gc7a69e6b6c-goog