Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/des.cpp
Line
Count
Source (jump to first uncovered line)
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)
76
static inline void IPERM(word32 &left, word32 &right)
77
634
{
78
634
  word32 work;
79
80
634
  right = rotlConstant<4>(right);
81
634
  work = (left ^ right) & 0xf0f0f0f0;
82
634
  left ^= work;
83
634
  right = rotrConstant<20>(right^work);
84
634
  work = (left ^ right) & 0xffff0000;
85
634
  left ^= work;
86
634
  right = rotrConstant<18>(right^work);
87
634
  work = (left ^ right) & 0x33333333;
88
634
  left ^= work;
89
634
  right = rotrConstant<6>(right^work);
90
634
  work = (left ^ right) & 0x00ff00ff;
91
634
  left ^= work;
92
634
  right = rotlConstant<9>(right^work);
93
634
  work = (left ^ right) & 0xaaaaaaaa;
94
634
  left = rotlConstant<1>(left^work);
95
634
  right ^= work;
96
634
}
97
98
static inline void FPERM(word32 &left, word32 &right)
99
634
{
100
634
  word32 work;
101
102
634
  right = rotrConstant<1>(right);
103
634
  work = (left ^ right) & 0xaaaaaaaa;
104
634
  right ^= work;
105
634
  left = rotrConstant<9>(left^work);
106
634
  work = (left ^ right) & 0x00ff00ff;
107
634
  right ^= work;
108
634
  left = rotlConstant<6>(left^work);
109
634
  work = (left ^ right) & 0x33333333;
110
634
  right ^= work;
111
634
  left = rotlConstant<18>(left^work);
112
634
  work = (left ^ right) & 0xffff0000;
113
634
  right ^= work;
114
634
  left = rotlConstant<20>(left^work);
115
634
  work = (left ^ right) & 0xf0f0f0f0;
116
634
  right ^= work;
117
634
  left = rotrConstant<4>(left^work);
118
634
}
119
120
void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
121
2
{
122
2
  AssertValidKeyLength(length);
123
124
2
  RawSetKey(GetCipherDirection(), userKey);
125
2
}
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
31
{
286
31
#if (CRYPTOPP_MSC_VERSION >= 1600) || (__cplusplus >= 201103L)
287
31
# define REGISTER /* Define to nothing for C++11 and above */
288
#else
289
# define REGISTER register
290
#endif
291
292
31
  SecByteBlock buffer(56+56+8);
293
31
  byte *const pc1m=buffer;                 /* place to modify pc1 into */
294
31
  byte *const pcr=pc1m+56;                 /* place to rotate pc1 into */
295
31
  byte *const ks=pcr+56;
296
31
  REGISTER int i,j,l;
297
31
  int m;
298
299
1.76k
  for (j=0; j<56; j++) {          /* convert pc1 to bits of key */
300
1.73k
    l=pc1[j]-1;             /* integer bit location  */
301
1.73k
    m = l & 07;             /* find bit              */
302
1.73k
    pc1m[j]=(key[l>>3] &    /* find which key byte l is in */
303
1.73k
      bytebit[m])     /* and which bit of that byte */
304
1.73k
      ? 1 : 0;        /* and store 1-bit result */
305
1.73k
  }
306
527
  for (i=0; i<16; i++) {          /* key chunk for each iteration */
307
496
    std::memset(ks,0,8);         /* Clear key schedule */
308
28.2k
    for (j=0; j<56; j++)    /* rotate pc1 the right amount */
309
27.7k
      pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
310
    /* rotate left and right halves independently */
311
24.3k
    for (j=0; j<48; j++){   /* select bits individually */
312
      /* check bit that goes to ks[j] */
313
23.8k
      if (pcr[pc2[j]-1]){
314
        /* mask it in if it's there */
315
6.52k
        l= j % 6;
316
6.52k
        ks[j/6] |= bytebit[l] >> 2;
317
6.52k
      }
318
23.8k
    }
319
    /* Now convert to odd/even interleaved form for use in F */
320
496
    k[2*i] = ((word32)ks[0] << 24)
321
496
      | ((word32)ks[2] << 16)
322
496
      | ((word32)ks[4] << 8)
323
496
      | ((word32)ks[6]);
324
496
    k[2*i+1] = ((word32)ks[1] << 24)
325
496
      | ((word32)ks[3] << 16)
326
496
      | ((word32)ks[5] << 8)
327
496
      | ((word32)ks[7]);
328
496
  }
329
330
31
  if (dir==DECRYPTION)     // reverse key schedule order
331
162
    for (i=0; i<16; i+=2)
332
144
    {
333
144
      std::swap(k[i], k[32-2-i]);
334
144
      std::swap(k[i+1], k[32-1-i]);
335
144
    }
336
31
}
337
338
void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const
339
714
{
340
714
  word32 l = l_, r = r_;
341
714
  const word32 *kptr=k;
342
343
6.42k
  for (unsigned i=0; i<8; i++)
344
5.71k
  {
345
5.71k
    word32 work = rotrConstant<4>(r) ^ kptr[4 * i + 0];
346
5.71k
    l ^= Spbox[6][(work) & 0x3f]
347
5.71k
      ^  Spbox[4][(work >> 8) & 0x3f]
348
5.71k
      ^  Spbox[2][(work >> 16) & 0x3f]
349
5.71k
      ^  Spbox[0][(work >> 24) & 0x3f];
350
5.71k
    work = r ^ kptr[4*i+1];
351
5.71k
    l ^= Spbox[7][(work) & 0x3f]
352
5.71k
      ^  Spbox[5][(work >> 8) & 0x3f]
353
5.71k
      ^  Spbox[3][(work >> 16) & 0x3f]
354
5.71k
      ^  Spbox[1][(work >> 24) & 0x3f];
355
356
5.71k
    work = rotrConstant<4>(l) ^ kptr[4 * i + 2];
357
5.71k
    r ^= Spbox[6][(work) & 0x3f]
358
5.71k
      ^  Spbox[4][(work >> 8) & 0x3f]
359
5.71k
      ^  Spbox[2][(work >> 16) & 0x3f]
360
5.71k
      ^  Spbox[0][(work >> 24) & 0x3f];
361
5.71k
    work = l ^ kptr[4*i+3];
362
5.71k
    r ^= Spbox[7][(work) & 0x3f]
363
5.71k
      ^  Spbox[5][(work >> 8) & 0x3f]
364
5.71k
      ^  Spbox[3][(work >> 16) & 0x3f]
365
5.71k
      ^  Spbox[1][(work >> 24) & 0x3f];
366
5.71k
  }
367
368
714
  l_ = l; r_ = r;
369
714
}
370
371
void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
372
12
{
373
12
  AssertValidKeyLength(length);
374
375
12
  m_des1.RawSetKey(GetCipherDirection(), userKey);
376
12
  m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8);
377
12
}
378
379
void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
380
40
{
381
40
  word32 l,r;
382
40
  Block::Get(inBlock)(l)(r);
383
40
  IPERM(l,r);
384
40
  m_des1.RawProcessBlock(l, r);
385
40
  m_des2.RawProcessBlock(r, l);
386
40
  m_des1.RawProcessBlock(l, r);
387
40
  FPERM(l,r);
388
40
  Block::Put(xorBlock, outBlock)(r)(l);
389
40
}
390
391
void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
392
0
{
393
0
  AssertValidKeyLength(length);
394
395
0
  m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16));
396
0
  m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8);
397
0
  m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0));
398
0
}
399
400
void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
401
0
{
402
0
  word32 l,r;
403
0
  Block::Get(inBlock)(l)(r);
404
0
  IPERM(l,r);
405
0
  m_des1.RawProcessBlock(l, r);
406
0
  m_des2.RawProcessBlock(r, l);
407
0
  m_des3.RawProcessBlock(l, r);
408
0
  FPERM(l,r);
409
0
  Block::Put(xorBlock, outBlock)(r)(l);
410
0
}
411
412
#endif  // #ifndef CRYPTOPP_IMPORTS
413
414
static inline bool CheckParity(byte b)
415
0
{
416
0
  unsigned int a = b ^ (b >> 4);
417
0
  return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
418
0
}
419
420
bool DES::CheckKeyParityBits(const byte *key)
421
0
{
422
0
  for (unsigned int i=0; i<8; i++)
423
0
    if (!CheckParity(key[i]))
424
0
      return false;
425
0
  return true;
426
0
}
427
428
void DES::CorrectKeyParityBits(byte *key)
429
0
{
430
0
  for (unsigned int i=0; i<8; i++)
431
0
    if (!CheckParity(key[i]))
432
0
      key[i] ^= 1;
433
0
}
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
594
{
438
594
  word32 l,r;
439
594
  Block::Get(inBlock)(l)(r);
440
594
  IPERM(l,r);
441
594
  RawProcessBlock(l, r);
442
594
  FPERM(l,r);
443
594
  Block::Put(xorBlock, outBlock)(r)(l);
444
594
}
445
446
void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &)
447
5
{
448
5
  AssertValidKeyLength(length);
449
450
5
  if (!m_des.get())
451
5
    m_des.reset(new DES::Encryption);
452
453
5
  std::memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE);
454
5
  m_des->RawSetKey(GetCipherDirection(), key + 8);
455
5
  std::memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE);
456
5
}
457
458
void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
459
5
{
460
5
  xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE);
461
5
  m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock);
462
5
  xorbuf(outBlock, m_x3, BLOCKSIZE);
463
5
}
464
465
NAMESPACE_END