From 7d21cdd54e95a936c7b4a946a7d5739a2366769c Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Sat, 12 Aug 2017 16:14:29 -0400 Subject: Convert GCM to use runtime blocksize checking (Issue 408) GCM is still only defined for 16-byte ciphers, but this is where we need to be when we add the larger polynomials --- gcm.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'gcm.cpp') diff --git a/gcm.cpp b/gcm.cpp index 6d86bac1..6d389a1b 100644 --- a/gcm.cpp +++ b/gcm.cpp @@ -325,7 +325,13 @@ void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const BlockCipher &blockCipher = AccessBlockCipher(); blockCipher.SetKey(userKey, keylength, params); - if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE) + // GCM is only defined for 16-byte block ciphers at the moment. + // However, variable blocksize support means we have to defer + // blocksize checks to runtime after the key is set. Also see + // https://github.com/weidai11/cryptopp/issues/408. + const unsigned int blockSize = blockCipher.BlockSize(); + CRYPTOPP_ASSERT(blockSize == REQUIRED_BLOCKSIZE); + if (blockSize != REQUIRED_BLOCKSIZE) throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16"); int tableSize, i, j, k; @@ -335,7 +341,7 @@ void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const { // Avoid "parameter not used" error and suppress Coverity finding (void)params.GetIntValue(Name::TableSize(), tableSize); - tableSize = s_clmulTableSizeInBlocks * REQUIRED_BLOCKSIZE; + tableSize = s_clmulTableSizeInBlocks * blockSize; } else #elif CRYPTOPP_BOOL_ARM_PMULL_AVAILABLE @@ -343,7 +349,7 @@ void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const { // Avoid "parameter not used" error and suppress Coverity finding (void)params.GetIntValue(Name::TableSize(), tableSize); - tableSize = s_clmulTableSizeInBlocks * REQUIRED_BLOCKSIZE; + tableSize = s_clmulTableSizeInBlocks * blockSize; } else #endif @@ -359,10 +365,10 @@ void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const #endif } - m_buffer.resize(3*REQUIRED_BLOCKSIZE + tableSize); + m_buffer.resize(3*blockSize + tableSize); byte *table = MulTable(); byte *hashKey = HashKey(); - memset(hashKey, 0, REQUIRED_BLOCKSIZE); + memset(hashKey, 0, blockSize); blockCipher.ProcessBlock(hashKey); #if CRYPTOPP_BOOL_AESNI_INTRINSICS_AVAILABLE @@ -537,6 +543,13 @@ void GCM_Base::Resync(const byte *iv, size_t len) BlockCipher &cipher = AccessBlockCipher(); byte *hashBuffer = HashBuffer(); + // GCM is only defined for 16-byte block ciphers at the moment. + // However, variable blocksize support means we have to defer + // blocksize checks to runtime after the key is set. Also see + // https://github.com/weidai11/cryptopp/issues/408. + const unsigned int blockSize = cipher.BlockSize(); + CRYPTOPP_ASSERT(blockSize == REQUIRED_BLOCKSIZE); + if (len == 12) { memcpy(hashBuffer, iv, len); @@ -568,7 +581,7 @@ void GCM_Base::Resync(const byte *iv, size_t len) } if (m_state >= State_IVSet) - m_ctr.Resynchronize(hashBuffer, REQUIRED_BLOCKSIZE); + m_ctr.Resynchronize(hashBuffer, blockSize); else m_ctr.SetCipherWithIV(cipher, hashBuffer); -- cgit v1.2.1