From nobody Sun Oct 15 19:31:18 2023 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4S7r2b3k4qz4xJY3; Sun, 15 Oct 2023 19:31:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4S7r2Z55Rdz4km9; Sun, 15 Oct 2023 19:31:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1697398278; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Nc7aOsMfbu3EjzfsI7ZbVs/E1hoYj/Saalf5oaG4C6E=; b=CTen2TnEdfAqNemKylLvD24RouxxX3xdeoQCEDUGCRTIe6AluVblICOrW41Eu2kTf9rfaQ Kc7/JsDMKeC4dcFrznlm7gfcad6m1GYH5kYDZfMHrmmB073ABWGkxRuc7amYtcoP7L8XVd int3bhCTunF/teKi9eh+ieAwGfMzvG83qUa4O0yJCfUzTCTreHv9Mth5hUYSlWC+R3/IVh 70q7q0ZNBKy7b0RBtYquxBg8aCDQWG6ro9OWqp3mpk6AUyrKERHIcIYuy3X8Uu6Cen5Ic+ XhTENqnm2MjplXwxz65r351sdi8C48IydpQyJ3djuTG4mxtBYUja/NCXVQG3Xw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1697398278; a=rsa-sha256; cv=none; b=kHidAvyzZQ0aP0M/xJC/sHsjXs7GWhsUfJMlGAxlq4oTPPdLMTbucBKOQNXtw1uFj5ea9D B5oCwaQeD0TDK02rqOmBhIgM3rZywspJdTpCgc7E+SNW5NLqh5NnATVmb8/aKkk2QmEYpS BGiVAxuXIzD5sUyXq+9OrQJTIk0yTFGHQRbEBP28RufRPtrch4Y26YDAHkzB5OvDSg95S6 05E3fpWBGWgrRYpT3ec91rjDZHNhuJUg4vhjPgv4tr1vjEgvKtrobCEHroEsMEMJChUX2n 4zml94eF1fVjefwniCOiRAYm48CxLl+Eiaq/iArzzUMGd72ka+XKNqLSD3g90A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1697398278; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Nc7aOsMfbu3EjzfsI7ZbVs/E1hoYj/Saalf5oaG4C6E=; b=ZHwhjpdFa1eeecDwzbSfT0qrd0I+ZX/YsWCRCNAKyaCd6aV6UeW7Tp5N0pKxDXgbWQVM5Y pSHs3ov+Ynf2NVLcLyWFztbey6Z1QQOuw0z6bQVkairO3EQ5rJsaySoat9r/9ZETxVdyeE /rak1O8LF0uuiR7LkujZxcUC2WsWcgHJLPTcfgXqiTiVfHw0XAWlFWmSFp1+uz71kVNIgV Q9o772X9PlUJzw04l0OZ0V2D48NtxQdf1fm/KQHd7tr9PblbouLW3/Em0b0tpRCMbwWy68 BBrUkoRdBmtusm1TmspJCkZuxPiHsfHZfeOmN5Fw9s4ZzAFazJUhhNjMjeVLjw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4S7r2Z48mZz1PWv; Sun, 15 Oct 2023 19:31:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 39FJVIBt088764; Sun, 15 Oct 2023 19:31:18 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 39FJVIpF088761; Sun, 15 Oct 2023 19:31:18 GMT (envelope-from git) Date: Sun, 15 Oct 2023 19:31:18 GMT Message-Id: <202310151931.39FJVIpF088761@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Robert Clausecker Subject: git: 76c2b331bcd9 - main - lib/libc/amd64/string: add timingsafe_bcmp(3) scalar, baseline implementations List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: fuz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 76c2b331bcd9f73c5c8c43a06e328fa0c7b8c39a Auto-Submitted: auto-generated The branch main has been updated by fuz: URL: https://cgit.FreeBSD.org/src/commit/?id=76c2b331bcd9f73c5c8c43a06e328fa0c7b8c39a commit 76c2b331bcd9f73c5c8c43a06e328fa0c7b8c39a Author: Robert Clausecker AuthorDate: 2023-08-30 15:37:26 +0000 Commit: Robert Clausecker CommitDate: 2023-10-15 19:19:04 +0000 lib/libc/amd64/string: add timingsafe_bcmp(3) scalar, baseline implementations Very straightforward and similar to memcmp(3). The code has been written to use only instructions specified as having data operand independent timing by Intel. Sponsored by: The FreeBSD Foundation Approved by: security (cperciva) Differential Revision: https://reviews.freebsd.org/D41673 --- lib/libc/amd64/string/Makefile.inc | 3 +- lib/libc/amd64/string/timingsafe_bcmp.S | 232 ++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+), 1 deletion(-) diff --git a/lib/libc/amd64/string/Makefile.inc b/lib/libc/amd64/string/Makefile.inc index 73973a6d69de..fc420de0450e 100644 --- a/lib/libc/amd64/string/Makefile.inc +++ b/lib/libc/amd64/string/Makefile.inc @@ -15,4 +15,5 @@ MDSRCS+= \ strcspn.S \ strlen.S \ strnlen.c \ - strspn.S + strspn.S \ + timingsafe_bcmp.S diff --git a/lib/libc/amd64/string/timingsafe_bcmp.S b/lib/libc/amd64/string/timingsafe_bcmp.S new file mode 100644 index 000000000000..c003da2ea9a7 --- /dev/null +++ b/lib/libc/amd64/string/timingsafe_bcmp.S @@ -0,0 +1,232 @@ +/*- + * Copyright (c) 2023 The FreeBSD Foundation + * + * This software was developed by Robert Clausecker + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE + */ + +#include + +#include "amd64_archlevel.h" + +#define ALIGN_TEXT .p2align 4,0x90 /* 16-byte alignment, nop filled */ + +ARCHFUNCS(timingsafe_bcmp) + ARCHFUNC(timingsafe_bcmp, scalar) + ARCHFUNC(timingsafe_bcmp, baseline) +ENDARCHFUNCS(timingsafe_bcmp) + +ARCHENTRY(timingsafe_bcmp, scalar) + cmp $16, %rdx # at least 17 bytes to process? + ja .Lgt16 + + cmp $8, %edx # at least 9 bytes to process? + ja .L0916 + + cmp $4, %edx # at least 5 bytes to process? + ja .L0508 + + cmp $2, %edx # at least 3 bytes to process? + ja .L0304 + + test %edx, %edx # buffer empty? + jnz .L0102 + + xor %eax, %eax # empty buffer always matches + ret + +.L0102: movzbl (%rdi), %eax # load 1--2 bytes from first buffer + movzbl -1(%rdi, %rdx, 1), %ecx + xor (%rsi), %al # xor in second buffer + xor -1(%rsi, %rdx, 1), %cl + or %ecx, %eax # mismatch in any of the two? + ret + +.L0304: movzwl (%rdi), %eax + movzwl -2(%rdi, %rdx, 1), %ecx + xor (%rsi), %ax + xor -2(%rsi, %rdx, 1), %cx + or %ecx, %eax + ret + +.L0508: mov (%rdi), %eax + mov -4(%rdi, %rdx, 1), %ecx + xor (%rsi), %eax + xor -4(%rsi, %rdx, 1), %ecx + or %ecx, %eax + ret + +.L0916: mov (%rdi), %rax + mov -8(%rdi, %rdx, 1), %rcx + xor (%rsi), %rax + xor -8(%rsi, %rdx, 1), %rcx + or %rcx, %rax + setnz %al # ensure EAX nonzero even if only + ret # high bits of RAX were set + + /* more than 16 bytes: process buffer in a loop */ +.Lgt16: mov (%rdi), %rax # process first 16 bytes + mov 8(%rdi), %r9 + mov $32, %ecx + xor (%rsi), %rax + xor 8(%rsi), %r9 + or %r9, %rax + + cmp %rdx, %rcx # enough left for a full iteration? + jae .Ltail + + /* main loop processing 16 bytes per iteration */ + ALIGN_TEXT +0: mov -16(%rdi, %rcx, 1), %r8 + mov -8(%rdi, %rcx, 1), %r9 + xor -16(%rsi, %rcx, 1), %r8 + xor -8(%rsi, %rcx, 1), %r9 + add $16, %rcx + or %r9, %r8 + or %r8, %rax + + cmp %rdx, %rcx + jb 0b + + /* process last 16 bytes */ +.Ltail: mov -16(%rdi, %rdx, 1), %r8 + mov -8(%rdi, %rdx, 1), %r9 + xor -16(%rsi, %rdx, 1), %r8 + xor -8(%rsi, %rdx, 1), %r9 + or %r9, %r8 + or %r8, %rax + setnz %al + ret +ARCHEND(timingsafe_bcmp, scalar) + +ARCHENTRY(timingsafe_bcmp, baseline) + cmp $32, %rdx # at least 33 bytes to process? + ja .Lgt32b + + cmp $16, %edx # at least 17 bytes to process? + ja .L1732b + + cmp $8, %edx # at least 9 bytes to process? + ja .L0916b + + cmp $4, %edx # at least 5 bytes to process? + ja .L0508b + + cmp $2, %edx # at least 3 bytes to process? + ja .L0304b + + test %edx, %edx # buffer empty? + jnz .L0102b + + xor %eax, %eax # empty buffer always matches + ret + +.L0102b: + movzbl (%rdi), %eax # load 1--2 bytes from first buffer + movzbl -1(%rdi, %rdx, 1), %ecx + xor (%rsi), %al # xor in second buffer + xor -1(%rsi, %rdx, 1), %cl + or %ecx, %eax # mismatch in any of the two? + ret + +.L0304b: + movzwl (%rdi), %eax + movzwl -2(%rdi, %rdx, 1), %ecx + xor (%rsi), %ax + xor -2(%rsi, %rdx, 1), %cx + or %ecx, %eax + ret + +.L0508b: + mov (%rdi), %eax + mov -4(%rdi, %rdx, 1), %ecx + xor (%rsi), %eax + xor -4(%rsi, %rdx, 1), %ecx + or %ecx, %eax + ret + +.L0916b: + mov (%rdi), %rax + mov -8(%rdi, %rdx, 1), %rcx + xor (%rsi), %rax + xor -8(%rsi, %rdx, 1), %rcx + or %rcx, %rax + setnz %al # ensure EAX nonzero even if only + ret # high bits of RAX were set + +.L1732b: + movdqu (%rdi), %xmm0 + movdqu (%rsi), %xmm2 + movdqu -16(%rdi, %rdx, 1), %xmm1 + movdqu -16(%rsi, %rdx, 1), %xmm3 + pcmpeqb %xmm2, %xmm0 + pcmpeqb %xmm3, %xmm1 + pand %xmm1, %xmm0 + pmovmskb %xmm0, %eax # 1 where equal + xor $0xffff, %eax # 1 where not equal + ret + + /* more than 32 bytes: process buffer in a loop */ +.Lgt32b: + movdqu (%rdi), %xmm4 + movdqu (%rsi), %xmm2 + movdqu 16(%rdi), %xmm1 + movdqu 16(%rsi), %xmm3 + mov $64, %ecx + pcmpeqb %xmm2, %xmm4 + pcmpeqb %xmm3, %xmm1 + pand %xmm1, %xmm4 + cmp %rdx, %rcx # enough left for a full iteration? + jae .Ltailb + + /* main loop processing 32 bytes per iteration */ + ALIGN_TEXT +0: movdqu -32(%rdi, %rcx, 1), %xmm0 + movdqu -32(%rsi, %rcx, 1), %xmm2 + movdqu -16(%rdi, %rcx, 1), %xmm1 + movdqu -16(%rsi, %rcx, 1), %xmm3 + add $32, %rcx + pcmpeqb %xmm2, %xmm0 + pcmpeqb %xmm3, %xmm1 + pand %xmm1, %xmm0 + pand %xmm0, %xmm4 + cmp %rdx, %rcx + jb 0b + + /* process last 32 bytes */ +.Ltailb: + movdqu -32(%rdi, %rdx, 1), %xmm0 + movdqu -32(%rsi, %rdx, 1), %xmm2 + movdqu -16(%rdi, %rdx, 1), %xmm1 + movdqu -16(%rsi, %rdx, 1), %xmm3 + pcmpeqb %xmm2, %xmm0 + pcmpeqb %xmm3, %xmm1 + pand %xmm1, %xmm0 + pand %xmm4, %xmm0 + pmovmskb %xmm0, %eax + xor $0xffff, %eax + ret +ARCHEND(timingsafe_bcmp, baseline) + + .section .note.GNU-stack,"",%progbits