From 6b1a56cf72b07dd7ad95611b914605ffab924736 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Mon, 4 Sep 2017 10:47:55 -0400 Subject: [PATCH] Fixup under-aligned buffers for DefaultEncryptors and DefaultDecryptors on AltiVec and Power8 This commit supports the upcoming AltiVec and Power8 processor support for DefaultEncryptors and DefaultDecryptors. The commit favors AlignedSecByteBlock over SecByteBlock in places where messages are handled on the AltiVec and Power8 processor data paths. The data paths include all block cipher modes of operation, and some filters like FilterWithBufferedInput. Intel and ARM processors are tolerant of under-aligned buffers when using crypto intstructions. AltiVec and Power8 are less tolerant, and they simply ignore the three low-order bits to ensure an address is aligned. The AltiVec and Power8 have caused a fair number of wild writes on the stack and in the heap. Testing on a 64-bit Intel Skylake show a marked improvement in performance. We suspect GCC is generating better code since it knows the alignment of the pointers, and does not have to emit fixup code for under-aligned and mis-aligned data. Testing on an mid-2000's 32-bit VIA C7-D with SSE2+SSSE3 showed no improvement, and no performance was lost. --- default.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/default.cpp b/default.cpp index eda6cb14..b447e9c3 100644 --- a/default.cpp +++ b/default.cpp @@ -32,8 +32,8 @@ static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int ite size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)H::DIGESTSIZE); byte b[2]; - SecByteBlock buf(bufSize); - SecByteBlock outBuf(bufSize); + AlignedSecByteBlock buf(bufSize); + AlignedSecByteBlock outBuf(bufSize); H hash; unsigned int i; @@ -66,14 +66,14 @@ template static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, unsigned int iterations, byte *key, byte *IV) { // UBsan. User supplied params, may be NULL - SecByteBlock temp(passphraseLength+saltLength); + AlignedSecByteBlock temp(passphraseLength+saltLength); if (passphrase != NULLPTR) memcpy(temp, passphrase, passphraseLength); if (salt != NULLPTR) memcpy(temp+passphraseLength, salt, saltLength); // OK. Derived params, cannot be NULL - SecByteBlock keyIV(Info::KEYLENGTH+Info::BLOCKSIZE); + AlignedSecByteBlock keyIV(Info::KEYLENGTH+Info::BLOCKSIZE); Mash(temp, passphraseLength + saltLength, keyIV, Info::KEYLENGTH+Info::BLOCKSIZE, iterations); memcpy(key, keyIV, Info::KEYLENGTH); memcpy(IV, keyIV+Info::KEYLENGTH, Info::BLOCKSIZE); @@ -100,7 +100,7 @@ DataEncryptor::DataEncryptor(const byte *passphrase, size_t passphras template void DataEncryptor::FirstPut(const byte *) { - SecByteBlock salt(DIGESTSIZE), keyCheck(DIGESTSIZE); + AlignedSecByteBlock salt(DIGESTSIZE), keyCheck(DIGESTSIZE); H hash; // use hash(passphrase | time | clock) as salt @@ -119,8 +119,8 @@ void DataEncryptor::FirstPut(const byte *) AttachedTransformation()->Put(salt, SALTLENGTH); // mash passphrase and salt together into key and IV - SecByteBlock key(KEYLENGTH); - SecByteBlock IV(BLOCKSIZE); + AlignedSecByteBlock key(KEYLENGTH); + AlignedSecByteBlock IV(BLOCKSIZE); GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, ITERATIONS, key, IV); m_cipher.SetKeyWithIV(key, key.size(), IV); @@ -186,15 +186,15 @@ void DataDecryptor::LastPut(const byte *inString, size_t length) template void DataDecryptor::CheckKey(const byte *salt, const byte *keyCheck) { - SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DIGESTSIZE)); + AlignedSecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DIGESTSIZE)); H hash; hash.Update(m_passphrase, m_passphrase.size()); hash.Update(salt, SALTLENGTH); hash.Final(check); - SecByteBlock key(KEYLENGTH); - SecByteBlock IV(BLOCKSIZE); + AlignedSecByteBlock key(KEYLENGTH); + AlignedSecByteBlock IV(BLOCKSIZE); GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, ITERATIONS, key, IV); m_cipher.SetKeyWithIV(key, key.size(), IV); @@ -222,7 +222,7 @@ template static MAC* NewDataEncryptorMAC(const byte *passphrase, size_t passphraseLength) { size_t macKeyLength = MAC::StaticGetValidKeyLength(16); - SecByteBlock macKey(macKeyLength); + AlignedSecByteBlock macKey(macKeyLength); // since the MAC is encrypted there is no reason to mash the passphrase for many iterations Mash(passphrase, passphraseLength, macKey, macKeyLength, 1); return new MAC(macKey, macKeyLength);