1 // des.cpp - modified by Wei Dai from Phil Karn's des.c
2 // The original code and all modifications are in the public domain.
3 
4 /*
5  * This is a major rewrite of my old public domain DES code written
6  * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977
7  * public domain code. I pretty much kept my key scheduling code, but
8  * the actual encrypt/decrypt routines are taken from from Richard
9  * Outerbridge's DES code as printed in Schneier's "Applied Cryptography."
10  *
11  * This code is in the public domain. I would appreciate bug reports and
12  * enhancements.
13  *
14  * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994.
15  */
16 
17 #include "pch.h"
18 #include "misc.h"
19 #include "des.h"
20 
21 NAMESPACE_BEGIN(CryptoPP)
22 
23 typedef BlockGetAndPut<word32, BigEndian> Block;
24 
25 // Richard Outerbridge's initial permutation algorithm
26 /*
27 inline void IPERM(word32 &left, word32 &right)
28 {
29 	word32 work;
30 
31 	work = ((left >> 4) ^ right) & 0x0f0f0f0f;
32 	right ^= work;
33 	left ^= work << 4;
34 	work = ((left >> 16) ^ right) & 0xffff;
35 	right ^= work;
36 	left ^= work << 16;
37 	work = ((right >> 2) ^ left) & 0x33333333;
38 	left ^= work;
39 	right ^= (work << 2);
40 	work = ((right >> 8) ^ left) & 0xff00ff;
41 	left ^= work;
42 	right ^= (work << 8);
43 	right = rotl(right, 1);
44 	work = (left ^ right) & 0xaaaaaaaa;
45 	left ^= work;
46 	right ^= work;
47 	left = rotl(left, 1);
48 }
49 inline void FPERM(word32 &left, word32 &right)
50 {
51 	word32 work;
52 
53 	right = rotr(right, 1);
54 	work = (left ^ right) & 0xaaaaaaaa;
55 	left ^= work;
56 	right ^= work;
57 	left = rotr(left, 1);
58 	work = ((left >> 8) ^ right) & 0xff00ff;
59 	right ^= work;
60 	left ^= work << 8;
61 	work = ((left >> 2) ^ right) & 0x33333333;
62 	right ^= work;
63 	left ^= work << 2;
64 	work = ((right >> 16) ^ left) & 0xffff;
65 	left ^= work;
66 	right ^= work << 16;
67 	work = ((right >> 4) ^ left) & 0x0f0f0f0f;
68 	left ^= work;
69 	right ^= work << 4;
70 }
71 */
72 
73 // Wei Dai's modification to Richard Outerbridge's initial permutation
74 // algorithm, this one is faster if you have access to rotate instructions
75 // (like in MSVC)
IPERM(word32 & left,word32 & right)76 static inline void IPERM(word32 &left, word32 &right)
77 {
78 	word32 work;
79 
80 	right = rotlConstant<4>(right);
81 	work = (left ^ right) & 0xf0f0f0f0;
82 	left ^= work;
83 	right = rotrConstant<20>(right^work);
84 	work = (left ^ right) & 0xffff0000;
85 	left ^= work;
86 	right = rotrConstant<18>(right^work);
87 	work = (left ^ right) & 0x33333333;
88 	left ^= work;
89 	right = rotrConstant<6>(right^work);
90 	work = (left ^ right) & 0x00ff00ff;
91 	left ^= work;
92 	right = rotlConstant<9>(right^work);
93 	work = (left ^ right) & 0xaaaaaaaa;
94 	left = rotlConstant<1>(left^work);
95 	right ^= work;
96 }
97 
FPERM(word32 & left,word32 & right)98 static inline void FPERM(word32 &left, word32 &right)
99 {
100 	word32 work;
101 
102 	right = rotrConstant<1>(right);
103 	work = (left ^ right) & 0xaaaaaaaa;
104 	right ^= work;
105 	left = rotrConstant<9>(left^work);
106 	work = (left ^ right) & 0x00ff00ff;
107 	right ^= work;
108 	left = rotlConstant<6>(left^work);
109 	work = (left ^ right) & 0x33333333;
110 	right ^= work;
111 	left = rotlConstant<18>(left^work);
112 	work = (left ^ right) & 0xffff0000;
113 	right ^= work;
114 	left = rotlConstant<20>(left^work);
115 	work = (left ^ right) & 0xf0f0f0f0;
116 	right ^= work;
117 	left = rotrConstant<4>(left^work);
118 }
119 
UncheckedSetKey(const byte * userKey,unsigned int length,const NameValuePairs &)120 void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
121 {
122 	AssertValidKeyLength(length);
123 
124 	RawSetKey(GetCipherDirection(), userKey);
125 }
126 
127 #ifndef CRYPTOPP_IMPORTS
128 
129 /* Tables defined in the Data Encryption Standard documents
130  * Three of these tables, the initial permutation, the final
131  * permutation and the expansion operator, are regular enough that
132  * for speed, we hard-code them. They're here for reference only.
133  * Also, the S and P boxes are used by a separate program, gensp.c,
134  * to build the combined SP box, Spbox[]. They're also here just
135  * for reference.
136  */
137 #ifdef notdef
138 /* initial permutation IP */
139 static byte ip[] = {
140 	   58, 50, 42, 34, 26, 18, 10,  2,
141 	   60, 52, 44, 36, 28, 20, 12,  4,
142 	   62, 54, 46, 38, 30, 22, 14,  6,
143 	   64, 56, 48, 40, 32, 24, 16,  8,
144 	   57, 49, 41, 33, 25, 17,  9,  1,
145 	   59, 51, 43, 35, 27, 19, 11,  3,
146 	   61, 53, 45, 37, 29, 21, 13,  5,
147 	   63, 55, 47, 39, 31, 23, 15,  7
148 };
149 
150 /* final permutation IP^-1 */
151 static byte fp[] = {
152 	   40,  8, 48, 16, 56, 24, 64, 32,
153 	   39,  7, 47, 15, 55, 23, 63, 31,
154 	   38,  6, 46, 14, 54, 22, 62, 30,
155 	   37,  5, 45, 13, 53, 21, 61, 29,
156 	   36,  4, 44, 12, 52, 20, 60, 28,
157 	   35,  3, 43, 11, 51, 19, 59, 27,
158 	   34,  2, 42, 10, 50, 18, 58, 26,
159 	   33,  1, 41,  9, 49, 17, 57, 25
160 };
161 /* expansion operation matrix */
162 static byte ei[] = {
163 	   32,  1,  2,  3,  4,  5,
164 		4,  5,  6,  7,  8,  9,
165 		8,  9, 10, 11, 12, 13,
166 	   12, 13, 14, 15, 16, 17,
167 	   16, 17, 18, 19, 20, 21,
168 	   20, 21, 22, 23, 24, 25,
169 	   24, 25, 26, 27, 28, 29,
170 	   28, 29, 30, 31, 32,  1
171 };
172 /* The (in)famous S-boxes */
173 static byte sbox[8][64] = {
174 	   /* S1 */
175 	   14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
176 		0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
177 		4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
178 	   15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
179 
180 	   /* S2 */
181 	   15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
182 		3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
183 		0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
184 	   13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
185 
186 	   /* S3 */
187 	   10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
188 	   13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
189 	   13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
190 		1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
191 
192 	   /* S4 */
193 		7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
194 	   13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
195 	   10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
196 		3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
197 
198 	   /* S5 */
199 		2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
200 	   14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
201 		4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
202 	   11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
203 
204 	   /* S6 */
205 	   12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
206 	   10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
207 		9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
208 		4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
209 
210 	   /* S7 */
211 		4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
212 	   13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
213 		1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
214 		6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
215 
216 	   /* S8 */
217 	   13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
218 		1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
219 		7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
220 		2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
221 };
222 
223 /* 32-bit permutation function P used on the output of the S-boxes */
224 namespace {
225 	const byte p32i[] = {
226 	   16,  7, 20, 21,
227 	   29, 12, 28, 17,
228 		1, 15, 23, 26,
229 		5, 18, 31, 10,
230 		2,  8, 24, 14,
231 	   32, 27,  3,  9,
232 	   19, 13, 30,  6,
233 	   22, 11,  4, 25
234 	};
235 }
236 #endif
237 
238 /* permuted choice table (key) */
239 namespace {
240 	const byte pc1[] = {
241 	   57, 49, 41, 33, 25, 17,  9,
242 		1, 58, 50, 42, 34, 26, 18,
243 	   10,  2, 59, 51, 43, 35, 27,
244 	   19, 11,  3, 60, 52, 44, 36,
245 
246 	   63, 55, 47, 39, 31, 23, 15,
247 		7, 62, 54, 46, 38, 30, 22,
248 	   14,  6, 61, 53, 45, 37, 29,
249 	   21, 13,  5, 28, 20, 12,  4
250 	};
251 }
252 
253 /* number left rotations of pc1 */
254 namespace {
255 	const byte totrot[] = {
256 	   1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
257 	};
258 }
259 
260 /* permuted choice key (table) */
261 namespace {
262 	const byte pc2[] = {
263 	   14, 17, 11, 24,  1,  5,
264 		3, 28, 15,  6, 21, 10,
265 	   23, 19, 12,  4, 26,  8,
266 	   16,  7, 27, 20, 13,  2,
267 	   41, 52, 31, 37, 47, 55,
268 	   30, 40, 51, 45, 33, 48,
269 	   44, 49, 39, 56, 34, 53,
270 	   46, 42, 50, 36, 29, 32
271 	};
272 }
273 
274 /* End of DES-defined tables */
275 
276 /* bit 0 is left-most in byte */
277 namespace {
278 	const int bytebit[] = {
279 	   0200,0100,040,020,010,04,02,01
280 	};
281 }
282 
283 /* Set key (initialize key schedule array) */
RawSetKey(CipherDir dir,const byte * key)284 void RawDES::RawSetKey(CipherDir dir, const byte *key)
285 {
286 #if (_MSC_VER >= 1600) || (__cplusplus >= 201103L)
287 # define REGISTER /* Define to nothing for C++11 and above */
288 #else
289 # define REGISTER register
290 #endif
291 
292 	SecByteBlock buffer(56+56+8);
293 	byte *const pc1m=buffer;                 /* place to modify pc1 into */
294 	byte *const pcr=pc1m+56;                 /* place to rotate pc1 into */
295 	byte *const ks=pcr+56;
296 	REGISTER int i,j,l;
297 	int m;
298 
299 	for (j=0; j<56; j++) {          /* convert pc1 to bits of key */
300 		l=pc1[j]-1;             /* integer bit location  */
301 		m = l & 07;             /* find bit              */
302 		pc1m[j]=(key[l>>3] &    /* find which key byte l is in */
303 			bytebit[m])     /* and which bit of that byte */
304 			? 1 : 0;        /* and store 1-bit result */
305 	}
306 	for (i=0; i<16; i++) {          /* key chunk for each iteration */
307 		memset(ks,0,8);         /* Clear key schedule */
308 		for (j=0; j<56; j++)    /* rotate pc1 the right amount */
309 			pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
310 		/* rotate left and right halves independently */
311 		for (j=0; j<48; j++){   /* select bits individually */
312 			/* check bit that goes to ks[j] */
313 			if (pcr[pc2[j]-1]){
314 				/* mask it in if it's there */
315 				l= j % 6;
316 				ks[j/6] |= bytebit[l] >> 2;
317 			}
318 		}
319 		/* Now convert to odd/even interleaved form for use in F */
320 		k[2*i] = ((word32)ks[0] << 24)
321 			| ((word32)ks[2] << 16)
322 			| ((word32)ks[4] << 8)
323 			| ((word32)ks[6]);
324 		k[2*i+1] = ((word32)ks[1] << 24)
325 			| ((word32)ks[3] << 16)
326 			| ((word32)ks[5] << 8)
327 			| ((word32)ks[7]);
328 	}
329 
330 	if (dir==DECRYPTION)     // reverse key schedule order
331 		for (i=0; i<16; i+=2)
332 		{
333 			std::swap(k[i], k[32-2-i]);
334 			std::swap(k[i+1], k[32-1-i]);
335 		}
336 }
337 
RawProcessBlock(word32 & l_,word32 & r_) const338 void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const
339 {
340 	word32 l = l_, r = r_;
341 	const word32 *kptr=k;
342 
343 	for (unsigned i=0; i<8; i++)
344 	{
345 		word32 work = rotrConstant<4>(r) ^ kptr[4 * i + 0];
346 		l ^= Spbox[6][(work) & 0x3f]
347 		  ^  Spbox[4][(work >> 8) & 0x3f]
348 		  ^  Spbox[2][(work >> 16) & 0x3f]
349 		  ^  Spbox[0][(work >> 24) & 0x3f];
350 		work = r ^ kptr[4*i+1];
351 		l ^= Spbox[7][(work) & 0x3f]
352 		  ^  Spbox[5][(work >> 8) & 0x3f]
353 		  ^  Spbox[3][(work >> 16) & 0x3f]
354 		  ^  Spbox[1][(work >> 24) & 0x3f];
355 
356 		work = rotrConstant<4>(l) ^ kptr[4 * i + 2];
357 		r ^= Spbox[6][(work) & 0x3f]
358 		  ^  Spbox[4][(work >> 8) & 0x3f]
359 		  ^  Spbox[2][(work >> 16) & 0x3f]
360 		  ^  Spbox[0][(work >> 24) & 0x3f];
361 		work = l ^ kptr[4*i+3];
362 		r ^= Spbox[7][(work) & 0x3f]
363 		  ^  Spbox[5][(work >> 8) & 0x3f]
364 		  ^  Spbox[3][(work >> 16) & 0x3f]
365 		  ^  Spbox[1][(work >> 24) & 0x3f];
366 	}
367 
368 	l_ = l; r_ = r;
369 }
370 
UncheckedSetKey(const byte * userKey,unsigned int length,const NameValuePairs &)371 void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
372 {
373 	AssertValidKeyLength(length);
374 
375 	m_des1.RawSetKey(GetCipherDirection(), userKey);
376 	m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8);
377 }
378 
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock) const379 void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
380 {
381 	word32 l,r;
382 	Block::Get(inBlock)(l)(r);
383 	IPERM(l,r);
384 	m_des1.RawProcessBlock(l, r);
385 	m_des2.RawProcessBlock(r, l);
386 	m_des1.RawProcessBlock(l, r);
387 	FPERM(l,r);
388 	Block::Put(xorBlock, outBlock)(r)(l);
389 }
390 
UncheckedSetKey(const byte * userKey,unsigned int length,const NameValuePairs &)391 void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
392 {
393 	AssertValidKeyLength(length);
394 
395 	m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16));
396 	m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8);
397 	m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0));
398 }
399 
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock) const400 void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
401 {
402 	word32 l,r;
403 	Block::Get(inBlock)(l)(r);
404 	IPERM(l,r);
405 	m_des1.RawProcessBlock(l, r);
406 	m_des2.RawProcessBlock(r, l);
407 	m_des3.RawProcessBlock(l, r);
408 	FPERM(l,r);
409 	Block::Put(xorBlock, outBlock)(r)(l);
410 }
411 
412 #endif	// #ifndef CRYPTOPP_IMPORTS
413 
CheckParity(byte b)414 static inline bool CheckParity(byte b)
415 {
416 	unsigned int a = b ^ (b >> 4);
417 	return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
418 }
419 
CheckKeyParityBits(const byte * key)420 bool DES::CheckKeyParityBits(const byte *key)
421 {
422 	for (unsigned int i=0; i<8; i++)
423 		if (!CheckParity(key[i]))
424 			return false;
425 	return true;
426 }
427 
CorrectKeyParityBits(byte * key)428 void DES::CorrectKeyParityBits(byte *key)
429 {
430 	for (unsigned int i=0; i<8; i++)
431 		if (!CheckParity(key[i]))
432 			key[i] ^= 1;
433 }
434 
435 // Encrypt or decrypt a block of data in ECB mode
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock) const436 void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
437 {
438 	word32 l,r;
439 	Block::Get(inBlock)(l)(r);
440 	IPERM(l,r);
441 	RawProcessBlock(l, r);
442 	FPERM(l,r);
443 	Block::Put(xorBlock, outBlock)(r)(l);
444 }
445 
UncheckedSetKey(const byte * key,unsigned int length,const NameValuePairs &)446 void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &)
447 {
448 	AssertValidKeyLength(length);
449 
450 	if (!m_des.get())
451 		m_des.reset(new DES::Encryption);
452 
453 	memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE);
454 	m_des->RawSetKey(GetCipherDirection(), key + 8);
455 	memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE);
456 }
457 
ProcessAndXorBlock(const byte * inBlock,const byte * xorBlock,byte * outBlock) const458 void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
459 {
460 	xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE);
461 	m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock);
462 	xorbuf(outBlock, m_x3, BLOCKSIZE);
463 }
464 
465 NAMESPACE_END
466