1 // lubyrack.h - originally written and placed in the public domain by Wei Dai
2 
3 /// \file lubyrack.h
4 /// \brief Classes for the Luby-Rackoff block cipher
5 
6 #ifndef CRYPTOPP_LUBYRACK_H
7 #define CRYPTOPP_LUBYRACK_H
8 
9 #include "simple.h"
10 #include "secblock.h"
11 
12 NAMESPACE_BEGIN(CryptoPP)
13 
14 /// \brief Luby-Rackoff block cipher information
15 template <class T>
16 struct LR_Info : public VariableKeyLength<16, 0, 2*(INT_MAX/2), 2>, public FixedBlockSize<2*T::DIGESTSIZE>
17 {
18 	static std::string StaticAlgorithmName() {return std::string("LR/")+T::StaticAlgorithmName();}
19 };
20 
21 /// \brief Luby-Rackoff block cipher
22 template <class T>
23 class LR : public LR_Info<T>, public BlockCipherDocumentation
24 {
25 	class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<LR_Info<T> >
26 	{
27 	public:
28 		// VC60 workaround: have to define these functions within class definition
29 		void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
30 		{
31 			this->AssertValidKeyLength(length);
32 
33 			L = length/2;
34 			buffer.New(2*S);
35 			digest.New(S);
36 			key.Assign(userKey, 2*L);
37 		}
38 
39 	protected:
40 		CRYPTOPP_CONSTANT(S=T::DIGESTSIZE);
41 		unsigned int L;	// key length / 2
42 		SecByteBlock key;
43 
44 		mutable T hm;
45 		mutable SecByteBlock buffer, digest;
46 	};
47 
48 	class CRYPTOPP_NO_VTABLE Enc : public Base
49 	{
50 	public:
51 
52 #define KL this->key
53 #define KR this->key+this->L
54 #define BL this->buffer
55 #define BR this->buffer+this->S
56 #define IL inBlock
57 #define IR inBlock+this->S
58 #define OL outBlock
59 #define OR outBlock+this->S
60 
61 		void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
62 		{
63 			this->hm.Update(KL, this->L);
64 			this->hm.Update(IL, this->S);
65 			this->hm.Final(BR);
66 			xorbuf(BR, IR, this->S);
67 
68 			this->hm.Update(KR, this->L);
69 			this->hm.Update(BR, this->S);
70 			this->hm.Final(BL);
71 			xorbuf(BL, IL, this->S);
72 
73 			this->hm.Update(KL, this->L);
74 			this->hm.Update(BL, this->S);
75 			this->hm.Final(this->digest);
76 			xorbuf(BR, this->digest, this->S);
77 
78 			this->hm.Update(KR, this->L);
79 			this->hm.Update(OR, this->S);
80 			this->hm.Final(this->digest);
81 			xorbuf(BL, this->digest, this->S);
82 
83 			if (xorBlock)
84 				xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
85 			else
86 				memcpy_s(outBlock, 2*this->S, this->buffer, 2*this->S);
87 		}
88 	};
89 
90 	class CRYPTOPP_NO_VTABLE Dec : public Base
91 	{
92 	public:
93 		void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
94 		{
95 			this->hm.Update(KR, this->L);
96 			this->hm.Update(IR, this->S);
97 			this->hm.Final(BL);
98 			xorbuf(BL, IL, this->S);
99 
100 			this->hm.Update(KL, this->L);
101 			this->hm.Update(BL, this->S);
102 			this->hm.Final(BR);
103 			xorbuf(BR, IR, this->S);
104 
105 			this->hm.Update(KR, this->L);
106 			this->hm.Update(BR, this->S);
107 			this->hm.Final(this->digest);
108 			xorbuf(BL, this->digest, this->S);
109 
110 			this->hm.Update(KL, this->L);
111 			this->hm.Update(OL, this->S);
112 			this->hm.Final(this->digest);
113 			xorbuf(BR, this->digest, this->S);
114 
115 			if (xorBlock)
116 				xorbuf(outBlock, xorBlock, this->buffer, 2*this->S);
117 			else
118 				memcpy(outBlock, this->buffer, 2*this->S);
119 		}
120 #undef KL
121 #undef KR
122 #undef BL
123 #undef BR
124 #undef IL
125 #undef IR
126 #undef OL
127 #undef OR
128 	};
129 
130 public:
131 	typedef BlockCipherFinal<ENCRYPTION, Enc> Encryption;
132 	typedef BlockCipherFinal<DECRYPTION, Dec> Decryption;
133 };
134 
135 NAMESPACE_END
136 
137 #endif
138