aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/block/aes
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-02-23 18:06:17 -0500
committerJack Lloyd <[email protected]>2018-02-23 19:56:22 -0500
commitc6accf871af69b16f4b194fecc34db36367be969 (patch)
tree4b3c5697f02cb75716545fd89d031a63a06a659e /src/lib/block/aes
parent41daa7f4e7c637836279608f31fac4115e4fd7f0 (diff)
AES encryption using POWER8 intrinsics
Diffstat (limited to 'src/lib/block/aes')
-rw-r--r--src/lib/block/aes/aes.cpp49
-rw-r--r--src/lib/block/aes/aes.h15
-rw-r--r--src/lib/block/aes/aes_power8/aes_power8.cpp223
-rw-r--r--src/lib/block/aes/aes_power8/info.txt9
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