Skip to content

Commit

Permalink
Tests for DIT functions and macro. Make armv8_get_dit() public."
Browse files Browse the repository at this point in the history
  • Loading branch information
nebeid committed Sep 13, 2024
1 parent dcd8f5d commit 37f707e
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 7 deletions.
1 change: 1 addition & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ if(BUILD_TESTING)
fipsmodule/sha/sha_test.cc
fipsmodule/sha/sha3_test.cc
fipsmodule/cpucap/cpu_arm_linux_test.cc
fipsmodule/cpucap/cpu_aarch64_dit_test.cc
fipsmodule/hkdf/hkdf_test.cc
fipsmodule/sshkdf/sshkdf_test.cc
hpke/hpke_test.cc
Expand Down
16 changes: 12 additions & 4 deletions crypto/fipsmodule/cpucap/cpu_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,14 @@ void handle_cpu_env(uint32_t *out, const char *in) {
#define DIT_REGISTER s3_3_c4_c2_5
DEFINE_STATIC_MUTEX(OPENSSL_armcap_P_lock)

static uint64_t armv8_get_dit(void) {
uint64_t val = 0;
__asm__ volatile("mrs %0, s3_3_c4_c2_5" : "=r" (val));
return (val >> 24) & 1;
uint64_t armv8_get_dit(void) {
if (CRYPTO_is_ARMv8_DIT_capable()) {
uint64_t val = 0;
__asm__ volatile("mrs %0, s3_3_c4_c2_5" : "=r" (val));
return (val >> 24) & 1;
} else {
return 0;
}
}

// See https://github.com/torvalds/linux/blob/53eaeb7fbe2702520125ae7d72742362c071a1f2/arch/arm64/include/asm/sysreg.h#L82
Expand Down Expand Up @@ -101,6 +105,10 @@ void armv8_enable_dit(void) {
CRYPTO_STATIC_MUTEX_unlock_write(OPENSSL_armcap_P_lock_bss_get());
}

int CRYPTO_is_ARMv8_DIT_capable_for_testing(void) {
return CRYPTO_is_ARMv8_DIT_capable();
}

#endif // !OPENSSL_WINDOWS

#endif // OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP
55 changes: 55 additions & 0 deletions crypto/fipsmodule/cpucap/cpu_aarch64_dit_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <openssl/crypto.h>
#include <gtest/gtest.h>

#include "internal.h"

#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP) && \
!defined(OPENSSL_WINDOWS)

#if defined(ENABLE_AUTO_SET_RESET_DIT)
static void NestedMacroInvocation(void) {
SET_DIT_AUTO_RESET;
uint64_t current_dit = armv8_get_dit();
EXPECT_EQ(current_dit, (uint64_t)1);
}
#endif // ENABLE_AUTO_SET_RESET_DIT

TEST(DITTest, SetReset) {
uint64_t one = CRYPTO_is_ARMv8_DIT_capable_for_testing()? (uint64_t)1 : (uint64_t)0;

uint64_t original_dit = 0, original_dit_2 = 0,
current_dit = 0;
original_dit = armv8_set_dit();
EXPECT_EQ(original_dit, (uint64_t)0);

// the case of a nested call of setting DIT
original_dit_2 = armv8_set_dit();
EXPECT_EQ(original_dit_2, one);

current_dit = armv8_get_dit();
EXPECT_EQ(current_dit, one);

armv8_restore_dit(&original_dit);
current_dit = armv8_get_dit();
EXPECT_EQ(current_dit, (uint64_t)0);

#if defined(ENABLE_AUTO_SET_RESET_DIT)
{ // invoke the macro within a scope
// to test that it restores the CPU DIT flag at the end
SET_DIT_AUTO_RESET;
current_dit = armv8_get_dit();
EXPECT_EQ(current_dit, one);
// Nested macro invocation will exit the scope leaving DIT = 1
NestedMacroInvocation();
current_dit = armv8_get_dit();
EXPECT_EQ(current_dit, one);
}
current_dit = armv8_get_dit();
EXPECT_EQ(current_dit, (uint64_t)0);
#endif // ENABLE_AUTO_SET_RESET_DIT
}

#endif // OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP && !OPENSSL_WINDOWS
6 changes: 5 additions & 1 deletion crypto/fipsmodule/cpucap/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,13 @@ OPENSSL_INLINE int CRYPTO_is_ARMv8_wide_multiplier_capable(void) {
}

OPENSSL_INLINE int CRYPTO_is_ARMv8_DIT_capable(void) {
return (OPENSSL_armcap_P & (ARMV8_DIT | ARMV8_DIT_ALLOWED)) == (ARMV8_DIT | ARMV8_DIT_ALLOWED);
return (OPENSSL_armcap_P & (ARMV8_DIT | ARMV8_DIT_ALLOWED)) ==
(ARMV8_DIT | ARMV8_DIT_ALLOWED);
}

// This function is used only for testing; hence, not inlined
OPENSSL_EXPORT int CRYPTO_is_ARMv8_DIT_capable_for_testing(void);

#endif // OPENSSL_ARM || OPENSSL_AARCH64

#if defined(OPENSSL_PPC64LE)
Expand Down
7 changes: 5 additions & 2 deletions include/openssl/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,14 @@ OPENSSL_EXPORT int CRYPTO_needs_hwcap2_workaround(void);
#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_WINDOWS)
// (TODO): See if we can detect the DIT capability in Windows environment

// armv8_set_dit sets the DIT flag to 1 and returns its original value
// armv8_get_dit gets the value of the DIT flag from the CPU.
OPENSSL_EXPORT uint64_t armv8_get_dit(void);

// armv8_set_dit sets the CPU DIT flag to 1 and returns its original value
// before it was called.
OPENSSL_EXPORT uint64_t armv8_set_dit(void);

// armv8_restore_dit takes as input a value to restore the DIT flag to.
// armv8_restore_dit takes as input a value to restore the CPU DIT flag to.
OPENSSL_EXPORT void armv8_restore_dit(volatile uint64_t *original_dit);

// armv8_disable_dit is a run-time disabler of the DIT capability.
Expand Down

0 comments on commit 37f707e

Please sign in to comment.