Crypto++  8.2
Free C++ class library of cryptographic schemes
des.cpp
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 
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)
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 
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 
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) */
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 
338 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 
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 
379 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 
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 
400 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 
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 
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 
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
436 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 
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 
458 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
the cipher is performing decryption
Definition: cryptlib.h:127
Utility functions for the Crypto++ library.
static void CorrectKeyParityBits(byte *key)
correct DES key parity bits
Definition: des.cpp:428
CipherDir
Specifies a direction for a cipher to operate.
Definition: cryptlib.h:123
Access a block of memory.
Definition: misc.h:2532
SecBlock<byte> typedef.
Definition: secblock.h:1058
Provides class member functions to key a block cipher.
Definition: seckey.h:317
Precompiled header file.
static bool CheckKeyParityBits(const byte *key)
check DES key parity bits
Definition: des.cpp:420
CipherDir ReverseCipherDir(CipherDir dir)
Inverts the cipher&#39;s direction.
Definition: seckey.h:32
Classes for DES, 2-key Triple-DES, 3-key Triple-DES and DESX.
CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:32
Access a block of memory.
Definition: misc.h:2495
Crypto++ library namespace.
Interface for retrieving values given their names.
Definition: cryptlib.h:293