1// seckey.h - written and placed in the public domain by Wei Dai
2
3// This file contains helper classes/functions for implementing secret key algorithms.
4
5#ifndef CRYPTOPP_SECKEY_H
6#define CRYPTOPP_SECKEY_H
7
8#include "cryptlib.h"
9#include "misc.h"
10#include "simple.h"
11
12NAMESPACE_BEGIN(CryptoPP)
13
14inline CipherDir ReverseCipherDir(CipherDir dir)
15{
16	return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
17}
18
19//! to be inherited by block ciphers with fixed block size
20template <unsigned int N>
21class FixedBlockSize
22{
23public:
24	CRYPTOPP_CONSTANT(BLOCKSIZE = N)
25};
26
27// ************** rounds ***************
28
29//! to be inherited by ciphers with fixed number of rounds
30template <unsigned int R>
31class FixedRounds
32{
33public:
34	CRYPTOPP_CONSTANT(ROUNDS = R)
35};
36
37//! to be inherited by ciphers with variable number of rounds
38template <unsigned int D, unsigned int N=1, unsigned int M=INT_MAX>		// use INT_MAX here because enums are treated as signed ints
39class VariableRounds
40{
41public:
42	CRYPTOPP_CONSTANT(DEFAULT_ROUNDS = D)
43	CRYPTOPP_CONSTANT(MIN_ROUNDS = N)
44	CRYPTOPP_CONSTANT(MAX_ROUNDS = M)
45	static unsigned int StaticGetDefaultRounds(size_t keylength) {return DEFAULT_ROUNDS;}
46
47protected:
48	inline void ThrowIfInvalidRounds(int rounds, const Algorithm *alg)
49	{
50		if (rounds < MIN_ROUNDS || rounds > MAX_ROUNDS)
51			throw InvalidRounds(alg->AlgorithmName(), rounds);
52	}
53
54	inline unsigned int GetRoundsAndThrowIfInvalid(const NameValuePairs &param, const Algorithm *alg)
55	{
56		int rounds = param.GetIntValueWithDefault("Rounds", DEFAULT_ROUNDS);
57		ThrowIfInvalidRounds(rounds, alg);
58		return (unsigned int)rounds;
59	}
60};
61
62// ************** key length ***************
63
64//! to be inherited by keyed algorithms with fixed key length
65template <unsigned int N, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE, unsigned int IV_L = 0>
66class FixedKeyLength
67{
68public:
69	CRYPTOPP_CONSTANT(KEYLENGTH=N)
70	CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N)
71	CRYPTOPP_CONSTANT(MAX_KEYLENGTH=N)
72	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=N)
73	CRYPTOPP_CONSTANT(IV_REQUIREMENT = IV_REQ)
74	CRYPTOPP_CONSTANT(IV_LENGTH = IV_L)
75	static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t) {return KEYLENGTH;}
76};
77
78/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1)
79template <unsigned int D, unsigned int N, unsigned int M, unsigned int Q = 1, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE, unsigned int IV_L = 0>
80class VariableKeyLength
81{
82	// make these private to avoid Doxygen documenting them in all derived classes
83	CRYPTOPP_COMPILE_ASSERT(Q > 0);
84	CRYPTOPP_COMPILE_ASSERT(N % Q == 0);
85	CRYPTOPP_COMPILE_ASSERT(M % Q == 0);
86	CRYPTOPP_COMPILE_ASSERT(N < M);
87	CRYPTOPP_COMPILE_ASSERT(D >= N);
88	CRYPTOPP_COMPILE_ASSERT(M >= D);
89
90public:
91	CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N)
92	CRYPTOPP_CONSTANT(MAX_KEYLENGTH=M)
93	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=D)
94	CRYPTOPP_CONSTANT(KEYLENGTH_MULTIPLE=Q)
95	CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ)
96	CRYPTOPP_CONSTANT(IV_LENGTH=IV_L)
97
98	static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t n)
99	{
100		if (n < (size_t)MIN_KEYLENGTH)
101			return MIN_KEYLENGTH;
102		else if (n > (size_t)MAX_KEYLENGTH)
103			return (size_t)MAX_KEYLENGTH;
104		else
105		{
106			n += KEYLENGTH_MULTIPLE-1;
107			return n - n%KEYLENGTH_MULTIPLE;
108		}
109	}
110};
111
112/// support query of key length that's the same as another class
113template <class T, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE, unsigned int IV_L = 0>
114class SameKeyLengthAs
115{
116public:
117	CRYPTOPP_CONSTANT(MIN_KEYLENGTH=T::MIN_KEYLENGTH)
118	CRYPTOPP_CONSTANT(MAX_KEYLENGTH=T::MAX_KEYLENGTH)
119	CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH)
120	CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ)
121	CRYPTOPP_CONSTANT(IV_LENGTH=IV_L)
122
123	static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength)
124		{return T::StaticGetValidKeyLength(keylength);}
125};
126
127// ************** implementation helper for SimpleKeyed ***************
128
129//! _
130template <class BASE, class INFO = BASE>
131class CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : public BASE
132{
133public:
134	size_t MinKeyLength() const {return INFO::MIN_KEYLENGTH;}
135	size_t MaxKeyLength() const {return (size_t)INFO::MAX_KEYLENGTH;}
136	size_t DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;}
137	size_t GetValidKeyLength(size_t n) const {return INFO::StaticGetValidKeyLength(n);}
138	SimpleKeyingInterface::IV_Requirement IVRequirement() const {return (SimpleKeyingInterface::IV_Requirement)INFO::IV_REQUIREMENT;}
139	unsigned int IVSize() const {return INFO::IV_LENGTH;}
140};
141
142template <class INFO, class BASE = BlockCipher>
143class CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl<SimpleKeyingInterfaceImpl<TwoBases<BASE, INFO> > >
144{
145public:
146	unsigned int BlockSize() const {return this->BLOCKSIZE;}
147};
148
149//! _
150template <CipherDir DIR, class BASE>
151class BlockCipherFinal : public ClonableImpl<BlockCipherFinal<DIR, BASE>, BASE>
152{
153public:
154 	BlockCipherFinal() {}
155	BlockCipherFinal(const byte *key)
156		{this->SetKey(key, this->DEFAULT_KEYLENGTH);}
157	BlockCipherFinal(const byte *key, size_t length)
158		{this->SetKey(key, length);}
159	BlockCipherFinal(const byte *key, size_t length, unsigned int rounds)
160		{this->SetKeyWithRounds(key, length, rounds);}
161
162	bool IsForwardTransformation() const {return DIR == ENCRYPTION;}
163};
164
165//! _
166template <class BASE, class INFO = BASE>
167class MessageAuthenticationCodeImpl : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
168{
169};
170
171//! _
172template <class BASE>
173class MessageAuthenticationCodeFinal : public ClonableImpl<MessageAuthenticationCodeFinal<BASE>, MessageAuthenticationCodeImpl<BASE> >
174{
175public:
176 	MessageAuthenticationCodeFinal() {}
177	MessageAuthenticationCodeFinal(const byte *key)
178		{this->SetKey(key, this->DEFAULT_KEYLENGTH);}
179	MessageAuthenticationCodeFinal(const byte *key, size_t length)
180		{this->SetKey(key, length);}
181};
182
183// ************** documentation ***************
184
185//! These objects usually should not be used directly. See CipherModeDocumentation instead.
186/*! Each class derived from this one defines two types, Encryption and Decryption,
187	both of which implement the BlockCipher interface. */
188struct BlockCipherDocumentation
189{
190	//! implements the BlockCipher interface
191	typedef BlockCipher Encryption;
192	//! implements the BlockCipher interface
193	typedef BlockCipher Decryption;
194};
195
196/*! \brief Each class derived from this one defines two types, Encryption and Decryption,
197	both of which implement the SymmetricCipher interface. Two types of classes derive
198	from this class: stream ciphers and block cipher modes. Stream ciphers can be used
199	alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation
200	for more for information about using cipher modes and block ciphers. */
201struct SymmetricCipherDocumentation
202{
203	//! implements the SymmetricCipher interface
204	typedef SymmetricCipher Encryption;
205	//! implements the SymmetricCipher interface
206	typedef SymmetricCipher Decryption;
207};
208
209/*! \brief Each class derived from this one defines two types, Encryption and Decryption,
210	both of which implement the AuthenticatedSymmetricCipher interface. */
211struct AuthenticatedSymmetricCipherDocumentation
212{
213	//! implements the AuthenticatedSymmetricCipher interface
214	typedef AuthenticatedSymmetricCipher Encryption;
215	//! implements the AuthenticatedSymmetricCipher interface
216	typedef AuthenticatedSymmetricCipher Decryption;
217};
218
219NAMESPACE_END
220
221#endif
222