Hello,

The attached is my attempt to enable PAC/BTI[1] support for AArch64.  As
the Nettle assembly files only define leaf functions (i.e., no
subroutine calls with LR/SP save/restore), PAC is not applicable and
thus only BTI is enabled for now.

To test, I used the mock[2] environment with the fedora-40-aarch64
configuration:

  $ mock -r fedora-40-aarch64 --init
  <mock-chroot> sh-5.2# ./.bootstrap 
  <mock-chroot> sh-5.2# ./configure --disable-documentation 
CFLAGS="-mbranch-protection=standard"
  <mock-chroot> sh-5.2# make -j$(nproc)
  <mock-chroot> sh-5.2# readelf -n libnettle.so 

  Displaying notes found in: .note.gnu.property
    Owner                Data size      Description
    GNU                  0x00000010     NT_GNU_PROPERTY_TYPE_0
        Properties: AArch64 feature: BTI, PAC
  ...

Regards,

Footnotes:
[1]  https://wiki.debian.org/ToolChain/PACBTI

[2]  https://fedoraproject.org/wiki/Using_Mock_to_test_package_builds

-- 
Daiki Ueno
>From bad675b345897fc248e0dc7261c3dd9f51b5c0d2 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <[email protected]>
Date: Mon, 15 Jul 2024 11:22:09 +0900
Subject: [PATCH] build: Support PACBTI in AArch64 assembly

This adds support for the branch protection mechanism provided in
64-bit Arm architecture, namely:
- Armv8.3-A Pointer Authentication (PAC)
- Armv8.5-A Branch Target Identification (BTI)

Note that PAC is currently unused in the assembly files as they only
define leaf functions wrapped by the corresponding C functions, which
will be instrumented by the compiler.

Signed-off-by: Daiki Ueno <[email protected]>
---
 asm.m4       |   2 +-
 config.m4.in |   7 +++
 configure.ac | 121 ++++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 117 insertions(+), 13 deletions(-)

diff --git a/asm.m4 b/asm.m4
index 2bb1068c..f9751608 100644
--- a/asm.m4
+++ b/asm.m4
@@ -30,7 +30,7 @@ define(`GMP_NUMB_BITS',`')dnl
 define(`PROLOGUE',
 `.globl C_NAME($1)
 DECLARE_FUNC(C_NAME($1))
-C_NAME($1): ASM_X86_ENDBR')
+C_NAME($1): ASM_X86_ENDBR`'ASM_ARM64_BTI_C')
 
 define(`EPILOGUE',
 `ifelse(ELF_STYLE,yes,
diff --git a/config.m4.in b/config.m4.in
index b98a5817..e96fa6cb 100644
--- a/config.m4.in
+++ b/config.m4.in
@@ -12,7 +12,14 @@ define(`WORDS_BIGENDIAN', `@ASM_WORDS_BIGENDIAN@')dnl
 define(`ASM_X86_ENDBR',`@ASM_X86_ENDBR@')dnl
 define(`ASM_X86_MARK_CET_ALIGN',`@ASM_X86_MARK_CET_ALIGN@')dnl
 define(`ASM_PPC_WANT_R_REGISTERS',`@ASM_PPC_WANT_R_REGISTERS@')dnl
+define(`ASM_ARM64_BTI_C',`@ASM_ARM64_BTI_C@')dnl
+define(`ASM_ARM64_SIGN_LR',`@ASM_ARM64_SIGN_LR@')dnl
+define(`ASM_ARM64_AUTH_LR',`@ASM_ARM64_AUTH_LR@')dnl
+define(`ASM_ARM64_PROPERTY_BTI',`@ASM_ARM64_PROPERTY_BTI@')dnl
+define(`ASM_ARM64_PROPERTY_PAC',`@ASM_ARM64_PROPERTY_PAC@')dnl
+define(`ASM_ARM64_MARK_PACBTI',`@ASM_ARM64_MARK_PACBTI@')dnl
 divert(1)
 @ASM_X86_MARK_CET@
+@ASM_ARM64_MARK_PACBTI@
 @ASM_MARK_NOEXEC_STACK@
 divert
diff --git a/configure.ac b/configure.ac
index 7ae99f25..99c26085 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1012,6 +1012,16 @@ EOF
   ASM_ALIGN_LOG="$nettle_cv_asm_align_log"
 fi
 
+AC_CACHE_CHECK([if .note.gnu.property section is needed],
+  [nettle_cv_asm_gnu_property],
+  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if !defined __ELF__
+#error GNU property is not needed
+#endif
+]], [[]])],
+  [nettle_cv_asm_gnu_property=yes],
+  [nettle_cv_asm_gnu_property=no])])
+
 dnl  Define
 dnl  1. ASM_X86_ENDBR for endbr32/endbr64.
 dnl  2. ASM_X86_MARK_CET to add a .note.gnu.property section to mark
@@ -1041,19 +1051,8 @@ if test "$nettle_cv_asm_x86_intel_cet" = yes; then
     ASM_X86_MARK_CET_ALIGN=2
     ;;
   esac
-  AC_CACHE_CHECK([if .note.gnu.property section is needed],
-    [nettle_cv_asm_x86_gnu_property],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#if !defined __ELF__ || !defined __CET__
-#error GNU property is not needed
-#endif
-    ]], [[]])],
-  [nettle_cv_asm_x86_gnu_property=yes],
-  [nettle_cv_asm_x86_gnu_property=no])])
-else
-  nettle_cv_asm_x86_gnu_property=no
 fi
-if test "$nettle_cv_asm_x86_gnu_property" = yes; then
+if test "$nettle_cv_asm_gnu_property" = yes && test "$nettle_cv_asm_x86_intel_cet" = yes; then
   ASM_X86_MARK_CET='
 	.pushsection ".note.gnu.property", "a"
 	.p2align ASM_X86_MARK_CET_ALIGN
@@ -1074,6 +1073,98 @@ if test "$nettle_cv_asm_x86_gnu_property" = yes; then
 	.popsection'
 fi
 
+dnl  Define
+dnl  1. ASM_ARM64_BTI_C for BTI.
+dnl  2. ASM_ARM64_{SIGN,AUTH}_LR for PAC, currently unused.
+dnl  3. ASM_ARM64_MARK_PACBTI to add a .note.gnu.property section to mark
+dnl  support for:
+dnl    - Armv8.3-A Pointer Authentication and
+dnl    - Armv8.5-A Branch Target Identification
+dnl  if needed.
+AC_CACHE_CHECK([if Armv8.5-A BTI is enabled],
+  [nettle_cv_asm_arm64_bti],
+  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if !(defined __ARM_FEATURE_BTI_DEFAULT && __ARM_FEATURE_BTI_DEFAULT == 1)
+#error Armv8.5-A BTI is not enabled
+#endif
+  ]], [[]])],
+  [nettle_cv_asm_arm64_bti=yes],
+  [nettle_cv_asm_arm64_bti=no])])
+if test "$nettle_cv_asm_arm64_bti" = yes; then
+  ASM_ARM64_PROPERTY_BTI=1
+  ASM_ARM64_BTI_C="bti c"
+else
+  ASM_ARM64_PROPERTY_BTI=0
+fi
+AC_CACHE_CHECK([if Armv8.3-A PAC is enabled],
+  [nettle_cv_asm_arm64_pac],
+  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#ifndef __ARM_FEATURE_PAC_DEFAULT
+#error Armv8.3-A PAC is not enabled
+#endif
+  ]], [[]])],
+  [nettle_cv_asm_arm64_pac=yes],
+  [nettle_cv_asm_arm64_pac=no])])
+if test "$nettle_cv_asm_arm64_pac" = yes; then
+  ASM_ARM64_PROPERTY_PAC=2
+  AC_MSG_CHECKING([for key used for Armv8.3-A PAC])
+  nettle_cv_asm_arm64_pac_key=unknown
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if __ARM_FEATURE_PAC_DEFAULT & 1
+#error Armv8.3-A PAC uses A key
+#endif
+    ]], [[]])],
+    [],
+    [nettle_cv_asm_arm64_pac_key=a])
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#if __ARM_FEATURE_PAC_DEFAULT & 2
+#error Armv8.3-A PAC uses B key
+#endif
+    ]], [[]])],
+    [],
+    [nettle_cv_asm_arm64_pac_key=b])
+  AC_MSG_RESULT([$nettle_cv_asm_arm64_pac_key])
+  AS_CASE([$nettle_cv_asm_arm64_pac_key],
+	  [a], [ASM_ARM64_SIGN_LR=paciasp
+		ASM_ARM64_AUTH_LR=autiasp],
+	  [b], [ASM_ARM64_SIGN_LR=pacibsp
+		ASM_ARM64_AUTH_LR=autibsp],
+	  [nettle_cv_asm_arm64_pac=no])
+else
+  ASM_ARM64_PROPERTY_PAC=0
+  if test "$nettle_cv_asm_arm64_bti" = yes; then
+    ASM_ARM64_SIGN_LR="$ASM_ARM64_BTI_C"
+  else
+    ASM_ARM64_SIGN_LR=
+  fi
+  ASM_ARM64_AUTH_LR=
+fi
+
+nettle_cv_asm_arm64_pacbti=no
+if test "$nettle_cv_asm_arm64_bti" = yes || test "$nettle_cv_asm_arm64_pac" = yes; then
+  nettle_cv_asm_arm64_pacbti=yes
+fi
+
+if test "$nettle_cv_asm_gnu_property" = yes && test "$nettle_cv_asm_arm64_pacbti" = yes; then
+  ASM_ARM64_MARK_PACBTI='
+	.pushsection ".note.gnu.property", "a"
+	.p2align 3
+	.long 1f - 0f
+	.long 4f - 1f
+	.long 5
+0:
+	.asciz "GNU"
+1:
+	.long 0xc0000000
+	.long 3f - 2f
+2:
+	.long (ASM_ARM64_PROPERTY_BTI|ASM_ARM64_PROPERTY_PAC)
+3:
+	.p2align 3
+4:
+	.popsection'
+fi
+
 AC_SUBST(ASM_SYMBOL_PREFIX)
 AC_SUBST(ASM_ELF_STYLE)
 AC_SUBST(ASM_COFF_STYLE)
@@ -1088,6 +1179,12 @@ AC_SUBST(EMULATOR)
 AC_SUBST(ASM_X86_ENDBR)
 AC_SUBST(ASM_X86_MARK_CET)
 AC_SUBST(ASM_X86_MARK_CET_ALIGN)
+AC_SUBST(ASM_ARM64_BTI_C)
+AC_SUBST(ASM_ARM64_SIGN_LR)
+AC_SUBST(ASM_ARM64_AUTH_LR)
+AC_SUBST(ASM_ARM64_PROPERTY_PAC)
+AC_SUBST(ASM_ARM64_PROPERTY_BTI)
+AC_SUBST(ASM_ARM64_MARK_PACBTI)
 
 AC_SUBST(LIBNETTLE_MAJOR)
 AC_SUBST(LIBNETTLE_MINOR)
-- 
2.45.2

_______________________________________________
nettle-bugs mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to