diff --git a/TestVectors/kalyna.txt b/TestVectors/kalyna.txt index 92157d49..3e3c8ff9 100644 --- a/TestVectors/kalyna.txt +++ b/TestVectors/kalyna.txt @@ -1,69 +1,61 @@ AlgorithmType: SymmetricCipher -Name: Kalyna/ECB +Name: Kalyna-128/ECB Source: Kalyna reference implementation Comment: Kalyna 128-bit key, 128-bit block Key: 000102030405060708090A0B0C0D0E0F -BlockSize: 16 Plaintext: 101112131415161718191A1B1C1D1E1F Ciphertext: 81BF1C7D779BAC20E1C9EA39B4D2AD06 Test: Encrypt -Name: Kalyna/ECB +Name: Kalyna-128/ECB Source: Kalyna reference implementation Comment: Kalyna 256-bit key, 128-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -BlockSize: 16 Plaintext: 202122232425262728292A2B2C2D2E2F Ciphertext: 58EC3E091000158A1148F7166F334F14 Test: Encrypt -Name: Kalyna/ECB +Name: Kalyna-256/ECB Source: Kalyna reference implementation Comment: Kalyna 256-bit key, 256-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F -BlockSize: 32 Plaintext: 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F Ciphertext: F66E3D570EC92135AEDAE323DCBD2A8CA03963EC206A0D5A88385C24617FD92C Test: Encrypt -Name: Kalyna/ECB +Name: Kalyna-256/ECB Source: Kalyna reference implementation Comment: Kalyna 512-bit key, 256-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F -BlockSize: 32 Plaintext: 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F Ciphertext: 606990E9E6B7B67A4BD6D893D72268B78E02C83C3CD7E102FD2E74A8FDFE5DD9 Test: Encrypt -Name: Kalyna/ECB +Name: Kalyna-512/ECB Source: Kalyna reference implementation Comment: Kalyna 512-bit key, 512-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F -BlockSize: 64 Plaintext: 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F Ciphertext: 4A26E31B811C356AA61DD6CA0596231A67BA8354AA47F3A13E1DEEC320EB56B895D0F417175BAB662FD6F134BB15C86CCB906A26856EFEB7C5BC6472940DD9D9 Test: Encrypt -Name: Kalyna/CBC +Name: Kalyna-128/CBC Source: DSTU 7624:2014, Section B.6.1 (p.148) Comment: Kalyna 128-bit key, 128-bit block Key: 000102030405060708090A0B0C0D0E0F IV: 101112131415161718191A1B1C1D1E1F -BlockSize: 16 Plaintext: 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F Ciphertext: A73625D7BE994E85469A9FAABCEDAAB6DBC5F65DD77BB35E06BD7D1D8EAFC8624D6CB31CE189C82B8979F2936DE9BF14 Test: Encrypt -Name: Kalyna/CBC +Name: Kalyna-128/CBC Source: DSTU 7624:2014, Section B.6.3 (p.149) Comment: Kalyna 256-bit key, 128-bit block, OneAndZeros padding Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F IV: 202122232425262728292A2B2C2D2E2F -BlockSize: 16 BlockPaddingScheme: 3 # OneAndZeroPadding Plaintext: 303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D Ciphertext: 13EA15843AD14C50BC03ECEF1F43E398E4217752D3EB046AC393DACC5CA1D6FA0EB9FCEB229362B4F1565527EE3D8433 Test: Encrypt -Name: Kalyna/CBC +Name: Kalyna-256/CBC Source: DSTU 7624:2014, Section B.6.5 (p.150) Comment: Kalyna 256-bit key, 256-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F IV: 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F -BlockSize: 32 Plaintext: 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F \ 606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F \ 808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F @@ -71,13 +63,12 @@ Ciphertext: 9CDFDAA75929E7C2A5CFC1BF16B42C5AE3886D0258E8C577DC01DAF62D185FB9 \ 99B9867736B87110F5F1BC7481912C593F48FF79E2AFDFAB9F704A277EC3E557 \ B1B0A9F223DAE6ED5AF591C4F2D6FB22E48334F5E9B96B1A2EA5200F30A406CE Test: Encrypt -Name: Kalyna/CBC +Name: Kalyna-256/CBC Source: DSTU 7624:2014, Section B.6.7 (p.151) Comment: Kalyna 512-bit key, 256-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \ 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F IV: 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F -BlockSize: 32 Plaintext: 606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F \ 808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F \ A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF @@ -85,14 +76,13 @@ Ciphertext: B8A2474578C2FEBF3F94703587BD5FDC3F4A4D2F43575B6144A1E1031FB3D145 \ 2B7FD52F5E3411461DAC506869FF8D2FAEF4FEE60379AE00B33AA3EAF911645A \ F8091CD8A45D141D1FB150E5A01C1F26FF3DBD26AC4225EC7577B2CE57A5B0FF Test: Encrypt -Name: Kalyna/CBC +Name: Kalyna-512/CBC Source: DSTU 7624:2014, Section B.6.9 (p.152) Comment: Kalyna 512-bit key, 512-bit block Key: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \ 202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F IV: 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F \ 606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F -BlockSize: 64 Plaintext: 808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9F \ A0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF \ C0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF \ diff --git a/kalyna.cpp b/kalyna.cpp index 873bbd49..18d6e2c0 100644 --- a/kalyna.cpp +++ b/kalyna.cpp @@ -416,7 +416,7 @@ NAMESPACE_BEGIN(CryptoPP) // *********************** UncheckedSetKey specializations *********************** // -void Kalyna::Base::SetKey_22(const word64 key[2]) +void Kalyna128::Base::SetKey_22(const word64 key[2]) { word64 *ks = m_wspace+0, *ksc = m_wspace+2, *t1 = m_wspace+4; word64 *t2 = m_wspace+6, *k = m_wspace+8, *kswapped = m_wspace+10; @@ -491,7 +491,7 @@ void Kalyna::Base::SetKey_22(const word64 key[2]) } } -void Kalyna::Base::SetKey_24(const word64 key[4]) +void Kalyna128::Base::SetKey_24(const word64 key[4]) { word64 *ks = m_wspace+0, *ksc = m_wspace+2, *t1 = m_wspace+4, *t2 = m_wspace+6; word64 *k = m_wspace+8, *ka = m_wspace+12, *ko = m_wspace+14; @@ -592,7 +592,7 @@ void Kalyna::Base::SetKey_24(const word64 key[4]) } } -void Kalyna::Base::SetKey_44(const word64 key[4]) +void Kalyna256::Base::SetKey_44(const word64 key[4]) { word64 *ks = m_wspace+0, *ksc = m_wspace+4, *t1 = m_wspace+8; word64 *t2 = m_wspace+12, *k = m_wspace+16; @@ -695,7 +695,7 @@ void Kalyna::Base::SetKey_44(const word64 key[4]) } } -void Kalyna::Base::SetKey_48(const word64 key[8]) +void Kalyna256::Base::SetKey_48(const word64 key[8]) { word64 *ks = m_wspace+0, *ksc = m_wspace+4, *t1 = m_wspace+8, *t2 = m_wspace+12; word64 *k = m_wspace+16, *ka = m_wspace+24, *ko = m_wspace+28; @@ -817,7 +817,7 @@ void Kalyna::Base::SetKey_48(const word64 key[8]) } } -void Kalyna::Base::SetKey_88(const word64 key[8]) +void Kalyna512::Base::SetKey_88(const word64 key[8]) { word64 *ks = m_wspace+0, *ksc = m_wspace+8, *t1 = m_wspace+16; word64 *t2 = m_wspace+24, *k = m_wspace+32; @@ -932,7 +932,7 @@ void Kalyna::Base::SetKey_88(const word64 key[8]) // *********************** ProcessAndXorBlock specializations *********************** // -void Kalyna::Base::ProcessBlock_22(const word64 inBlock[2], const word64 xorBlock[2], word64 outBlock[2]) const +void Kalyna128::Base::ProcessBlock_22(const word64 inBlock[2], const word64 xorBlock[2], word64 outBlock[2]) const { word64 *t1 = m_wspace+0, *t2 = m_wspace+2, *msg = m_wspace+4; @@ -978,7 +978,7 @@ void Kalyna::Base::ProcessBlock_22(const word64 inBlock[2], const word64 xorBloc oblk(t1[0])(t1[1]); } -void Kalyna::Base::ProcessBlock_24(const word64 inBlock[2], const word64 xorBlock[2], word64 outBlock[2]) const +void Kalyna128::Base::ProcessBlock_24(const word64 inBlock[2], const word64 xorBlock[2], word64 outBlock[2]) const { word64 *t1 = m_wspace+0, *t2 = m_wspace+2, *msg = m_wspace+4; @@ -1032,7 +1032,7 @@ void Kalyna::Base::ProcessBlock_24(const word64 inBlock[2], const word64 xorBloc oblk(t1[0])(t1[1]); } -void Kalyna::Base::ProcessBlock_44(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const +void Kalyna256::Base::ProcessBlock_44(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const { word64 *t1 = m_wspace+0, *t2 = m_wspace+4, *msg = m_wspace+8; @@ -1086,7 +1086,7 @@ void Kalyna::Base::ProcessBlock_44(const word64 inBlock[4], const word64 xorBloc oblk(t1[0])(t1[1])(t1[2])(t1[3]); } -void Kalyna::Base::ProcessBlock_48(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const +void Kalyna256::Base::ProcessBlock_48(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const { word64 *t1 = m_wspace+0, *t2 = m_wspace+4, *msg = m_wspace+8; @@ -1148,7 +1148,7 @@ void Kalyna::Base::ProcessBlock_48(const word64 inBlock[4], const word64 xorBloc oblk(t1[0])(t1[1])(t1[2])(t1[3]); } -void Kalyna::Base::ProcessBlock_88(const word64 inBlock[8], const word64 xorBlock[8], word64 outBlock[8]) const +void Kalyna512::Base::ProcessBlock_88(const word64 inBlock[8], const word64 xorBlock[8], word64 outBlock[8]) const { word64 *t1 = m_wspace+0, *t2 = m_wspace+8, *msg = m_wspace+16; @@ -1212,32 +1212,16 @@ void Kalyna::Base::ProcessBlock_88(const word64 inBlock[8], const word64 xorBloc // *********************** Library routines *********************** // -void Kalyna::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +void Kalyna128::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) { + CRYPTOPP_UNUSED(params); + m_nb = static_cast(16U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + switch (keylen) { case 16: // 128 m_kl = 16; - m_blocksize = params.GetIntValueWithDefault(Name::BlockSize(), 16); - break; - case 32: // 256 - m_kl = 32; - m_blocksize = params.GetIntValueWithDefault(Name::BlockSize(), 32); - break; - case 64: // 512 - m_kl = 64; - m_blocksize = params.GetIntValueWithDefault(Name::BlockSize(), 64); - break; - default: - CRYPTOPP_ASSERT(0); - } - - m_nb = static_cast(m_blocksize / sizeof(word64)); - m_nk = static_cast(keylen / sizeof(word64)); - - switch ((m_nb << 8) | m_nk) - { - case (2 << 8) | 2: // 128 key, 128 block m_mkey.New(2); m_rkeys.New(11*2); m_wspace.New(2*6); @@ -1245,7 +1229,8 @@ void Kalyna::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const N GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 2, key, 16); SetKey_22(m_mkey.begin()); break; - case (2 << 8) | 4: // 256 key, 128 block + case 32: // 256 + m_kl = 32; m_mkey.New(4); m_rkeys.New(15*2); m_wspace.New(6*2+4); @@ -1253,36 +1238,12 @@ void Kalyna::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const N GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 4, key, 32); SetKey_24(m_mkey.begin()); break; - case (4 << 8) | 4: // 256 key, 256 block - m_mkey.New(4); - m_rkeys.New(15*4); - m_wspace.New(5*4); - - GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 4, key, 32); - SetKey_44(m_mkey.begin()); - break; - case (4 << 8) | 8: // 512 key, 256 block - m_mkey.New(8); - m_rkeys.New(19*4); - m_wspace.New(6*4+8); - - GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 8, key, 64); - SetKey_48(m_mkey.begin()); - break; - case (8 << 8) | 8: // 512 key, 512 block - m_mkey.New(8); - m_rkeys.New(19*8); - m_wspace.New(5*8); - - GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 8, key, 64); - SetKey_88(m_mkey.begin()); - break; default: CRYPTOPP_ASSERT(0); } } -void Kalyna::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +void Kalyna128::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const { // Timing attack countermeasure. see comments in Rijndael for more details const int cacheLineSize = GetCacheLineSize(); @@ -1304,6 +1265,56 @@ void Kalyna::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, ProcessBlock_24(reinterpret_cast(inBlock), reinterpret_cast(xorBlock), reinterpret_cast(outBlock)); break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna256::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_nb = static_cast(32U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + switch (keylen) + { + case 32: // 256 + m_kl = 32; + m_mkey.New(4); + m_rkeys.New(15*4); + m_wspace.New(5*4); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 4, key, 32); + SetKey_44(m_mkey.begin()); + break; + case 64: // 512 + m_kl = 64; + m_mkey.New(8); + m_rkeys.New(19*4); + m_wspace.New(6*4+8); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 8, key, 64); + SetKey_48(m_mkey.begin()); + break; + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna256::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Timing attack countermeasure. see comments in Rijndael for more details + const int cacheLineSize = GetCacheLineSize(); + volatile word64 _u = 0; + word64 u = _u; + + const byte* p = reinterpret_cast(KalynaTab::S); + for (unsigned int i=0; i<256; i+=cacheLineSize) + u ^= *reinterpret_cast(p+i); + m_wspace[0] = u; + + switch ((m_nb << 8) | m_nk) + { case (4 << 8) | 4: ProcessBlock_44(reinterpret_cast(inBlock), reinterpret_cast(xorBlock), reinterpret_cast(outBlock)); @@ -1312,13 +1323,50 @@ void Kalyna::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, ProcessBlock_48(reinterpret_cast(inBlock), reinterpret_cast(xorBlock), reinterpret_cast(outBlock)); break; - case (8 << 8) | 8: - ProcessBlock_88(reinterpret_cast(inBlock), - reinterpret_cast(xorBlock), reinterpret_cast(outBlock)); + default: + CRYPTOPP_ASSERT(0); + } +} + +void Kalyna512::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms) +{ + CRYPTOPP_UNUSED(params); + m_nb = static_cast(64U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + switch (keylen) + { + case 64: // 512 + m_kl = 64; + m_nb = static_cast(64U / sizeof(word64)); + m_nk = static_cast(keylen / sizeof(word64)); + + m_mkey.New(8); + m_rkeys.New(19*8); + m_wspace.New(5*8); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_mkey.begin(), 8, key, 64); + SetKey_88(m_mkey.begin()); break; default: CRYPTOPP_ASSERT(0); } } +void Kalyna512::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + // Timing attack countermeasure. see comments in Rijndael for more details + const int cacheLineSize = GetCacheLineSize(); + volatile word64 _u = 0; + word64 u = _u; + + const byte* p = reinterpret_cast(KalynaTab::S); + for (unsigned int i=0; i<256; i+=cacheLineSize) + u ^= *reinterpret_cast(p+i); + m_wspace[0] = u; + + ProcessBlock_88(reinterpret_cast(inBlock), + reinterpret_cast(xorBlock), reinterpret_cast(outBlock)); +} + NAMESPACE_END diff --git a/kalyna.h b/kalyna.h index 28fe0cfb..1084eca8 100644 --- a/kalyna.h +++ b/kalyna.h @@ -20,81 +20,59 @@ NAMESPACE_BEGIN(CryptoPP) -/// \class Kalyna_Info -/// \brief Kalyna block cipher information -/// \details Kalyna key sizes and block sizes do not fit well into the library. Rather -/// than using VariableKeyLength (which is wrong) or using a GeometricKeyLength -/// (a new class), we just unroll it here. Note that the step size, Q, is still -/// wrong for this implementation. +/// \class Kalyna128_Info +/// \brief Kalyna-128 block cipher information /// \since Crypto++ 6.0 -struct Kalyna_Info : public VariableBlockSize<16, 16, 64> +struct Kalyna128_Info : public FixedBlockSize<16>, VariableKeyLength<16, 16, 32> { - CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "Kalyna";} - - /// \brief The minimum key length used by the algorithm provided as a constant - /// \details MIN_KEYLENGTH is provided in bytes, not bits - CRYPTOPP_CONSTANT(MIN_KEYLENGTH=16) - /// \brief The maximum key length used by the algorithm provided as a constant - /// \details MIN_KEYLENGTH is provided in bytes, not bits - CRYPTOPP_CONSTANT(MAX_KEYLENGTH=64) - /// \brief The default key length used by the algorithm provided as a constant - /// \details MIN_KEYLENGTH is provided in bytes, not bits - CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=16) - /// \brief The default IV requirements for the algorithm provided as a constant - /// \details The default value is NOT_RESYNCHRONIZABLE. See IV_Requirement - /// in cryptlib.h for allowed values. - CRYPTOPP_CONSTANT(IV_REQUIREMENT=SimpleKeyingInterface::UNIQUE_IV) - /// \brief The default initialization vector length for the algorithm provided as a constant - /// \details IV_LENGTH is provided in bytes, not bits. Kalyna has two different block sizes for - /// each key length. This function returns the default block size for the defult key length. - CRYPTOPP_CONSTANT(IV_LENGTH=16) - /// \brief Provides a valid key length for the algorithm provided by a static function. - /// \param keylength the size of the key, in bytes - /// \details The key length depends on the block size. For each block size, 128, 256 and 512, - /// the key length can be either the block size or twice the block size. That means the - /// valid key lengths are 126, 256, 512 and 1024. Additionally, it means a key length of, - /// say, 32 could be used with either 128-block size or 256-block size. - CRYPTOPP_STATIC_CONSTEXPR size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength) + static const char* StaticAlgorithmName() { - return (keylength >= 64) ? 64 : - (keylength >= 32) ? 32 : 16; + // Format is Cipher-Blocksize(Keylength) + return "Kalyna-128"; } +}; - /// \brief Validates the blocksize for Kalyna. - /// \param blocksize the candidate blocksize - /// \param alg an Algorithm object used if the blocksize is invalid - /// \throws InvalidBlockSize if the blocksize is invalid - /// \details ThrowIfInvalidBlockSize() validates the blocksize and throws if invalid. - inline void ThrowIfInvalidBlockSize(int blocksize, const Algorithm *alg) +/// \class Kalyna256_Info +/// \brief Kalyna-256 block cipher information +/// \since Crypto++ 6.0 +struct Kalyna256_Info : public FixedBlockSize<32>, VariableKeyLength<32, 32, 64> +{ + static const char* StaticAlgorithmName() { - if ( blocksize != 16 && blocksize != 32 && blocksize != 64) - throw InvalidBlockSize(alg ? alg->AlgorithmName() : std::string("VariableBlockSize"), blocksize); + // Format is Cipher-Blocksize(Keylength) + return "Kalyna-256"; } +}; - /// \brief Validates the blocksize for Kalyna. - /// \param keylength the key length of the cipher - /// \param blocksize the candidate blocksize - /// \param alg an Algorithm object used if the blocksize is invalid - /// \throws InvalidBlockSize if the blocksize is invalid - /// \details ThrowIfInvalidBlockSize() validates the blocksize under a key and throws if invalid. - inline void ThrowIfInvalidBlockSize(int keylength, int blocksize, const Algorithm *alg) +/// \class Kalyna512_Info +/// \brief Kalyna-512 block cipher information +/// \since Crypto++ 6.0 +struct Kalyna512_Info : public FixedBlockSize<64>, FixedKeyLength<64> +{ + static const char* StaticAlgorithmName() { - if ( ((keylength == 16) && (blocksize != 16)) || - ((keylength == 32) && (blocksize != 32 && blocksize != 64)) || - ((keylength == 64) && (blocksize != 32 && blocksize != 64)) ) - { - throw InvalidBlockSize(alg ? alg->AlgorithmName() : std::string("VariableBlockSize"), blocksize); - } + // Format is Cipher-Blocksize(Keylength) + return "Kalyna-512"; } }; /// \class Kalyna /// \brief Kalyna block cipher /// \since Crypto++ 6.0 -class Kalyna : public Kalyna_Info, public BlockCipherDocumentation +class Kalyna_Base +{ +protected: + typedef SecBlock > AlignedSecBlock64; + mutable AlignedSecBlock64 m_wspace; // work space + AlignedSecBlock64 m_mkey; // master key + AlignedSecBlock64 m_rkeys; // round keys + unsigned int m_kl, m_nb, m_nk; // key length, number 64-bit blocks and keys +}; + +class Kalyna128 : public Kalyna128_Info, public BlockCipherDocumentation { public: - class CRYPTOPP_NO_VTABLE Base : public VariableBlockCipherImpl + class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl { public: /// \brief Provides the name of this algorithm @@ -109,7 +87,7 @@ public: /// DSTU is a little more complex with more parameters, dashes, underscores, but the /// library does not use the delimiters or full convention. std::string AlgorithmName() const { - return m_blocksize ? "Kalyna-" + IntToString(m_blocksize*8) + "(" + IntToString(m_kl*8) + ")" : StaticAlgorithmName(); + return std::string("Kalyna-128") + "(" + IntToString(m_kl*8) + ")"; } unsigned int OptimalDataAlignment() const { @@ -121,38 +99,93 @@ public: void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; protected: - // Visual Studio and C2910: 'Kalyna::Base::SetKey_Template': cannot be explicitly specialized - //template - // void SetKey_Template(const word64 key[NK]); void SetKey_22(const word64 key[2]); void SetKey_24(const word64 key[4]); - void SetKey_44(const word64 key[4]); - void SetKey_48(const word64 key[8]); - void SetKey_88(const word64 key[8]); - - // Visual Studio and C2910: 'Kalyna::Base::ProcessBlock_Template': cannot be explicitly specialized - //template - // void ProcessBlock_Template(const word64 inBlock[NB], const word64 outBlock[NB]) const; void ProcessBlock_22(const word64 inBlock[2], const word64 xorBlock[2], word64 outBlock[2]) const; void ProcessBlock_24(const word64 inBlock[2], const word64 xorBlock[2] ,word64 outBlock[2]) const; - void ProcessBlock_44(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const; - void ProcessBlock_48(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const; - void ProcessBlock_88(const word64 inBlock[8], const word64 xorBlock[8], word64 outBlock[8]) const; - - private: - typedef SecBlock > AlignedSecBlock64; - mutable AlignedSecBlock64 m_wspace; // work space - AlignedSecBlock64 m_mkey; // master key - AlignedSecBlock64 m_rkeys; // round keys - unsigned int m_kl, m_nb, m_nk; // key length, number 64-bit blocks and keys }; typedef BlockCipherFinal Encryption; typedef BlockCipherFinal Decryption; }; -typedef Kalyna::Encryption KalynaEncryption; -typedef Kalyna::Decryption KalynaDecryption; +class Kalyna256 : public Kalyna256_Info, public BlockCipherDocumentation +{ +public: + class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl + { + public: + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + /// \details If the object is unkeyed, then the generic name "Kalyna" is returned + /// to the caller. If the algorithm is keyed, then a two or three part name is + /// returned to the caller. The name follows DSTU 7624:2014, where block size is + /// provided first and then key length. The library uses a dash to identify block size + /// and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna + /// with a 128-bit block size and a 256-bit key length. If a mode is associated + /// with the object, then it follows as expected. For example, Kalyna-128(256)/ECB. + /// DSTU is a little more complex with more parameters, dashes, underscores, but the + /// library does not use the delimiters or full convention. + std::string AlgorithmName() const { + return std::string("Kalyna-256") + "(" + IntToString(m_kl*8) + ")"; + } + + unsigned int OptimalDataAlignment() const { + return GetAlignmentOf(); + } + + protected: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + void SetKey_44(const word64 key[4]); + void SetKey_48(const word64 key[8]); + void ProcessBlock_44(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const; + void ProcessBlock_48(const word64 inBlock[4], const word64 xorBlock[4], word64 outBlock[4]) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +class Kalyna512 : Kalyna512_Info, public BlockCipherDocumentation +{ +public: + class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl + { + public: + /// \brief Provides the name of this algorithm + /// \return the standard algorithm name + /// \details If the object is unkeyed, then the generic name "Kalyna" is returned + /// to the caller. If the algorithm is keyed, then a two or three part name is + /// returned to the caller. The name follows DSTU 7624:2014, where block size is + /// provided first and then key length. The library uses a dash to identify block size + /// and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna + /// with a 128-bit block size and a 256-bit key length. If a mode is associated + /// with the object, then it follows as expected. For example, Kalyna-128(256)/ECB. + /// DSTU is a little more complex with more parameters, dashes, underscores, but the + /// library does not use the delimiters or full convention. + std::string AlgorithmName() const { + return std::string("Kalyna-512") + "(" + IntToString(m_kl*8) + ")"; + } + + unsigned int OptimalDataAlignment() const { + return GetAlignmentOf(); + } + + protected: + void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + void SetKey_88(const word64 key[8]); + void ProcessBlock_88(const word64 inBlock[8], const word64 xorBlock[8], word64 outBlock[8]) const; + }; + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; NAMESPACE_END diff --git a/nacl.h b/nacl.h index 43b5d8b2..4dd909c4 100644 --- a/nacl.h +++ b/nacl.h @@ -229,7 +229,7 @@ int crypto_box_open_afternm(uint8_t *m,const uint8_t *c,uint64_t d,const uint8_t /// \returns 0 on success, non-0 otherwise /// \warning This version of crypto_box() does not check for small order elements. It should not /// be used in new software. -/// \sa NaCl crypto_box documentation, +/// \sa NaCl crypto_box documentation, /// May the Fourth Be With You: A Microarchitectural /// Side Channel Attack on Several Real-World Applications of Curve25519, /// libsodium commit @@ -253,7 +253,7 @@ int crypto_box_unchecked(uint8_t *c,const uint8_t *m,uint64_t d,const uint8_t *n /// \returns 0 on success, non-0 otherwise /// \warning This version of crypto_box_open() does not check for small order elements. It should not /// be used in new software. -/// \sa NaCl crypto_box documentation, +/// \sa NaCl crypto_box documentation, /// May the Fourth Be With You: A Microarchitectural /// Side Channel Attack on Several Real-World Applications of Curve25519, /// libsodium commit @@ -275,7 +275,7 @@ int crypto_box_open_unchecked(uint8_t *m,const uint8_t *c,uint64_t d,const uint8 /// \returns 0 on success, non-0 otherwise /// \warning This version of crypto_box_beforenm() does not check for small order elements. It should not /// be used in new software. -/// \sa NaCl crypto_box documentation, +/// \sa NaCl crypto_box documentation, /// May the Fourth Be With You: A Microarchitectural /// Side Channel Attack on Several Real-World Applications of Curve25519, /// libsodium commit diff --git a/regtest2.cpp b/regtest2.cpp index 7cc03709..b5bf18b0 100644 --- a/regtest2.cpp +++ b/regtest2.cpp @@ -143,9 +143,15 @@ void RegisterFactories2() RegisterSymmetricCipherDefaultFactories >(); RegisterSymmetricCipherDefaultFactories >(); - RegisterSymmetricCipherDefaultFactories >(); // Test Vectors - RegisterSymmetricCipherDefaultFactories >(); // Test Vectors - RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Test Vectors + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks + RegisterSymmetricCipherDefaultFactories >(); // Benchmarks RegisterSymmetricCipherDefaultFactories >(); // Test Vectors RegisterSymmetricCipherDefaultFactories >(); // Test Vectors diff --git a/seckey.h b/seckey.h index 74e1ac15..a417dcf4 100644 --- a/seckey.h +++ b/seckey.h @@ -138,123 +138,6 @@ protected: } }; -/// \class VariableBlockSize -/// \brief Inherited by algorithms with variable blocksize -/// \tparam D Default blocksize -/// \tparam N Minimum blocksize -/// \tparam M Maximum blocksize -template // use INT_MAX here because enums are treated as signed ints -class VariableBlockSize -{ -public: - /// \brief The default blocksize for the algorithm provided as a constant. - CRYPTOPP_CONSTANT(DEFAULT_BLOCKSIZE = D) - /// \brief The minimum blocksize for the algorithm provided as a constant. - CRYPTOPP_CONSTANT(MIN_BLOCKSIZE = N) - /// \brief The maximum blocksize for the algorithm provided as a constant. - CRYPTOPP_CONSTANT(MAX_BLOCKSIZE = M) - /// \brief The default block size for the algorithm provided by a static function. - /// \param blocksize the block size, in bytes - /// \details The default implementation returns BLOCKSIZE. blocksize is unused - /// in the default implementation. - CRYPTOPP_STATIC_CONSTEXPR size_t CRYPTOPP_API StaticGetValidBlockSize(size_t blocksize) - { - return CRYPTOPP_UNUSED(blocksize), static_cast(DEFAULT_BLOCKSIZE); - } - /// \brief The default block size under a key provided by a static function. - /// \param keylength the size of the key, in bytes - /// \param blocksize the block size, in bytes - /// \details The default implementation returns BLOCKSIZE. blocksize is unused - /// in the default implementation. - CRYPTOPP_STATIC_CONSTEXPR size_t CRYPTOPP_API StaticGetValidBlockSize(size_t keylength, size_t blocksize) - { - return CRYPTOPP_UNUSED(keylength), CRYPTOPP_UNUSED(blocksize), static_cast(DEFAULT_BLOCKSIZE); - } - -protected: - /// \brief Validates the blocksize for an algorithm. - /// \param blocksize the candidate blocksize - /// \param alg an Algorithm object used if the blocksize is invalid - /// \throws InvalidBlockSize if the blocksize is invalid - /// \details ThrowIfInvalidBlockSize() validates the blocksize and throws if invalid. - inline void ThrowIfInvalidBlockSize(int blocksize, const Algorithm *alg) - { - if (M == INT_MAX) // Coverity and result_independent_of_operands - { - if (blocksize < MIN_BLOCKSIZE) - throw InvalidBlockSize(alg ? alg->AlgorithmName() : std::string("VariableBlockSize"), blocksize); - } - else - { - if (blocksize < MIN_BLOCKSIZE || blocksize > MAX_BLOCKSIZE) - throw InvalidBlockSize(alg ? alg->AlgorithmName() : std::string("VariableBlockSize"), blocksize); - } - } - - /// \brief Validates the blocksize for an algorithm - /// \param param the candidate blocksize - /// \param alg an Algorithm object used if the blocksize is invalid - /// \returns the blocksize for the algorithm - /// \throws InvalidBlockSize if the blocksize is invalid - /// \details GetBlockSizeAndThrowIfInvalid() validates the blocksize and throws if invalid. - inline unsigned int GetBlockSizeAndThrowIfInvalid(const NameValuePairs ¶m, const Algorithm *alg) - { - int keylength = param.GetIntValueWithDefault("KeySize", 0); - int blocksize = param.GetIntValueWithDefault("BlockSize", DEFAULT_BLOCKSIZE); - if (keylength > 0) - ThrowIfInvalidBlockSize(keylength, blocksize, alg); - else - ThrowIfInvalidBlockSize(blocksize, alg); - return static_cast(blocksize); - } - - /// Provides the block size of the cipher - /// \return the block size, in bytes - /// \details The sematics of BlockSize() is return DEFAULT_BLOCKSIZE if the default blocksize - /// is in effect. If the blocksize has changed, then the value returned is the BlockSize() - /// parameter used during SetKey(). - /// \details DEFAULT_BLOCKSIZE should be paired with DEFAULT_KEYLENGTH, and it is the same as - /// BLOCKSIZE in a FixedBlockSize cipher. - virtual unsigned int BlockSize() const =0; - - /// Provides the minimum block size of the cipher - /// \return the minimum block size, in bytes - /// \details MinBlockSize() returns the smallest blocksize a cipher can use. The size can - /// be affected by the key length. For example, Threefish has key sizes of 256, 512 and 1024 bits, - /// and the blocksize follows the key length. If a 512-bit key is used, then the block size is 512 - /// bits. Once keyed, the minimum block size of 256 is not accurate, nor is a block size of 1024 bit. - virtual unsigned int MinBlockSize() const - { return MIN_BLOCKSIZE; } - - /// Provides the maximum block size of the cipher - /// \return the maximum block size, in bytes - /// \details MaxBlockSize() returns the largest blocksize a cipher can use. The size can - /// be affected by the key length. For example, Threefish has key sizes of 256, 512 and 1024 bits, - /// and the blocksize follows the key length. If a 512-bit key is used, then the block size is 512 - /// bits. Once keyed, the minimum block size of 256 is not accurate, nor is a block size of 1024 bit. - virtual unsigned int MaxBlockSize() const - { return MAX_BLOCKSIZE; } - - /// Provides the initialization vector length of the cipher - /// \return the initialization vector length, in bytes - /// \details The sematics of IVSize() is return IV_LENGTH if the default blocksize is - /// in effect. If the blocksize has changed, then the default implentation returns the value of - /// the BlockSize() parameter used during SetKey(). - /// \details Derived classes may override the behavior such that a different value is returned. - /// This may happen with a cipher that requires an IV that is twice the block size. - virtual unsigned int IVSize() const =0; - - /// \brief Provides the minimum size of an IV - /// \return minimal length of IVs accepted by this cipher, in bytes - virtual unsigned int MinIVLength() const - { return MIN_BLOCKSIZE; } - - /// \brief Provides the maximum size of an IV - /// \return maximal length of IVs accepted by this cipher, in bytes - virtual unsigned int MaxIVLength() const - { return MAX_BLOCKSIZE; } -}; - // ************** key length *************** /// \class FixedKeyLength @@ -456,41 +339,6 @@ public: unsigned int BlockSize() const {return this->BLOCKSIZE;} }; -/// \class VariableBlockCipherImpl -/// \brief Provides a base implementation of Algorithm and SimpleKeyingInterface for block ciphers with varibale block sizes -/// \tparam INFO a SimpleKeyingInterface derived class -/// \tparam BASE a SimpleKeyingInterface derived class -/// \details VariableBlockCipherImpl() provides a default implementation for block ciphers with varibale block sizes using AlgorithmImpl() -/// and SimpleKeyingInterfaceImpl(). -/// \sa Algorithm(), SimpleKeyingInterface(), AlgorithmImpl(), SimpleKeyingInterfaceImpl() -template -class CRYPTOPP_NO_VTABLE VariableBlockCipherImpl : public AlgorithmImpl > > -{ -public: - VariableBlockCipherImpl() : m_blocksize(0), m_ivlength(0) {} - VariableBlockCipherImpl(unsigned int blockSize) : m_blocksize(blockSize), m_ivlength(blockSize) {} - VariableBlockCipherImpl(unsigned int blockSize, unsigned int ivLength) : m_blocksize(blockSize), m_ivlength(ivLength) {} - - /// Provides the block size of the algorithm - /// \returns the block size, in bytes - unsigned int BlockSize() const { - return m_blocksize ? m_blocksize : - static_cast(this->DEFAULT_BLOCKSIZE); - } - - /// Provides the initialization vector length of the algorithm - /// \returns the initialization vector length, in bytes - unsigned int IVSize() const { - if (!this->IsResynchronizable()) - throw NotImplemented(this->GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization"); - return m_ivlength ? m_ivlength : - static_cast(this->IV_LENGTH); - } - -protected: - unsigned int m_blocksize, m_ivlength; -}; - /// \class BlockCipherFinal /// \brief Provides class member functions to key a block cipher /// \tparam DIR a CipherDir diff --git a/tweetnacl.cpp b/tweetnacl.cpp index afe7cd48..8348c3ed 100644 --- a/tweetnacl.cpp +++ b/tweetnacl.cpp @@ -431,7 +431,7 @@ static int has_small_order(const uint8_t s[32]) { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; CRYPTOPP_COMPILE_ASSERT(12 == COUNTOF(blacklist)); - + uint8_t c[12] = { 0 }; for (size_t j = 0; j < 32; j++) { for (size_t i = 0; i < COUNTOF(blacklist); i++) { diff --git a/validat1.cpp b/validat1.cpp index d3eafea2..9b1bd8e3 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -2082,7 +2082,7 @@ bool TestModeIV(SymmetricCipher &e, SymmetricCipher &d) const int BUF_SIZE=20480U; AlignedSecByteBlock plaintext(BUF_SIZE); - for (unsigned int i=1; i<20480; i*=2) + for (unsigned int i=1; i