monotone

monotone Mtn Source Tree

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

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status