Ver código fonte

Encrypt: use OpenSSL's EVP interface, which supports AES-NI without the need of another library

Davide Beatrici 7 anos atrás
pai
commit
a7be140f85
5 arquivos alterados com 113 adições e 104 exclusões
  1. 0 12
      src/Cedar/Server.c
  2. 0 1
      src/Cedar/Server.h
  3. 113 77
      src/Mayaqua/Encrypt.c
  4. 0 8
      src/Mayaqua/Encrypt.h
  5. 0 6
      src/Mayaqua/Mayaqua.h

+ 0 - 12
src/Cedar/Server.c

@@ -5946,9 +5946,6 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
 		// Disable the NAT-traversal feature
 		s->DisableNatTraversal = CfgGetBool(f, "DisableNatTraversal");
 
-		// Intel AES
-		s->DisableIntelAesAcceleration = CfgGetBool(f, "DisableIntelAesAcceleration");
-
 		if (s->Cedar->Bridge == false)
 		{
 			// Enable the VPN-over-ICMP
@@ -6372,9 +6369,6 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
 			CfgAddBool(f, "EnableVpnOverDns", s->EnableVpnOverDns);
 		}
 
-		// Intel AES
-		CfgAddBool(f, "DisableIntelAesAcceleration", s->DisableIntelAesAcceleration);
-
 		if (c->Bridge == false)
 		{
 			OPENVPN_SSTP_CONFIG config;
@@ -10982,12 +10976,6 @@ SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server, bool relay_serve
 	SetFifoCurrentReallocMemSize(MEM_FIFO_REALLOC_MEM_SIZE);
 
 
-	if (s->DisableIntelAesAcceleration)
-	{
-		// Disable the Intel AES acceleration
-		DisableIntelAesAccel();
-	}
-
 	// Raise the priority
 	if (s->NoHighPriorityProcess == false)
 	{

+ 0 - 1
src/Cedar/Server.h

@@ -293,7 +293,6 @@ struct SERVER
 	bool DisableNatTraversal;			// Disable the NAT-traversal feature
 	bool EnableVpnOverIcmp;				// VPN over ICMP is enabled
 	bool EnableVpnOverDns;				// VPN over DNS is enabled
-	bool DisableIntelAesAcceleration;	// Disable the Intel AES acceleration
 	bool NoMoreSave;					// Do not save any more
 	bool EnableConditionalAccept;		// Apply the Conditional Accept the Listener
 	bool EnableLegacySSL;				// Enable Legacy SSL

+ 113 - 77
src/Mayaqua/Encrypt.c

@@ -145,9 +145,11 @@
 #include <openssl/x509v3.h>
 #include <Mayaqua/Mayaqua.h>
 
-#ifdef	USE_INTEL_AESNI_LIBRARY
-#include <intelaes/iaesni.h>
-#endif	// USE_INTEL_AESNI_LIBRARY
+#ifdef _MSC_VER
+#include <intrin.h> // For __cpuid()
+#else
+#include <cpuid.h> // For __get_cpuid()
+#endif
 
 LOCK *openssl_lock = NULL;
 
@@ -156,7 +158,6 @@ int ssl_clientcert_index = 0;
 LOCK **ssl_lock_obj = NULL;
 UINT ssl_lock_num;
 static bool openssl_inited = false;
-static bool is_intel_aes_supported = false;
 
 static unsigned char *Internal_SHA0(const unsigned char *d, size_t n, unsigned char *md);
 
@@ -3662,7 +3663,6 @@ void InitCryptLibrary()
 {
 	char tmp[16];
 
-	CheckIfIntelAesNiSupportedInit();
 //	RAND_Init_For_SoftEther()
 	openssl_lock = NewLock();
 	SSL_library_init();
@@ -4106,81 +4106,85 @@ void AesFreeKey(AES_KEY_VALUE *k)
 // AES encryption
 void AesEncrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
 {
-	UCHAR ivec_copy[AES_IV_SIZE];
+	EVP_CIPHER_CTX *ctx = NULL;
+	int dest_len = 0;
+	int len = 0;
+	int ret = 0;
+
 	// Validate arguments
 	if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
 	{
 		return;
 	}
 
-#ifdef	USE_INTEL_AESNI_LIBRARY
-	if (is_intel_aes_supported)
+	// Create and initialize the context
+	ctx = EVP_CIPHER_CTX_new();
+
+	if (!ctx)
 	{
-		AesEncryptWithIntel(dest, src, size, k, ivec);
+		ERR_print_errors_fp(stderr);
 		return;
 	}
-#endif	// USE_INTEL_AESNI_LIBRARY
 
-	Copy(ivec_copy, ivec, AES_IV_SIZE);
+	// Disable padding, as it's handled by IkeEncryptWithPadding()
+	EVP_CIPHER_CTX_set_padding(ctx, false);
 
-	AES_cbc_encrypt(src, dest, size, k->EncryptKey, ivec, 1);
-}
-
-// AES decryption
-void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
-{
-	UCHAR ivec_copy[AES_IV_SIZE];
-	// Validate arguments
-	if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+	// Initialize the encryption operation
+	switch (k->KeySize)
 	{
-		return;
+	case 16:
+		ret = EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k->KeyValue, ivec);
+		break;
+
+	case 24:
+		ret = EVP_EncryptInit_ex(ctx, EVP_aes_192_cbc(), NULL, k->KeyValue, ivec);
+		break;
+
+	case 32:
+		ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, k->KeyValue, ivec);
+		break;
 	}
 
-#ifdef	USE_INTEL_AESNI_LIBRARY
-	if (is_intel_aes_supported)
+	if (ret != 1)
 	{
-		AesDecryptWithIntel(dest, src, size, k, ivec);
+		ERR_print_errors_fp(stderr);
+		EVP_CIPHER_CTX_free(ctx);
 		return;
 	}
-#endif	// USE_INTEL_AESNI_LIBRARY
 
-	Copy(ivec_copy, ivec, AES_IV_SIZE);
-
-	AES_cbc_encrypt(src, dest, size, k->DecryptKey, ivec, 0);
-}
+	// Provide the message to be encrypted and obtain the cipher output
+	ret = EVP_EncryptUpdate(ctx, dest, &dest_len, src, size);
 
-// Determine whether the Intel AES-NI is supported
-bool IsIntelAesNiSupported()
-{
-	return is_intel_aes_supported;
-}
-void CheckIfIntelAesNiSupportedInit()
-{
-#ifdef	USE_INTEL_AESNI_LIBRARY
-	if (check_for_aes_instructions())
+	if (ret != 1)
 	{
-		is_intel_aes_supported = true;
+		ERR_print_errors_fp(stderr);
+		EVP_CIPHER_CTX_free(ctx);
+		return;
 	}
-	else
+
+	// Finalize the encryption
+	ret = EVP_EncryptFinal_ex(ctx, (unsigned char *) dest + dest_len, &len);
+
+	if (ret != 1)
 	{
-		is_intel_aes_supported = false;
+		ERR_print_errors_fp(stderr);
+		EVP_CIPHER_CTX_free(ctx);
+		return;
 	}
-#else	// USE_INTEL_AESNI_LIBRARY
-	is_intel_aes_supported = false;
-#endif	// USE_INTEL_AESNI_LIBRARY
-}
 
-// Disable the Intel AES-NI
-void DisableIntelAesAccel()
-{
-	is_intel_aes_supported = false;
+	dest_len += len;
+
+	// Clean up
+	EVP_CIPHER_CTX_free(ctx);
 }
 
-#ifdef	USE_INTEL_AESNI_LIBRARY
-// Encrypt AES using the Intel AES-NI
-void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
+// AES decryption
+void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
 {
-	UCHAR ivec_copy[AES_IV_SIZE];
+	EVP_CIPHER_CTX *ctx = NULL;
+	int dest_len = 0;
+	int len = 0;
+	int ret = 0;
 
 	// Validate arguments
 	if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
@@ -4188,53 +4192,85 @@ void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, voi
 		return;
 	}
 
-	Copy(ivec_copy, ivec, AES_IV_SIZE);
+	// Create and initialize the context
+	ctx = EVP_CIPHER_CTX_new();
 
+	if (!ctx)
+	{
+		ERR_print_errors_fp(stderr);
+		return;
+	}
+
+	// Disable padding, as it's handled by IkeEncryptWithPadding()
+	EVP_CIPHER_CTX_set_padding(ctx, false);
+
+	// Initialize the decryption operation
 	switch (k->KeySize)
 	{
 	case 16:
-		intel_AES_enc128_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+		ret = EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k->KeyValue, ivec);
 		break;
 
 	case 24:
-		intel_AES_enc192_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+		ret = EVP_DecryptInit_ex(ctx, EVP_aes_192_cbc(), NULL, k->KeyValue, ivec);
 		break;
 
 	case 32:
-		intel_AES_enc256_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
+		ret = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, k->KeyValue, ivec);
 		break;
 	}
-}
 
-// Decrypt AES using the Intel AES-NI
-void AesDecryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec)
-{
-	UCHAR ivec_copy[AES_IV_SIZE];
-
-	// Validate arguments
-	if (dest == NULL || src == NULL || size == 0 || k == NULL || ivec == NULL)
+	if (ret != 1)
 	{
+		ERR_print_errors_fp(stderr);
+		EVP_CIPHER_CTX_free(ctx);
 		return;
 	}
 
-	Copy(ivec_copy, ivec, AES_IV_SIZE);
+	// Provide the message to be decrypted and obtain the plaintext output
+	ret = EVP_DecryptUpdate(ctx, dest, &dest_len, src, size);
 
-	switch (k->KeySize)
+	if (ret != 1)
 	{
-	case 16:
-		intel_AES_dec128_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
-		break;
+		ERR_print_errors_fp(stderr);
+		EVP_CIPHER_CTX_free(ctx);
+		return;
+	}
 
-	case 24:
-		intel_AES_dec192_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
-		break;
+	// Finalize the decryption
+	ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) dest + dest_len, &len);
 
-	case 32:
-		intel_AES_dec256_CBC(src, dest, k->KeyValue, (size / AES_IV_SIZE), ivec_copy);
-		break;
+	if (ret != 1)
+	{
+		ERR_print_errors_fp(stderr);
+		EVP_CIPHER_CTX_free(ctx);
+		return;
 	}
+
+	dest_len += len;
+
+	// Clean up
+	EVP_CIPHER_CTX_free(ctx);
+}
+
+// Determine whether the Intel AES-NI is supported
+bool IsIntelAesNiSupported()
+{
+	bool supported = false;
+
+	// Unfortunately OpenSSL doesn't provide a function to do it
+#ifdef _MSC_VER
+	int regs[4]; // EAX, EBX, ECX, EDX
+	__cpuid(regs, 1);
+	supported = (regs[2] >> 25) & 1;
+#else
+	uint32_t eax, ebx, ecx, edx;
+	__get_cpuid(1, &eax, &ebx, &ecx, &edx);
+	supported = (ecx & bit_AES) > 0;
+#endif
+
+	return supported;
 }
-#endif	// USE_INTEL_AESNI_LIBRARY
 
 // Calculation of HMAC-SHA-1
 void MacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size)

+ 0 - 8
src/Mayaqua/Encrypt.h

@@ -523,12 +523,6 @@ void AesEncrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
 void AesDecrypt(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
 
 bool IsIntelAesNiSupported();
-void CheckIfIntelAesNiSupportedInit();
-
-#ifdef	USE_INTEL_AESNI_LIBRARY
-void AesEncryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
-void AesDecryptWithIntel(void *dest, void *src, UINT size, AES_KEY_VALUE *k, void *ivec);
-#endif	// USE_INTEL_AESNI_LIBRARY
 
 void OpenSSL_InitLock();
 void OpenSSL_FreeLock();
@@ -551,8 +545,6 @@ void Enc_tls1_PRF(unsigned char *label, int label_len, const unsigned char *sec,
 void HMacSha1(void *dst, void *key, UINT key_size, void *data, UINT data_size);
 void HMacMd5(void *dst, void *key, UINT key_size, void *data, UINT data_size);
 
-void DisableIntelAesAccel();
-
 int GetSslClientCertIndex();
 
 #ifdef	ENCRYPT_C

+ 0 - 6
src/Mayaqua/Mayaqua.h

@@ -215,12 +215,6 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
 #define	PROBE_DATA(data, size)
 #endif	// USE_PROBE
 
-// About Intel AES-NI Library
-#if	(defined(OS_WIN32) || (defined(UNIX_LINUX) && (defined(CPU_X86) || defined(CPU_X64))))
-// Supports only for Linux (x86 / x64) or Windows
-#define	USE_INTEL_AESNI_LIBRARY
-#endif
-
 // Determine the performance / memory strategy
 #if	(defined(CPU_X86) || defined(CPU_X64) || defined(CPU_X86_X64) || defined(CPU_SPARC) || defined(CPU_SPARC64) || defined(OS_WIN32) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__ia64__) || defined(__IA64__) || defined(_IA64))
 #define	USE_STRATEGY_PERFORMACE