1 // kalyna.h - written and placed in the public domain by Jeffrey Walton
2 //            Based on public domain code by Keru Kuro.
3 
4 /// \file kalyna.h
5 /// \brief Classes for the Kalyna block cipher
6 /// \details The Crypto++ implementation relied upon three sources. First was Oliynykov, Gorbenko, Kazymyrov,
7 ///   Ruzhentsev, Kuznetsov, Gorbenko, Dyrda, Dolgov, Pushkaryov, Mordvinov and Kaidalov's "A New Encryption
8 ///   Standard of Ukraine: The Kalyna Block Cipher" (http://eprint.iacr.org/2015/650.pdf). Second was Roman
9 ///   Oliynykov and Oleksandr Kazymyrov's GitHub with the reference implementation
10 ///   (http://github.com/Roman-Oliynykov/Kalyna-reference). The third resource was Keru Kuro's implementation
11 ///   of Kalyna in CppCrypto (http://sourceforge.net/projects/cppcrypto/). Kuro has an outstanding
12 ///   implementation that performed better than the reference implementation and our initial attempts.
13 
14 #ifndef CRYPTOPP_KALYNA_H
15 #define CRYPTOPP_KALYNA_H
16 
17 #include "config.h"
18 #include "seckey.h"
19 #include "secblock.h"
20 
21 NAMESPACE_BEGIN(CryptoPP)
22 
23 /// \brief Kalyna-128 block cipher information
24 /// \since Crypto++ 6.0
25 struct CRYPTOPP_NO_VTABLE Kalyna128_Info : public FixedBlockSize<16>, VariableKeyLength<16, 16, 32>
26 {
StaticAlgorithmNameKalyna128_Info27     static const char* StaticAlgorithmName()
28     {
29         // Format is Cipher-Blocksize(Keylength)
30         return "Kalyna-128";
31     }
32 };
33 
34 /// \brief Kalyna-256 block cipher information
35 /// \since Crypto++ 6.0
36 struct CRYPTOPP_NO_VTABLE Kalyna256_Info : public FixedBlockSize<32>, VariableKeyLength<32, 32, 64>
37 {
StaticAlgorithmNameKalyna256_Info38     static const char* StaticAlgorithmName()
39     {
40         // Format is Cipher-Blocksize(Keylength)
41         return "Kalyna-256";
42     }
43 };
44 
45 /// \brief Kalyna-512 block cipher information
46 /// \since Crypto++ 6.0
47 struct CRYPTOPP_NO_VTABLE Kalyna512_Info : public FixedBlockSize<64>, FixedKeyLength<64>
48 {
StaticAlgorithmNameKalyna512_Info49     static const char* StaticAlgorithmName()
50     {
51         // Format is Cipher-Blocksize(Keylength)
52         return "Kalyna-512";
53     }
54 };
55 
56 /// \brief Kalyna block cipher base class
57 /// \since Crypto++ 6.0
58 class CRYPTOPP_NO_VTABLE Kalyna_Base
59 {
60 public:
~Kalyna_Base()61     virtual ~Kalyna_Base() {}
62 
63 protected:
64     typedef SecBlock<word64, AllocatorWithCleanup<word64, true> > AlignedSecBlock64;
65     mutable AlignedSecBlock64 m_wspace;  // work space
66     AlignedSecBlock64         m_mkey;    // master key
67     AlignedSecBlock64         m_rkeys;   // round keys
68     unsigned int     m_kl, m_nb, m_nk;   // number 64-bit blocks and keys
69 };
70 
71 /// \brief Kalyna 128-bit block cipher
72 /// \details Kalyna128 provides 128-bit block size. The valid key sizes are 128-bit and 256-bit.
73 /// \since Crypto++ 6.0
74 class Kalyna128 : public Kalyna128_Info, public BlockCipherDocumentation
75 {
76 public:
77     class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl<Kalyna128_Info>
78     {
79     public:
80         /// \brief Provides the name of this algorithm
81         /// \return the standard algorithm name
82         /// \details If the object is unkeyed, then the generic name "Kalyna" is returned
83         ///   to the caller. If the algorithm is keyed, then a two or three part name is
84         ///   returned to the caller. The name follows DSTU 7624:2014, where block size is
85         ///   provided first and then key length. The library uses a dash to identify block size
86         ///   and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna
87         ///   with a 128-bit block size and a 256-bit key length. If a mode is associated
88         ///   with the object, then it follows as expected. For example, Kalyna-128(256)/ECB.
89         ///   DSTU is a little more complex with more parameters, dashes, underscores, but the
90         ///   library does not use the delimiters or full convention.
AlgorithmName()91         std::string AlgorithmName() const {
92             return std::string("Kalyna-128") + "(" + IntToString(m_kl*8) + ")";
93         }
94 
95         /// \brief Provides input and output data alignment for optimal performance.
96         /// \return the input data alignment that provides optimal performance
97         /// \sa GetAlignment() and OptimalBlockSize()
OptimalDataAlignment()98         unsigned int OptimalDataAlignment() const {
99             return GetAlignmentOf<word64>();
100         }
101 
102     protected:
103         void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &params);
104         void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
105 
106     protected:
107         void SetKey_22(const word64 key[2]);
108         void SetKey_24(const word64 key[4]);
109         void ProcessBlock_22(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
110         void ProcessBlock_24(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
111     };
112 
113     typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
114     typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
115 };
116 
117 /// \brief Kalyna 256-bit block cipher
118 /// \details Kalyna256 provides 256-bit block size. The valid key sizes are 256-bit and 512-bit.
119 /// \since Crypto++ 6.0
120 class Kalyna256 : public Kalyna256_Info, public BlockCipherDocumentation
121 {
122 public:
123     class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl<Kalyna256_Info>
124     {
125     public:
126         /// \brief Provides the name of this algorithm
127         /// \return the standard algorithm name
128         /// \details If the object is unkeyed, then the generic name "Kalyna" is returned
129         ///   to the caller. If the algorithm is keyed, then a two or three part name is
130         ///   returned to the caller. The name follows DSTU 7624:2014, where block size is
131         ///   provided first and then key length. The library uses a dash to identify block size
132         ///   and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna
133         ///   with a 128-bit block size and a 256-bit key length. If a mode is associated
134         ///   with the object, then it follows as expected. For example, Kalyna-128(256)/ECB.
135         ///   DSTU is a little more complex with more parameters, dashes, underscores, but the
136         ///   library does not use the delimiters or full convention.
AlgorithmName()137         std::string AlgorithmName() const {
138             return std::string("Kalyna-256") + "(" + IntToString(m_kl*8) + ")";
139         }
140 
141         /// \brief Provides input and output data alignment for optimal performance.
142         /// \return the input data alignment that provides optimal performance
143         /// \sa GetAlignment() and OptimalBlockSize()
OptimalDataAlignment()144         unsigned int OptimalDataAlignment() const {
145             return GetAlignmentOf<word64>();
146         }
147 
148     protected:
149         void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &params);
150         void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
151 
152     protected:
153         void SetKey_44(const word64 key[4]);
154         void SetKey_48(const word64 key[8]);
155         void ProcessBlock_44(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
156         void ProcessBlock_48(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
157     };
158 
159     typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
160     typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
161 };
162 
163 /// \brief Kalyna 512-bit block cipher
164 /// \details Kalyna512 provides 512-bit block size. The valid key size is 512-bit.
165 /// \since Crypto++ 6.0
166 class Kalyna512 : public Kalyna512_Info, public BlockCipherDocumentation
167 {
168 public:
169     class CRYPTOPP_NO_VTABLE Base : public Kalyna_Base, public BlockCipherImpl<Kalyna512_Info>
170     {
171     public:
172         /// \brief Provides the name of this algorithm
173         /// \return the standard algorithm name
174         /// \details If the object is unkeyed, then the generic name "Kalyna" is returned
175         ///   to the caller. If the algorithm is keyed, then a two or three part name is
176         ///   returned to the caller. The name follows DSTU 7624:2014, where block size is
177         ///   provided first and then key length. The library uses a dash to identify block size
178         ///   and parenthesis to identify key length. For example, Kalyna-128(256) is Kalyna
179         ///   with a 128-bit block size and a 256-bit key length. If a mode is associated
180         ///   with the object, then it follows as expected. For example, Kalyna-128(256)/ECB.
181         ///   DSTU is a little more complex with more parameters, dashes, underscores, but the
182         ///   library does not use the delimiters or full convention.
AlgorithmName()183         std::string AlgorithmName() const {
184             return std::string("Kalyna-512") + "(" + IntToString(m_kl*8) + ")";
185         }
186 
187         /// \brief Provides input and output data alignment for optimal performance.
188         /// \return the input data alignment that provides optimal performance
189         /// \sa GetAlignment() and OptimalBlockSize()
OptimalDataAlignment()190         unsigned int OptimalDataAlignment() const {
191             return GetAlignmentOf<word64>();
192         }
193 
194     protected:
195         void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &params);
196         void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
197 
198     protected:
199         void SetKey_88(const word64 key[8]);
200         void ProcessBlock_88(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
201     };
202 
203     typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
204     typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
205 };
206 
207 typedef Kalyna128::Encryption Kalyna128Encryption;
208 typedef Kalyna128::Decryption Kalyna128Decryption;
209 
210 typedef Kalyna256::Encryption Kalyna256Encryption;
211 typedef Kalyna256::Decryption Kalyna256Decryption;
212 
213 typedef Kalyna512::Encryption Kalyna512Encryption;
214 typedef Kalyna512::Decryption Kalyna512Decryption;
215 
216 NAMESPACE_END
217 
218 #endif  // CRYPTOPP_KALYNA_H
219