Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling DIT flag in AArch64. #1687

Merged
merged 16 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ option(ENABLE_DILITHIUM "Enable Dilithium signatures in the EVP API" OFF)
option(DISABLE_PERL "Disable Perl for AWS-LC" OFF)
option(DISABLE_GO "Disable Go for AWS-LC" OFF)
option(ENABLE_FIPS_ENTROPY_CPU_JITTER "Enable FIPS entropy source: CPU Jitter" OFF)
option(ENABLE_DATA_INDEPENDENT_TIMING "Enable Data-Independent Timing (DIT) flag" OFF)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a bit more specific?

Suggested change
option(ENABLE_DATA_INDEPENDENT_TIMING "Enable Data-Independent Timing (DIT) flag" OFF)
option(ENABLE_DATA_INDEPENDENT_TIMING_AARCH64 "Enable Data-Independent Timing (DIT) flag" OFF)

include(cmake/go.cmake)

enable_language(C)
Expand Down Expand Up @@ -801,6 +802,11 @@ else()
set(ARCH "generic")
endif()

#if(ENABLE_DATA_INDEPENDENT_TIMING AND ARCH EQUAL "aarch64")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. Thanks.

if(ENABLE_DATA_INDEPENDENT_TIMING)
add_definitions(-DMAKE_DIT_AVAILABLE)
endif()

if(USE_CUSTOM_LIBCXX)
if(NOT CLANG)
message(FATAL_ERROR "USE_CUSTOM_LIBCXX only supported with Clang")
Expand Down
8 changes: 7 additions & 1 deletion crypto/curve25519/curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "internal.h"
#include "../internal.h"
#include "../fipsmodule/cpucap/internal.h"

// X25519 [1] and Ed25519 [2] is an ECDHE protocol and signature scheme,
// respectively. This file contains an implementation of both using two
Expand Down Expand Up @@ -91,7 +92,7 @@ void ED25519_keypair_from_seed(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],
#endif

// Encoded public key is a suffix in the private key. Avoids having to
// generate the public key from the private key when signing.
// generate the public key from the private key when signing.
OPENSSL_STATIC_ASSERT(ED25519_PRIVATE_KEY_LEN == (ED25519_SEED_LEN + ED25519_PUBLIC_KEY_LEN), ed25519_parameter_length_mismatch)
OPENSSL_memcpy(out_private_key, seed, ED25519_SEED_LEN);
OPENSSL_memcpy(out_private_key + ED25519_SEED_LEN, out_public_key,
Expand All @@ -100,6 +101,7 @@ void ED25519_keypair_from_seed(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],

void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],
uint8_t out_private_key[ED25519_PRIVATE_KEY_LEN]) {
ENABLE_DIT_AUTO_DISABLE;

// Ed25519 key generation: rfc8032 5.1.5
// Private key is 32 octets of random data.
Expand Down Expand Up @@ -127,6 +129,7 @@ int ED25519_sign(uint8_t out_sig[ED25519_SIGNATURE_LEN],
// seed = private_key[0:31]
// A = private_key[32:61] (per 5.1.5.4)
// Compute az = SHA512(seed).
ENABLE_DIT_AUTO_DISABLE;
uint8_t az[SHA512_DIGEST_LENGTH];
SHA512(private_key, ED25519_PRIVATE_KEY_SEED_LEN, az);
// s = az[0:31]
Expand Down Expand Up @@ -215,6 +218,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
void X25519_public_from_private(
uint8_t out_public_value[X25519_PUBLIC_VALUE_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN]) {
ENABLE_DIT_AUTO_DISABLE;

#if defined(CURVE25519_S2N_BIGNUM_CAPABLE)
x25519_public_from_private_s2n_bignum(out_public_value, private_key);
Expand All @@ -225,6 +229,7 @@ void X25519_public_from_private(

void X25519_keypair(uint8_t out_public_value[X25519_PUBLIC_VALUE_LEN],
uint8_t out_private_key[X25519_PRIVATE_KEY_LEN]) {
ENABLE_DIT_AUTO_DISABLE;

RAND_bytes(out_private_key, X25519_PRIVATE_KEY_LEN);

Expand Down Expand Up @@ -252,6 +257,7 @@ int X25519(uint8_t out_shared_key[X25519_SHARED_KEY_LEN],
const uint8_t private_key[X25519_PRIVATE_KEY_LEN],
const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN]) {

ENABLE_DIT_AUTO_DISABLE;
static const uint8_t kZeros[X25519_SHARED_KEY_LEN] = {0};

#if defined(CURVE25519_S2N_BIGNUM_CAPABLE)
Expand Down
4 changes: 4 additions & 0 deletions crypto/fipsmodule/aes/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
// code, above, is incompatible with the |aes_hw_*| functions.

void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
ENABLE_DIT_AUTO_DISABLE;
if (hwaes_capable()) {
aes_hw_encrypt(in, out, key);
} else if (vpaes_capable()) {
Expand All @@ -70,6 +71,7 @@ void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
}

void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
ENABLE_DIT_AUTO_DISABLE;
if (hwaes_capable()) {
aes_hw_decrypt(in, out, key);
} else if (vpaes_capable()) {
Expand All @@ -80,6 +82,7 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
}

int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
ENABLE_DIT_AUTO_DISABLE;
if (bits != 128 && bits != 192 && bits != 256) {
return -2;
}
Expand All @@ -93,6 +96,7 @@ int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
}

int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
ENABLE_DIT_AUTO_DISABLE;
if (bits != 128 && bits != 192 && bits != 256) {
return -2;
}
Expand Down
5 changes: 5 additions & 0 deletions crypto/fipsmodule/cipher/aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
ENABLE_DIT_AUTO_DISABLE;
if (key_len != aead->key_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_KEY_SIZE);
ctx->aead = NULL;
Expand Down Expand Up @@ -124,6 +125,7 @@ int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
ENABLE_DIT_AUTO_DISABLE;
if (in_len + ctx->aead->overhead < in_len /* overflow */) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
goto error;
Expand Down Expand Up @@ -162,6 +164,7 @@ int EVP_AEAD_CTX_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad,
size_t ad_len) {
ENABLE_DIT_AUTO_DISABLE; //check that it was preserved
// |in| and |out| may alias exactly, |out_tag| may not alias.
if (!check_alias(in, in_len, out, in_len) ||
buffers_alias(out, in_len, out_tag, max_out_tag_len) ||
Expand Down Expand Up @@ -194,6 +197,7 @@ int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len) {
ENABLE_DIT_AUTO_DISABLE;
if (!check_alias(in, in_len, out, max_out_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
goto error;
Expand Down Expand Up @@ -241,6 +245,7 @@ int EVP_AEAD_CTX_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *in, size_t in_len,
const uint8_t *in_tag, size_t in_tag_len,
const uint8_t *ad, size_t ad_len) {
ENABLE_DIT_AUTO_DISABLE;
if (!check_alias(in, in_len, out, in_len)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
goto error;
Expand Down
9 changes: 8 additions & 1 deletion crypto/fipsmodule/cipher/cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) {
return 0;
}
GUARD_PTR(out);
ENABLE_DIT_AUTO_DISABLE;

EVP_CIPHER_CTX_cleanup(out);
OPENSSL_memcpy(out, in, sizeof(EVP_CIPHER_CTX));
Expand Down Expand Up @@ -146,6 +147,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
ENGINE *engine, const uint8_t *key, const uint8_t *iv,
int enc) {
GUARD_PTR(ctx);
ENABLE_DIT_AUTO_DISABLE;
if (enc == -1) {
enc = ctx->encrypt;
} else {
Expand Down Expand Up @@ -263,6 +265,7 @@ static int block_remainder(const EVP_CIPHER_CTX *ctx, int len) {
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, int in_len) {
GUARD_PTR(ctx);
ENABLE_DIT_AUTO_DISABLE;
if (ctx->poisoned) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
Expand Down Expand Up @@ -357,6 +360,7 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
int n;
unsigned int i, b, bl;
GUARD_PTR(ctx);
ENABLE_DIT_AUTO_DISABLE;

if (ctx->poisoned) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Expand Down Expand Up @@ -409,6 +413,7 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, int in_len) {
GUARD_PTR(ctx);
ENABLE_DIT_AUTO_DISABLE;
if (ctx->poisoned) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
Expand Down Expand Up @@ -478,11 +483,12 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) {
unsigned int b;
*out_len = 0;
GUARD_PTR(ctx);
ENABLE_DIT_AUTO_DISABLE;

// |ctx->cipher->cipher| calls the static aes encryption function way under
// the hood instead of |EVP_Cipher|, so the service indicator does not need
// locking here.

if (ctx->poisoned) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
Expand Down Expand Up @@ -548,6 +554,7 @@ int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t in_len) {
GUARD_PTR(ctx);
GUARD_PTR(ctx->cipher);
ENABLE_DIT_AUTO_DISABLE;
const int ret = ctx->cipher->cipher(ctx, out, in, in_len);

// |EVP_CIPH_FLAG_CUSTOM_CIPHER| never sets the FIPS indicator via
Expand Down
40 changes: 40 additions & 0 deletions crypto/fipsmodule/cpucap/cpu_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,44 @@ void handle_cpu_env(uint32_t *out, const char *in) {
}
}

#if defined(MAKE_DIT_AVAILABLE) && !defined(OPENSSL_WINDOWS)
// "DIT" is not recognised as a register name by clang-10 (at least)
// Register's encoded name is from e.g.
// https://github.com/ashwio/arm64-sysreg-lib/blob/d421e249a026f6f14653cb6f9c4edd8c5d898595/include/sysreg/dit.h#L286
#define DIT_REGISTER s3_3_c4_c2_5

uint64_t armv8_get_dit(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this function can be static since it's not used outside this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

uint64_t val = 0;
if (CRYPTO_is_ARMv8_DIT_capable()) {
__asm__ volatile("mrs %0, s3_3_c4_c2_5" : "=r" (val));
}
return val >> 24;
}

// See https://github.com/torvalds/linux/blob/53eaeb7fbe2702520125ae7d72742362c071a1f2/arch/arm64/include/asm/sysreg.h#L82
// As per Arm ARM for v8-A, Section "C.5.1.3 op0 == 0b00, architectural hints,
// barriers and CLREX, and PSTATE access", ARM DDI 0487 J.a, system instructions
// for accessing PSTATE fields have the following encoding
// and C5.2.4 DIT, Data Independent Timing:
// Op0 = 0, CRn = 4
// Op1 (3 for DIT) , Op2 (5 for DIT) encodes the PSTATE field modified and defines the constraints.
// CRm = Imm4 (#0 or #1 below)
// Rt = 0x1f
uint64_t armv8_enable_dit(void) {
uint64_t original_dit = armv8_get_dit();
if (CRYPTO_is_ARMv8_DIT_capable() && original_dit != 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have to check original_dit != 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. Thanks.

// Encoding of "msr dit, #1"
__asm__ volatile(".long 0xd503415f");
}
return original_dit;
}

void armv8_restore_dit(volatile uint64_t *original_dit) {
if (CRYPTO_is_ARMv8_DIT_capable() && *original_dit != 1) {
// Encoding of "msr dit, #0"
__asm__ volatile(".long 0xd503405f");
}
}
#endif // MAKE_DIT_AVAILABLE && !OPENSSL_WINDOWS

#endif // OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP
6 changes: 6 additions & 0 deletions crypto/fipsmodule/cpucap/cpu_aarch64_apple.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ void OPENSSL_cpuid_setup(void) {
OPENSSL_armcap_P |= ARMV8_APPLE_M1;
}

#if defined(MAKE_DIT_AVAILABLE)
if (has_hw_feature("hw.optional.arm.FEAT_DIT")) {
OPENSSL_armcap_P |= ARMV8_DIT;
}
#endif // MAKE_DIT_AVAILABLE

// OPENSSL_armcap is a 32-bit, unsigned value which may start with "0x" to
// indicate a hex value. Prior to the 32-bit value, a '~' or '|' may be given.
//
Expand Down
8 changes: 8 additions & 0 deletions crypto/fipsmodule/cpucap/cpu_aarch64_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ void OPENSSL_cpuid_setup(void) {
}
}

#if defined(MAKE_DIT_AVAILABLE)
static const unsigned long kDIT = 1 << 24;
// Before enabling/disabling the DIT flag, check it's available in HWCAP
if (hwcap & kDIT) {
OPENSSL_armcap_P |= ARMV8_DIT;
}
#endif // MAKE_DIT_AVAILABLE

// OPENSSL_armcap is a 32-bit, unsigned value which may start with "0x" to
// indicate a hex value. Prior to the 32-bit value, a '~' or '|' may be given.
//
Expand Down
4 changes: 4 additions & 0 deletions crypto/fipsmodule/cpucap/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ OPENSSL_INLINE int CRYPTO_is_ARMv8_wide_multiplier_capable(void) {
(OPENSSL_armcap_P & ARMV8_APPLE_M1) != 0;
}

OPENSSL_INLINE int CRYPTO_is_ARMv8_DIT_capable(void) {
return (OPENSSL_armcap_P & ARMV8_DIT) != 0;
}

#endif // OPENSSL_ARM || OPENSSL_AARCH64

#if defined(OPENSSL_PPC64LE)
Expand Down
Loading
Loading