summaryrefslogtreecommitdiff
path: root/rijndael.cpp
diff options
context:
space:
mode:
authorJeffrey Walton <noloader@gmail.com>2017-09-11 22:52:22 -0400
committerJeffrey Walton <noloader@gmail.com>2017-09-11 22:52:22 -0400
commit7fb34e9b0894ccb091550e0b9457b72f0920abea (patch)
tree69a22ecaf6cfd27c6b7f14d5f75dd83b638e68a4 /rijndael.cpp
parent9c9d5ebe8702c69aec7488b511475eefe33ba862 (diff)
downloadcryptopp-git-7fb34e9b0894ccb091550e0b9457b72f0920abea.tar.gz
Add Power8 AES encryption
This is the forward direction on encryption only. Crypto++ uses the "Equivalent Inverse Cipher" (FIPS-197, Section 5.3.5, p.23), and it is not compatible with IBM hardware. The library library will need to re-work the decryption key scheduling routines. (We may be able to work around it another way, but I have not investigated it).
Diffstat (limited to 'rijndael.cpp')
-rw-r--r--rijndael.cpp52
1 files changed, 48 insertions, 4 deletions
diff --git a/rijndael.cpp b/rijndael.cpp
index 3c2a2cad..25d172a0 100644
--- a/rijndael.cpp
+++ b/rijndael.cpp
@@ -237,6 +237,17 @@ extern size_t Rijndael_Dec_AdvancedProcessBlocks_ARMV8(const word32 *subkeys, si
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
#endif
+#if (CRYPTOPP_POWER8_AES_AVAILABLE)
+extern void ByteReverseArrayLE(byte src[16]);
+
+extern void Rijndael_UncheckedSetKey_POWER8(const byte *userKey, size_t keyLen, word32 *rk, CipherDir dir);
+
+extern void Rijndael_Enc_ProcessAndXorBlock_POWER8(const word32 *subkeys, size_t rounds,
+ const byte *inBlock, const byte *xorBlock, byte *outBlock);
+extern void Rijndael_Dec_ProcessAndXorBlock_POWER8(const word32 *subkeys, size_t rounds,
+ const byte *inBlock, const byte *xorBlock, byte *outBlock);
+#endif
+
void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLen, const NameValuePairs &)
{
AssertValidKeyLength(keyLen);
@@ -267,7 +278,8 @@ void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLen, c
while (true)
{
temp = rk[keyLen/4-1];
- word32 x = (word32(Se[GETBYTE(temp, 2)]) << 24) ^ (word32(Se[GETBYTE(temp, 1)]) << 16) ^ (word32(Se[GETBYTE(temp, 0)]) << 8) ^ Se[GETBYTE(temp, 3)];
+ word32 x = (word32(Se[GETBYTE(temp, 2)]) << 24) ^ (word32(Se[GETBYTE(temp, 1)]) << 16) ^
+ (word32(Se[GETBYTE(temp, 0)]) << 8) ^ Se[GETBYTE(temp, 3)];
rk[keyLen/4] = rk[0] ^ x ^ *(rc++);
rk[keyLen/4+1] = rk[1] ^ rk[keyLen/4];
rk[keyLen/4+2] = rk[2] ^ rk[keyLen/4+1];
@@ -307,10 +319,11 @@ void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLen, c
if (!s_TdFilled)
FillDecTable();
- unsigned int i, j;
-
-#define InverseMixColumn(x) TL_M(Td, 0, Se[GETBYTE(x, 3)]) ^ TL_M(Td, 1, Se[GETBYTE(x, 2)]) ^ TL_M(Td, 2, Se[GETBYTE(x, 1)]) ^ TL_M(Td, 3, Se[GETBYTE(x, 0)])
+ #define InverseMixColumn(x) \
+ TL_M(Td, 0, Se[GETBYTE(x, 3)]) ^ TL_M(Td, 1, Se[GETBYTE(x, 2)]) ^ \
+ TL_M(Td, 2, Se[GETBYTE(x, 1)]) ^ TL_M(Td, 3, Se[GETBYTE(x, 0)])
+ unsigned int i, j;
for (i = 4, j = 4*m_rounds-4; i < j; i += 4, j -= 4)
{
temp = InverseMixColumn(rk[i ]); rk[i ] = InverseMixColumn(rk[j ]); rk[j ] = temp;
@@ -338,6 +351,21 @@ void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLen, c
if (HasAES())
ConditionalByteReverse(BIG_ENDIAN_ORDER, rk+4, rk+4, (m_rounds-1)*16);
#endif
+#if CRYPTOPP_POWER8_AES_AVAILABLE
+ if (IsForwardTransformation() && HasAES())
+ {
+ ConditionalByteReverse(BIG_ENDIAN_ORDER, rk+4, rk+4, (m_rounds-1)*16);
+
+ // VSX registers are big-endian. The entire subkey table must be byte
+ // reversed on little-endian systems to ensure it loads properly.
+ // I believe we should do this when msr.le=1, but I can't find an
+ // intrinsic to access the machine status register. In the meantime
+ // we will do it anytime IS_LITTLE_ENDIAN is true.
+ byte * ptr = reinterpret_cast<byte*>(rk);
+ for (unsigned int i=0; i<=m_rounds; i++)
+ ByteReverseArrayLE(ptr+i*16);
+ }
+#endif
}
void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
@@ -362,6 +390,14 @@ void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
}
#endif
+#if (CRYPTOPP_POWER8_AES_AVAILABLE)
+ if (HasAES())
+ {
+ (void)Rijndael_Enc_ProcessAndXorBlock_POWER8(m_key, m_rounds, inBlock, xorBlock, outBlock);
+ return;
+ }
+#endif
+
typedef BlockGetAndPut<word32, NativeByteOrder> Block;
word32 s0, s1, s2, s3, t0, t1, t2, t3;
@@ -448,6 +484,14 @@ void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
}
#endif
+#if (CRYPTOPP_POWER8_AES_AVAILABLE) && 0
+ if (HasAES())
+ {
+ (void)Rijndael_Dec_ProcessAndXorBlock_POWER8(m_key, m_rounds, inBlock, xorBlock, outBlock);
+ return;
+ }
+#endif
+
typedef BlockGetAndPut<word32, NativeByteOrder> Block;
word32 s0, s1, s2, s3, t0, t1, t2, t3;