This commit is contained in:
Paul Elliott 2025-12-24 11:02:24 +03:00 committed by GitHub
commit 5740236ed0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 173 additions and 3 deletions

View File

@ -218,6 +218,14 @@ _armv8_rng_probe:
mrs x0, s3_3_c2_c4_1 // rndrrs
ret
.size _armv8_rng_probe,.-_armv8_rng_probe
.globl _armv8_dit_probe
.type _armv8_dit_probe,%function
_armv8_dit_probe:
AARCH64_VALID_CALL_TARGET
mrs x0, s3_3_c4_c2_5 // dit
ret
.size _armv8_dit_probe,.-_armv8_dit_probe
___
sub gen_random {

View File

@ -83,6 +83,7 @@ extern unsigned int OPENSSL_armv8_rsa_neonized;
#define ARMV8_HAVE_SHA3_AND_WORTH_USING (1 << 15)
#define ARMV8_UNROLL12_EOR3 (1 << 16)
#define ARMV9_SVE2_POLY1305 (1 << 17)
#define ARMV8_DIT (1 << 18)
/*
* MIDR_EL1 system register

View File

@ -142,6 +142,7 @@ static unsigned long getauxval(unsigned long key)
#define OSSL_HWCAP_CE_SM4 (1 << 19)
#define OSSL_HWCAP_CE_SHA512 (1 << 21)
#define OSSL_HWCAP_SVE (1 << 22)
#define OSSL_HWCAP_DIT (1 << 24)
/* AT_HWCAP2 */
#define OSSL_HWCAP2 26
#define OSSL_HWCAP2_SVE2 (1 << 1)
@ -217,6 +218,7 @@ void _armv8_eor3_probe(void);
void _armv8_sve_probe(void);
void _armv8_sve2_probe(void);
void _armv8_rng_probe(void);
void _armv8_dit_probe(void);
#endif
#endif /* !__APPLE__ && !OSSL_IMPLEMENT_GETAUXVAL */
@ -294,6 +296,7 @@ void OPENSSL_cpuid_setup(void)
/* More recent extensions are indicated by sysctls */
OPENSSL_armcap_P |= sysctl_query("hw.optional.armv8_2_sha512", ARMV8_SHA512);
OPENSSL_armcap_P |= sysctl_query("hw.optional.armv8_2_sha3", ARMV8_SHA3);
OPENSSL_armcap_P |= sysctl_query("hw.optional.arm.FEAT_DIT", ARMV8_DIT);
if (OPENSSL_armcap_P & ARMV8_SHA3) {
char uarch[64];
@ -346,6 +349,9 @@ void OPENSSL_cpuid_setup(void)
if (getauxval(OSSL_HWCAP) & OSSL_HWCAP_SVE)
OPENSSL_armcap_P |= ARMV8_SVE;
if (getauxval(OSSL_HWCAP) & OSSL_HWCAP_DIT)
OPENSSL_armcap_P |= ARMV8_DIT;
if (getauxval(OSSL_HWCAP2) & OSSL_HWCAP2_SVE2)
OPENSSL_armcap_P |= ARMV9_SVE2;
@ -394,6 +400,7 @@ void OPENSSL_cpuid_setup(void)
OPENSSL_armcap_P |= arm_probe_for(_armv8_sve_probe, ARMV8_SVE);
OPENSSL_armcap_P |= arm_probe_for(_armv8_sve2_probe, ARMV9_SVE2);
OPENSSL_armcap_P |= arm_probe_for(_armv8_rng_probe, ARMV8_RNG);
OPENSSL_armcap_P |= arm_probe_for(_armv8_dit_probe, ARMV8_DIT);
#endif
/*
@ -434,3 +441,66 @@ void OPENSSL_cpuid_setup(void)
#endif
}
#endif /* _WIN32, __ARM_MAX_ARCH__ >= 7 */
#if defined(__aarch64__) && !defined(OSSL_NO_DIT)
/* For PSTATE.DIT */
/* Gets the current value of the DIT flag as 0 or 1 */
/* MUST NOT be called unless OPENSSL_armcap_P has ARMV8_DIT set */
static ossl_inline uint64_t ossl_get_dit(void)
{
uint64_t val = 0;
/* In case we're used with an older assembler that doesn't understand DIT */
__asm__ volatile("mrs %0, s3_3_c4_c2_5" : "=r"(val));
return (val >> 24) & 1;
}
/* Sets DIT on: MUST NOT be called unless OPENSSL_armcap_P has ARMV8_DIT set */
static ossl_inline void ossl_set_dit_on(void)
{
__asm__ volatile(".inst 0xD503415F"); /* msr dit, #1 */
}
/* Sets DIT off: MUST NOT be called unless OPENSSL_armcap_P has ARMV8_DIT set */
static ossl_inline void ossl_set_dit_off(void)
{
__asm__ volatile(".inst 0xD503405F"); /* msr dit, #0 */
}
/*
* Sets DIT on and returns original value (0 or value given, for off and on respectively)
* (we allow the caller to supply the "on" value returned, so that bit flags
* can be supported more easily).
*/
int OPENSSL_ensure_dit_on(int value_for_on)
{
if (!(OPENSSL_armcap_P & ARMV8_DIT))
return 0;
if (ossl_get_dit()) /* It's already enabled */
return value_for_on; /* Tell caller to leave it on */
ossl_set_dit_on();
return 0;
}
/*
* Sets the DIT flag to its previous value, either off (*dit_prev == 0) or
* on (*dit_prev != 0). To be called when DIT is already on.
*/
void OPENSSL_restore_original_dit(volatile int *dit_prev)
{
if (!(OPENSSL_armcap_P & ARMV8_DIT)) /* Nothing to do */
return;
if (*dit_prev) /* Was previously set, so leave */
return;
ossl_set_dit_off();
}
#endif

View File

@ -5638,6 +5638,8 @@ int ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *tbs, size_t tbs_len,
unsigned int sz;
int res = 0;
OSSL_ENABLE_DIT_FOR_SCOPE
if (context == NULL)
context_len = 0;
@ -5699,6 +5701,8 @@ int ossl_ed25519_pubkey_verify(const uint8_t *pub, size_t pub_len)
{
ge_p3 A;
/* OSSL_ENABLE_DIT_FOR_SCOPE explicitly omitted on verify */
if (pub_len != ED25519_KEYLEN)
return 0;
return (ge_frombytes_vartime(&A, pub) == 0);
@ -5820,6 +5824,8 @@ int ossl_ed25519_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[3
int r;
EVP_MD *sha512 = NULL;
OSSL_ENABLE_DIT_FOR_SCOPE
sha512 = EVP_MD_fetch(ctx, SN_sha512, propq);
if (sha512 == NULL)
return 0;
@ -5845,6 +5851,9 @@ int ossl_x25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32])
{
static const uint8_t kZeros[32] = { 0 };
OSSL_ENABLE_DIT_FOR_SCOPE
x25519_scalar_mult(out_shared_key, private_key, peer_public_value);
/* The all-zero output results when the input is a point of small order. */
return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0;
@ -5857,6 +5866,8 @@ void ossl_x25519_public_from_private(uint8_t out_public_value[32],
ge_p3 A;
fe zplusy, zminusy, zminusy_inv;
OSSL_ENABLE_DIT_FOR_SCOPE
memcpy(e, private_key, 32);
e[0] &= 248;
e[31] &= 127;

View File

@ -216,6 +216,8 @@ int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
const char *desc;
int ret;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
@ -259,6 +261,8 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
const char *desc;
int ret;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;

View File

@ -744,6 +744,8 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
size_t soutl, inl_ = (size_t)inl;
int blocksize;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ossl_likely(outl != NULL)) {
*outl = 0;
} else {
@ -805,6 +807,8 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
size_t soutl;
int blocksize;
OSSL_ENABLE_DIT_FOR_SCOPE
if (outl != NULL) {
*outl = 0;
} else {
@ -855,6 +859,8 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
size_t soutl, inl_ = (size_t)inl;
int blocksize;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ossl_likely(outl != NULL)) {
*outl = 0;
} else {
@ -911,6 +917,8 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int ret;
int blocksize;
OSSL_ENABLE_DIT_FOR_SCOPE
if (outl != NULL) {
*outl = 0;
} else {

View File

@ -225,6 +225,8 @@ int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
unsigned char *secret, size_t *secretlen)
{
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL)
return 0;
@ -262,6 +264,8 @@ int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
unsigned char *secret, size_t *secretlen,
const unsigned char *in, size_t inlen)
{
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL
|| (in == NULL || inlen == 0)
|| (secret == NULL && secretlen == NULL))

View File

@ -337,6 +337,8 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
EVP_PKEY_CTX *pctx = ctx->pctx;
int ret;
OSSL_ENABLE_DIT_FOR_SCOPE
if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
return 0;
@ -412,6 +414,8 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
int r = 0;
EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx;
OSSL_ENABLE_DIT_FOR_SCOPE
if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
return 0;
@ -465,6 +469,8 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
return 0;
}
OSSL_ENABLE_DIT_FOR_SCOPE
if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) {
ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR);
return 0;

View File

@ -107,6 +107,8 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
/* Legacy compatible keygen callback info, only used with provider impls */
int gentmp[2];
OSSL_ENABLE_DIT_FOR_SCOPE
if (ppkey == NULL)
return -1;

View File

@ -903,6 +903,8 @@ int EVP_PKEY_sign_message_update(EVP_PKEY_CTX *ctx,
const char *desc;
int ret;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return -1;
@ -935,6 +937,8 @@ int EVP_PKEY_sign_message_final(EVP_PKEY_CTX *ctx,
const char *desc;
int ret;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return -1;
@ -969,6 +973,8 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
const char *desc;
int ret;
OSSL_ENABLE_DIT_FOR_SCOPE
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return -1;
@ -1051,6 +1057,8 @@ int EVP_PKEY_verify_message_update(EVP_PKEY_CTX *ctx,
const char *desc;
int ret;
/* OSSL_ENABLE_DIT_FOR_SCOPE explicitly omitted on verify */
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return -1;

View File

@ -1683,9 +1683,10 @@ This call is only valid when decrypting data.
Where possible the B<EVP> interface to symmetric ciphers should be used in
preference to the low-level interfaces. This is because the code then becomes
transparent to the cipher used and much more flexible. Additionally, the
B<EVP> interface will ensure the use of platform specific cryptographic
acceleration such as AES-NI (the low-level interfaces do not provide the
guarantee).
B<EVP> interface will ensure the use of platform-specific cryptographic
acceleration such as AES-NI and platform-provided data-independent timing
protection such as DIT (the low-level interfaces do not provide these
guarantees).
PKCS padding works by adding B<n> padding bytes of value B<n> to make the total
length of the encrypted data a multiple of the block size. Padding is always

View File

@ -591,6 +591,53 @@ void OSSL_sleep(uint64_t millis);
void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index);
/*
* Data-independent timing.
*
* OSSL_ENABLE_DIT_FOR_SCOPE must be placed before code that uses instructions
* whose timing depends on their data - otherwise constant-time code might not
* be.
*
* OSSL_ENABLE_DIT_FOR_SCOPE can be placed at the beginning of a code section
* that makes repeated calls to crypto functions.
*
* DIT state will automatically be restored to its previous value at the end of
* the scope.
*
* This can reduce the overhead of repeatedly setting and resetting the state.
*
* Note that this requires the cleanup attribute to function, and that this
* attribute is not supported in clang versions before 15. Support for the
* cleanup attribute was introduced into GCC in version 4.0, which pre-dates
* Aarch64. For the minute we just support those two compilers, but if a
* compiler has attribute cleanup support, it could be added to the list below.
*/
#if defined(__aarch64__) && !defined(OSSL_NO_DIT)
#if !(defined(__GNUC__) || (defined(__clang__) && (__clang_major__ >= 15)))
#warning "Unsupported compiler - disabling DIT"
#define OSSL_NO_DIT
#endif
#endif
#if defined(__aarch64__) && !defined(OSSL_NO_DIT)
/* Internal functions used by OSSL_ENABLE_DIT_FOR_SCOPE */
void OPENSSL_restore_original_dit(volatile int *dit_prev);
int OPENSSL_ensure_dit_on(int);
#define OSSL_ENABLE_DIT_FOR_SCOPE \
volatile int dit_prev_ \
__attribute__((cleanup(OPENSSL_restore_original_dit))) \
__attribute__((unused)) \
= OPENSSL_ensure_dit_on(1);
#else
#define OSSL_ENABLE_DIT_FOR_SCOPE
#endif /* __aarch64__ && !OSSL_NO_DIT */
#ifdef __cplusplus
}
#endif