From bd7f6e539e8d415655f558dbd3e314ea0def3f65 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sun, 3 Sep 2017 15:02:41 -0400 Subject: Add support for ARMv8 PMULL instruction Contributed in GH #842 --- src/lib/modes/aead/gcm/gcm.cpp | 6 +++ src/lib/modes/aead/gcm/pmull/info.txt | 16 ++++++++ src/lib/modes/aead/gcm/pmull/pmull.cpp | 71 ++++++++++++++++++++++++++++++++++ src/lib/modes/aead/gcm/pmull/pmull.h | 19 +++++++++ 4 files changed, 112 insertions(+) create mode 100644 src/lib/modes/aead/gcm/pmull/info.txt create mode 100644 src/lib/modes/aead/gcm/pmull/pmull.cpp create mode 100644 src/lib/modes/aead/gcm/pmull/pmull.h diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index 0d0cbff3c..f9ffdee97 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -14,6 +14,9 @@ #if defined(BOTAN_HAS_GCM_CLMUL) #include #include +#elif defined(BOTAN_HAS_GCM_PMULL) + #include + #include #endif namespace Botan { @@ -25,6 +28,9 @@ void GHASH::gcm_multiply(secure_vector& x) const #if defined(BOTAN_HAS_GCM_CLMUL) if(CPUID::has_clmul()) return gcm_multiply_clmul(x.data(), m_H.data()); +#elif defined(BOTAN_HAS_GCM_PMULL) + if(CPUID::has_arm_pmull()) + return gcm_multiply_pmull(x.data(), m_H.data()); #endif static const uint64_t R = 0xE100000000000000; diff --git a/src/lib/modes/aead/gcm/pmull/info.txt b/src/lib/modes/aead/gcm/pmull/info.txt new file mode 100644 index 000000000..711587568 --- /dev/null +++ b/src/lib/modes/aead/gcm/pmull/info.txt @@ -0,0 +1,16 @@ + +GCM_PMULL -> 20170903 + + + +arm64 + + + +gcc:4.9 +clang:3.8 + + + +pmull.h + diff --git a/src/lib/modes/aead/gcm/pmull/pmull.cpp b/src/lib/modes/aead/gcm/pmull/pmull.cpp new file mode 100644 index 000000000..54e841650 --- /dev/null +++ b/src/lib/modes/aead/gcm/pmull/pmull.cpp @@ -0,0 +1,71 @@ +/* +* Contributed by Jeffrey Walton +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include + +namespace Botan { + +BOTAN_FUNC_ISA("+crypto") +void gcm_multiply_pmull(uint8_t x[16], const uint8_t H[16]) + { + /* + * Implementing GCM on ARMv8, http://conradoplg.cryptoland.net/files/2010/12/gcm14.pdf + */ + + const uint64x2_t a64 = vreinterpretq_u64_u8(vcombine_u8(vrev64_u8(vld1_u8(x+8)), vrev64_u8(vld1_u8(x)))); + const uint64x2_t b64 = vreinterpretq_u64_u8(vcombine_u8(vrev64_u8(vld1_u8(H+8)), vrev64_u8(vld1_u8(H)))); + + uint64x2_t T0, T1, T2, T3, T4, T5; + + T0 = (uint64x2_t)vmull_p64(vgetq_lane_u64(a64, 0), vgetq_lane_u64(b64, 0)); + T1 = (uint64x2_t)vmull_p64(vgetq_lane_u64(a64, 1), vgetq_lane_u64(b64, 0)); + T2 = (uint64x2_t)vmull_p64(vgetq_lane_u64(a64, 0), vgetq_lane_u64(b64, 1)); + T3 = (uint64x2_t)vmull_p64(vgetq_lane_u64(a64, 1), vgetq_lane_u64(b64, 1)); + + T1 = veorq_u64(T1, T2); + T2 = vreinterpretq_u64_u8(vextq_u8(vdupq_n_u8(0), vreinterpretq_u8_u64(T1), 8)); + T1 = vreinterpretq_u64_u8(vextq_u8(vreinterpretq_u8_u64(T1), vdupq_n_u8(0), 8)); + T0 = veorq_u64(T0, T2); + T3 = veorq_u64(T3, T1); + + T4 = vshrq_n_u64(T0, 31); + T0 = vshlq_n_u64(T0, 1); + + T5 = vshrq_n_u64(T3, 31); + T3 = vshlq_n_u64(T3, 1); + + T2 = vreinterpretq_u64_u8(vextq_u8(vreinterpretq_u8_u64(T4), vdupq_n_u8(0), 12)); + T5 = vreinterpretq_u64_u8(vextq_u8(vdupq_n_u8(0), vreinterpretq_u8_u64(T5), 12)); + T4 = vreinterpretq_u64_u8(vextq_u8(vdupq_n_u8(0), vreinterpretq_u8_u64(T4), 12)); + T0 = vorrq_u64(T0, T4); + T3 = vorrq_u64(T3, T5); + T3 = vorrq_u64(T3, T2); + + T4 = vreinterpretq_u64_u32(vshlq_n_u32(vreinterpretq_u32_u64(T0), 31)); + T5 = vreinterpretq_u64_u32(vshlq_n_u32(vreinterpretq_u32_u64(T0), 30)); + T2 = vreinterpretq_u64_u32(vshlq_n_u32(vreinterpretq_u32_u64(T0), 25)); + + T4 = veorq_u64(T4, T5); + T4 = veorq_u64(T4, T2); + T5 = vreinterpretq_u64_u8(vextq_u8(vreinterpretq_u8_u64(T4), vdupq_n_u8(0), 4)); + T3 = veorq_u64(T3, T5); + T4 = vreinterpretq_u64_u8(vextq_u8(vdupq_n_u8(0), vreinterpretq_u8_u64(T4), 4)); + T0 = veorq_u64(T0, T4); + T3 = veorq_u64(T3, T0); + + T4 = vreinterpretq_u64_u32(vshrq_n_u32(vreinterpretq_u32_u64(T0), 1)); + T1 = vreinterpretq_u64_u32(vshrq_n_u32(vreinterpretq_u32_u64(T0), 2)); + T2 = vreinterpretq_u64_u32(vshrq_n_u32(vreinterpretq_u32_u64(T0), 7)); + T3 = veorq_u64(T3, T1); + T3 = veorq_u64(T3, T2); + T3 = veorq_u64(T3, T4); + + vst1_u8(x+0, vrev64_u8(vreinterpret_u8_u64(vget_high_u64(T3)))); + vst1_u8(x+8, vrev64_u8(vreinterpret_u8_u64(vget_low_u64(T3)))); + } + +} diff --git a/src/lib/modes/aead/gcm/pmull/pmull.h b/src/lib/modes/aead/gcm/pmull/pmull.h new file mode 100644 index 000000000..04afddfbf --- /dev/null +++ b/src/lib/modes/aead/gcm/pmull/pmull.h @@ -0,0 +1,19 @@ +/* +* PMULL hook +* (C) 2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_GCM_PMULL_H__ +#define BOTAN_GCM_PMULL_H__ + +#include + +namespace Botan { + +void gcm_multiply_pmull(uint8_t x[16], const uint8_t H[16]); + +} + +#endif -- cgit v1.2.3