diff options
author | Jack Lloyd <[email protected]> | 2018-02-23 18:06:17 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-02-23 19:56:22 -0500 |
commit | c6accf871af69b16f4b194fecc34db36367be969 (patch) | |
tree | 4b3c5697f02cb75716545fd89d031a63a06a659e /src/lib/block/aes | |
parent | 41daa7f4e7c637836279608f31fac4115e4fd7f0 (diff) |
AES encryption using POWER8 intrinsics
Diffstat (limited to 'src/lib/block/aes')
-rw-r--r-- | src/lib/block/aes/aes.cpp | 49 | ||||
-rw-r--r-- | src/lib/block/aes/aes.h | 15 | ||||
-rw-r--r-- | src/lib/block/aes/aes_power8/aes_power8.cpp | 223 | ||||
-rw-r--r-- | src/lib/block/aes/aes_power8/info.txt | 9 |
4 files changed, 296 insertions, 0 deletions
diff --git a/src/lib/block/aes/aes.cpp b/src/lib/block/aes/aes.cpp index 9c375c362..04f2cc21f 100644 --- a/src/lib/block/aes/aes.cpp +++ b/src/lib/block/aes/aes.cpp @@ -430,6 +430,13 @@ const char* aes_provider() } #endif +#if defined(BOTAN_HAS_AES_POWER8) + if(CPUID::has_ppc_crypto()) + { + return "power8"; + } +#endif + #if defined(BOTAN_HAS_AES_ARMV8) if(CPUID::has_arm_aes()) { @@ -475,6 +482,13 @@ void AES_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const } #endif +#if defined(BOTAN_HAS_AES_POWER8) + if(CPUID::has_ppc_crypto()) + { + return power8_encrypt_n(in, out, blocks); + } +#endif + aes_encrypt_n(in, out, blocks, m_EK, m_ME); } @@ -503,6 +517,13 @@ void AES_128::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const } #endif +#if defined(BOTAN_HAS_AES_POWER8) && 0 + if(CPUID::has_ppc_crypto()) + { + return power8_decrypt_n(in, out, blocks); + } +#endif + aes_decrypt_n(in, out, blocks, m_DK, m_MD); } @@ -558,6 +579,13 @@ void AES_192::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const } #endif +#if defined(BOTAN_HAS_AES_POWER8) + if(CPUID::has_ppc_crypto()) + { + return power8_encrypt_n(in, out, blocks); + } +#endif + aes_encrypt_n(in, out, blocks, m_EK, m_ME); } @@ -586,6 +614,13 @@ void AES_192::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const } #endif +#if defined(BOTAN_HAS_AES_POWER8) && 0 + if(CPUID::has_ppc_crypto()) + { + return power8_decrypt_n(in, out, blocks); + } +#endif + aes_decrypt_n(in, out, blocks, m_DK, m_MD); } @@ -641,6 +676,13 @@ void AES_256::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const } #endif +#if defined(BOTAN_HAS_AES_POWER8) + if(CPUID::has_ppc_crypto()) + { + return power8_encrypt_n(in, out, blocks); + } +#endif + aes_encrypt_n(in, out, blocks, m_EK, m_ME); } @@ -669,6 +711,13 @@ void AES_256::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const } #endif +#if defined(BOTAN_HAS_AES_POWER8) && 0 + if(CPUID::has_ppc_crypto()) + { + return power8_decrypt_n(in, out, blocks); + } +#endif + aes_decrypt_n(in, out, blocks, m_DK, m_MD); } diff --git a/src/lib/block/aes/aes.h b/src/lib/block/aes/aes.h index 8af2423d0..294cdcad3 100644 --- a/src/lib/block/aes/aes.h +++ b/src/lib/block/aes/aes.h @@ -48,6 +48,11 @@ class BOTAN_PUBLIC_API(2,0) AES_128 final : public Block_Cipher_Fixed_Params<16, void armv8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; #endif +#if defined(BOTAN_HAS_AES_POWER8) + void power8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; + void power8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; +#endif + secure_vector<uint32_t> m_EK, m_DK; secure_vector<uint8_t> m_ME, m_MD; }; @@ -86,6 +91,11 @@ class BOTAN_PUBLIC_API(2,0) AES_192 final : public Block_Cipher_Fixed_Params<16, void armv8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; #endif +#if defined(BOTAN_HAS_AES_POWER8) + void power8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; + void power8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; +#endif + void key_schedule(const uint8_t key[], size_t length) override; secure_vector<uint32_t> m_EK, m_DK; @@ -127,6 +137,11 @@ class BOTAN_PUBLIC_API(2,0) AES_256 final : public Block_Cipher_Fixed_Params<16, void armv8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; #endif +#if defined(BOTAN_HAS_AES_POWER8) + void power8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; + void power8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const; +#endif + void key_schedule(const uint8_t key[], size_t length) override; secure_vector<uint32_t> m_EK, m_DK; diff --git a/src/lib/block/aes/aes_power8/aes_power8.cpp b/src/lib/block/aes/aes_power8/aes_power8.cpp new file mode 100644 index 000000000..b6d42081e --- /dev/null +++ b/src/lib/block/aes/aes_power8/aes_power8.cpp @@ -0,0 +1,223 @@ +/* +* AES using POWER8 crypto extensions +* +* Contributed by Jeffrey Walton +* +* Further changes +* (C) 2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/aes.h> +#include <botan/cpuid.h> + +#include <altivec.h> +#undef vector +#undef bool + +namespace Botan { + +namespace { + +__vector unsigned long long LoadKey(const uint32_t* src) + { + __vector unsigned int vec = vec_vsx_ld(0, src); + + if(CPUID::is_little_endian()) + { + const __vector unsigned char mask = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3}; + const __vector unsigned char zero = {0}; + return (__vector unsigned long long)vec_perm((__vector unsigned char)vec, zero, mask); + } + else + { + return (__vector unsigned long long)vec; + } + } + +__vector unsigned char Reverse8x16(const __vector unsigned char src) + { + if(CPUID::is_little_endian()) + { + const __vector unsigned char mask = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; + const __vector unsigned char zero = {0}; + return vec_perm(src, zero, mask); + } + else + { + return src; + } + } + +__vector unsigned long long LoadBlock(const uint8_t* src) + { + return (__vector unsigned long long)Reverse8x16(vec_vsx_ld(0, src)); + } + +void StoreBlock(const __vector unsigned long long src, uint8_t* dest) + { + vec_vsx_st(Reverse8x16((__vector unsigned char)src), 0, dest); + } + +} + +BOTAN_FUNC_ISA("crypto") +void AES_128::power8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const + { + BOTAN_ASSERT(m_EK.empty() == false, "Key was set"); + + const __vector unsigned long long K0 = LoadKey(&m_EK[0]); + const __vector unsigned long long K1 = LoadKey(&m_EK[4]); + const __vector unsigned long long K2 = LoadKey(&m_EK[8]); + const __vector unsigned long long K3 = LoadKey(&m_EK[12]); + const __vector unsigned long long K4 = LoadKey(&m_EK[16]); + const __vector unsigned long long K5 = LoadKey(&m_EK[20]); + const __vector unsigned long long K6 = LoadKey(&m_EK[24]); + const __vector unsigned long long K7 = LoadKey(&m_EK[28]); + const __vector unsigned long long K8 = LoadKey(&m_EK[32]); + const __vector unsigned long long K9 = LoadKey(&m_EK[36]); + const __vector unsigned long long K10 = LoadBlock(m_ME.data()); + + for(size_t i = 0; i != blocks; ++i) + { + __vector unsigned long long B = LoadBlock(in); + + B = vec_xor(B, K0); + B = __builtin_crypto_vcipher(B, K1); + B = __builtin_crypto_vcipher(B, K2); + B = __builtin_crypto_vcipher(B, K3); + B = __builtin_crypto_vcipher(B, K4); + B = __builtin_crypto_vcipher(B, K5); + B = __builtin_crypto_vcipher(B, K6); + B = __builtin_crypto_vcipher(B, K7); + B = __builtin_crypto_vcipher(B, K8); + B = __builtin_crypto_vcipher(B, K9); + B = __builtin_crypto_vcipherlast(B, K10); + + StoreBlock(B, out); + + out += 16; + in += 16; + } + } + +BOTAN_FUNC_ISA("crypto") +void AES_128::power8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const + { + BOTAN_ASSERT(m_DK.empty() == false, "Key was set"); + + BOTAN_UNUSED(in, out, blocks); + throw Not_Implemented("FIXME"); + } + +BOTAN_FUNC_ISA("crypto") +void AES_192::power8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const + { + BOTAN_ASSERT(m_EK.empty() == false, "Key was set"); + + const __vector unsigned long long K0 = LoadKey(&m_EK[0]); + const __vector unsigned long long K1 = LoadKey(&m_EK[4]); + const __vector unsigned long long K2 = LoadKey(&m_EK[8]); + const __vector unsigned long long K3 = LoadKey(&m_EK[12]); + const __vector unsigned long long K4 = LoadKey(&m_EK[16]); + const __vector unsigned long long K5 = LoadKey(&m_EK[20]); + const __vector unsigned long long K6 = LoadKey(&m_EK[24]); + const __vector unsigned long long K7 = LoadKey(&m_EK[28]); + const __vector unsigned long long K8 = LoadKey(&m_EK[32]); + const __vector unsigned long long K9 = LoadKey(&m_EK[36]); + const __vector unsigned long long K10 = LoadKey(&m_EK[40]); + const __vector unsigned long long K11 = LoadKey(&m_EK[44]); + const __vector unsigned long long K12 = LoadBlock(m_ME.data()); + + for(size_t i = 0; i != blocks; ++i) + { + __vector unsigned long long B = LoadBlock(in); + + B = vec_xor(B, K0); + B = __builtin_crypto_vcipher(B, K1); + B = __builtin_crypto_vcipher(B, K2); + B = __builtin_crypto_vcipher(B, K3); + B = __builtin_crypto_vcipher(B, K4); + B = __builtin_crypto_vcipher(B, K5); + B = __builtin_crypto_vcipher(B, K6); + B = __builtin_crypto_vcipher(B, K7); + B = __builtin_crypto_vcipher(B, K8); + B = __builtin_crypto_vcipher(B, K9); + B = __builtin_crypto_vcipher(B, K10); + B = __builtin_crypto_vcipher(B, K11); + B = __builtin_crypto_vcipherlast(B, K12); + + StoreBlock(B, out); + + out += 16; + in += 16; + } + } + +BOTAN_FUNC_ISA("crypto") +void AES_192::power8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const + { + BOTAN_ASSERT(m_DK.empty() == false, "Key was set"); + BOTAN_UNUSED(in, out, blocks); + throw Not_Implemented("FIXME"); + } + +BOTAN_FUNC_ISA("crypto") +void AES_256::power8_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const + { + BOTAN_ASSERT(m_EK.empty() == false, "Key was set"); + const __vector unsigned long long K0 = LoadKey(&m_EK[0]); + const __vector unsigned long long K1 = LoadKey(&m_EK[4]); + const __vector unsigned long long K2 = LoadKey(&m_EK[8]); + const __vector unsigned long long K3 = LoadKey(&m_EK[12]); + const __vector unsigned long long K4 = LoadKey(&m_EK[16]); + const __vector unsigned long long K5 = LoadKey(&m_EK[20]); + const __vector unsigned long long K6 = LoadKey(&m_EK[24]); + const __vector unsigned long long K7 = LoadKey(&m_EK[28]); + const __vector unsigned long long K8 = LoadKey(&m_EK[32]); + const __vector unsigned long long K9 = LoadKey(&m_EK[36]); + const __vector unsigned long long K10 = LoadKey(&m_EK[40]); + const __vector unsigned long long K11 = LoadKey(&m_EK[44]); + const __vector unsigned long long K12 = LoadKey(&m_EK[48]); + const __vector unsigned long long K13 = LoadKey(&m_EK[52]); + const __vector unsigned long long K14 = LoadBlock(m_ME.data()); + + for(size_t i = 0; i != blocks; ++i) + { + __vector unsigned long long B = LoadBlock(in); + + B = vec_xor(B, K0); + B = __builtin_crypto_vcipher(B, K1); + B = __builtin_crypto_vcipher(B, K2); + B = __builtin_crypto_vcipher(B, K3); + B = __builtin_crypto_vcipher(B, K4); + B = __builtin_crypto_vcipher(B, K5); + B = __builtin_crypto_vcipher(B, K6); + B = __builtin_crypto_vcipher(B, K7); + B = __builtin_crypto_vcipher(B, K8); + B = __builtin_crypto_vcipher(B, K9); + B = __builtin_crypto_vcipher(B, K10); + B = __builtin_crypto_vcipher(B, K11); + B = __builtin_crypto_vcipher(B, K12); + B = __builtin_crypto_vcipher(B, K13); + B = __builtin_crypto_vcipherlast(B, K14); + + StoreBlock(B, out); + + out += 16; + in += 16; + } + + } + +BOTAN_FUNC_ISA("crypto") +void AES_256::power8_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const + { + BOTAN_ASSERT(m_DK.empty() == false, "Key was set"); + + BOTAN_UNUSED(in, out, blocks); + throw Not_Implemented("FIXME"); + } + +} diff --git a/src/lib/block/aes/aes_power8/info.txt b/src/lib/block/aes/aes_power8/info.txt new file mode 100644 index 000000000..6aa52d25a --- /dev/null +++ b/src/lib/block/aes/aes_power8/info.txt @@ -0,0 +1,9 @@ +<defines> +AES_POWER8 -> 20180223 +</defines> + +<arch> +ppc64 +</arch> + +need_isa ppccrypto |