update x86 and aes support checks at compile time

Signed-off-by: r4sas <r4sas@i2pmail.org>
This commit is contained in:
r4sas 2023-08-10 14:01:03 +00:00
parent ebe9fd90af
commit 9d3d35c71c
No known key found for this signature in database
GPG key ID: 66F6C87B98EBCFE2
3 changed files with 172 additions and 160 deletions

View file

@ -25,7 +25,7 @@ namespace cpu
inline bool cpu_support_aes() inline bool cpu_support_aes()
{ {
#if (_M_AMD64 || __x86_64__) || (_M_IX86 || __i386__) #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__))
#if defined(_MSC_VER) #if defined(_MSC_VER)
int cpu_info[4]; int cpu_info[4];
__cpuid(cpu_info, 1); __cpuid(cpu_info, 1);

View file

@ -193,7 +193,7 @@ namespace config {
options_description precomputation("Precomputation options"); options_description precomputation("Precomputation options");
precomputation.add_options() precomputation.add_options()
("precomputation.elgamal", ("precomputation.elgamal",
#if defined(__x86_64__) #if (_M_AMD64 || __x86_64__)
value<bool>()->default_value(false), value<bool>()->default_value(false),
#else #else
value<bool>()->default_value(true), value<bool>()->default_value(true),

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2023, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -28,6 +28,12 @@
#include "I2PEndian.h" #include "I2PEndian.h"
#include "Log.h" #include "Log.h"
#if defined(__AES__) && !defined(_MSC_VER) && ((defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)))
#define SUPPORTS_AES 1
#else
#define SUPPORTS_AES 0
#endif
namespace i2p namespace i2p
{ {
namespace crypto namespace crypto
@ -361,7 +367,7 @@ namespace crypto
BIGNUM * b1 = BN_CTX_get (ctx); BIGNUM * b1 = BN_CTX_get (ctx);
BIGNUM * b = BN_CTX_get (ctx); BIGNUM * b = BN_CTX_get (ctx);
// select random k // select random k
#if defined(__x86_64__) #if (defined(_M_AMD64) || defined(__x86_64__))
BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
#else #else
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
@ -428,7 +434,7 @@ namespace crypto
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub) void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
{ {
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER) #if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_IX86) || defined(__i386__)) || defined(_MSC_VER)
RAND_bytes (priv, 256); RAND_bytes (priv, 256);
#else #else
// lower 226 bits (28 bytes and 2 bits) only. short exponent // lower 226 bits (28 bytes and 2 bits) only. short exponent
@ -555,7 +561,7 @@ namespace crypto
} }
// AES // AES
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
#define KeyExpansion256(round0,round1) \ #define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \
"movaps %%xmm1, %%xmm4 \n" \ "movaps %%xmm1, %%xmm4 \n" \
@ -580,7 +586,7 @@ namespace crypto
"movaps %%xmm3, "#round1"(%[sched]) \n" "movaps %%xmm3, "#round1"(%[sched]) \n"
#endif #endif
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
void ECBCryptoAESNI::ExpandKey (const AESKey& key) void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{ {
__asm__ __asm__
@ -621,7 +627,7 @@ namespace crypto
#endif #endif
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
#define EncryptAES256(sched) \ #define EncryptAES256(sched) \
"pxor (%["#sched"]), %%xmm0 \n" \ "pxor (%["#sched"]), %%xmm0 \n" \
"aesenc 16(%["#sched"]), %%xmm0 \n" \ "aesenc 16(%["#sched"]), %%xmm0 \n" \
@ -642,16 +648,18 @@ namespace crypto
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out) void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
EncryptAES256(sched) EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" :
); : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
} }
else else
#endif #endif
@ -660,7 +668,7 @@ namespace crypto
} }
} }
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
#define DecryptAES256(sched) \ #define DecryptAES256(sched) \
"pxor 224(%["#sched"]), %%xmm0 \n" \ "pxor 224(%["#sched"]), %%xmm0 \n" \
"aesdec 208(%["#sched"]), %%xmm0 \n" \ "aesdec 208(%["#sched"]), %%xmm0 \n" \
@ -681,16 +689,18 @@ namespace crypto
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out) void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
DecryptAES256(sched) DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" :
); : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
} }
else else
#endif #endif
@ -699,7 +709,7 @@ namespace crypto
} }
} }
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
#define CallAESIMC(offset) \ #define CallAESIMC(offset) \
"movaps "#offset"(%[shed]), %%xmm0 \n" \ "movaps "#offset"(%[shed]), %%xmm0 \n" \
"aesimc %%xmm0, %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \
@ -708,7 +718,7 @@ namespace crypto
void ECBEncryption::SetKey (const AESKey& key) void ECBEncryption::SetKey (const AESKey& key)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
ExpandKey (key); ExpandKey (key);
@ -722,28 +732,30 @@ namespace crypto
void ECBDecryption::SetKey (const AESKey& key) void ECBDecryption::SetKey (const AESKey& key)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
ExpandKey (key); // expand encryption key first ExpandKey (key); // expand encryption key first
// then invert it using aesimc // then invert it using aesimc
__asm__ __asm__
( (
CallAESIMC(16) CallAESIMC(16)
CallAESIMC(32) CallAESIMC(32)
CallAESIMC(48) CallAESIMC(48)
CallAESIMC(64) CallAESIMC(64)
CallAESIMC(80) CallAESIMC(80)
CallAESIMC(96) CallAESIMC(96)
CallAESIMC(112) CallAESIMC(112)
CallAESIMC(128) CallAESIMC(128)
CallAESIMC(144) CallAESIMC(144)
CallAESIMC(160) CallAESIMC(160)
CallAESIMC(176) CallAESIMC(176)
CallAESIMC(192) CallAESIMC(192)
CallAESIMC(208) CallAESIMC(208)
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory" :
); : [shed]"r"(GetKeySchedule ())
: "%xmm0", "memory"
);
} }
else else
#endif #endif
@ -754,28 +766,28 @@ namespace crypto
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
"movups (%[iv]), %%xmm1 \n" "movups (%[iv]), %%xmm1 \n"
"1: \n" "1: \n"
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched) EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n" "movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n" "add $16, %[in] \n"
"add $16, %[out] \n" "add $16, %[out] \n"
"dec %[num] \n" "dec %[num] \n"
"jnz 1b \n" "jnz 1b \n"
"movups %%xmm1, (%[iv]) \n" "movups %%xmm1, (%[iv]) \n"
: :
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory" : "%xmm0", "%xmm1", "cc", "memory"
); );
} }
else else
#endif #endif
@ -799,22 +811,22 @@ namespace crypto
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
"movups (%[iv]), %%xmm1 \n" "movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched) EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n" "movups %%xmm0, (%[iv]) \n"
: :
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out) [in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory" : "%xmm0", "%xmm1", "memory"
); );
} }
else else
#endif #endif
@ -823,29 +835,29 @@ namespace crypto
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
"movups (%[iv]), %%xmm1 \n" "movups (%[iv]), %%xmm1 \n"
"1: \n" "1: \n"
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n" "movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched) DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n" "movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n" "add $16, %[in] \n"
"add $16, %[out] \n" "add $16, %[out] \n"
"dec %[num] \n" "dec %[num] \n"
"jnz 1b \n" "jnz 1b \n"
"movups %%xmm1, (%[iv]) \n" "movups %%xmm1, (%[iv]) \n"
: :
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory" : "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
); );
} }
else else
#endif #endif
@ -869,22 +881,22 @@ namespace crypto
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
"movups (%[iv]), %%xmm1 \n" "movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n" "movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched) DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
: :
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out) [in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory" : "%xmm0", "%xmm1", "memory"
); );
} }
else else
#endif #endif
@ -893,34 +905,34 @@ namespace crypto
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
// encrypt IV // encrypt IV
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv) EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n" "movaps %%xmm0, %%xmm1 \n"
// double IV encryption // double IV encryption
EncryptAES256(sched_iv) EncryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
// encrypt data, IV is xmm1 // encrypt data, IV is xmm1
"1: \n" "1: \n"
"add $16, %[in] \n" "add $16, %[in] \n"
"add $16, %[out] \n" "add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l) EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n" "movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
"dec %[num] \n" "dec %[num] \n"
"jnz 1b \n" "jnz 1b \n"
: :
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()), : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory" : "%xmm0", "%xmm1", "cc", "memory"
); );
} }
else else
#endif #endif
@ -934,35 +946,35 @@ namespace crypto
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{ {
#if defined(__AES__) && (defined(__x86_64__) || defined(__i386__)) #if SUPPORTS_AES
if(i2p::cpu::aesni) if(i2p::cpu::aesni)
{ {
__asm__ __asm__
( (
// decrypt IV // decrypt IV
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv) DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n" "movaps %%xmm0, %%xmm1 \n"
// double IV encryption // double IV encryption
DecryptAES256(sched_iv) DecryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
// decrypt data, IV is xmm1 // decrypt data, IV is xmm1
"1: \n" "1: \n"
"add $16, %[in] \n" "add $16, %[in] \n"
"add $16, %[out] \n" "add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n" "movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n" "movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l) DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n" "pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n" "movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n" "dec %[num] \n"
"jnz 1b \n" "jnz 1b \n"
: :
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()), : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory" : "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
); );
} }
else else
#endif #endif
@ -1297,7 +1309,7 @@ namespace crypto
CRYPTO_set_locking_callback (OpensslLockingCallback);*/ CRYPTO_set_locking_callback (OpensslLockingCallback);*/
if (precomputation) if (precomputation)
{ {
#if defined(__x86_64__) #if (defined(_M_AMD64) || defined(__x86_64__))
g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
#else #else
@ -1312,7 +1324,7 @@ namespace crypto
if (g_ElggTable) if (g_ElggTable)
{ {
DestroyElggTable (g_ElggTable, DestroyElggTable (g_ElggTable,
#if defined(__x86_64__) #if (defined(_M_AMD64) || defined(__x86_64__))
ELGAMAL_FULL_EXPONENT_NUM_BYTES ELGAMAL_FULL_EXPONENT_NUM_BYTES
#else #else
ELGAMAL_SHORT_EXPONENT_NUM_BYTES ELGAMAL_SHORT_EXPONENT_NUM_BYTES