View Javadoc
1   package org.bouncycastle.crypto.engines;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * SNMP Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 Sentry Software, Westhawk
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import org.bouncycastle.crypto.BlockCipher;
26  import org.bouncycastle.crypto.CipherParameters;
27  import org.bouncycastle.crypto.DataLengthException;
28  import org.bouncycastle.crypto.params.KeyParameter;
29  
30  /**
31   * a class that provides a basic DES engine.
32   */
33  public class DESEngine
34      implements BlockCipher
35  {
36      protected static final int  BLOCK_SIZE = 8;
37  
38      private int[]               workingKey = null;
39  
40      /**
41       * standard constructor.
42       */
43      public DESEngine()
44      {
45      }
46  
47      /**
48       * initialise a DES cipher.
49       *
50       * @param encrypting whether or not we are for encryption.
51       * @param params the parameters required to set up the cipher.
52       * @exception IllegalArgumentException if the params argument is
53       * inappropriate.
54       */
55      public void init(
56          boolean           encrypting,
57          CipherParameters  params)
58      {
59          if (params instanceof KeyParameter)
60          {
61              workingKey = generateWorkingKey(encrypting,
62                                    ((KeyParameter)params).getKey());
63  
64              return;
65          }
66  
67          throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
68      }
69  
70      public String getAlgorithmName()
71      {
72          return "DES";
73      }
74  
75      public int getBlockSize()
76      {
77          return BLOCK_SIZE;
78      }
79  
80      public int processBlock(
81          byte[] in,
82          int inOff,
83          byte[] out,
84          int outOff)
85      {
86          if (workingKey == null)
87          {
88              throw new IllegalStateException("DES engine not initialised");
89          }
90  
91          if ((inOff + BLOCK_SIZE) > in.length)
92          {
93              throw new DataLengthException("input buffer too short");
94          }
95  
96          if ((outOff + BLOCK_SIZE) > out.length)
97          {
98              throw new DataLengthException("output buffer too short");
99          }
100 
101         desFunc(workingKey, in, inOff, out, outOff);
102 
103         return BLOCK_SIZE;
104     }
105 
106     public void reset()
107     {
108     }
109 
110     /**
111      * what follows is mainly taken from "Applied Cryptography", by
112      * Bruce Schneier, however it also bears great resemblance to Richard
113      * Outerbridge's D3DES...
114      */
115 
116     static short[]    Df_Key =
117         {
118             0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
119             0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
120             0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
121         };
122 
123     static short[]    bytebit =
124         {
125             0200, 0100, 040, 020, 010, 04, 02, 01
126         };
127 
128     static int[]    bigbyte =
129         {
130             0x800000, 0x400000, 0x200000, 0x100000,
131             0x80000,  0x40000,  0x20000,  0x10000,
132             0x8000,      0x4000,   0x2000,   0x1000,
133             0x800,    0x400,    0x200,    0x100,
134             0x80,      0x40,        0x20,     0x10,
135             0x8,      0x4,      0x2,      0x1
136         };
137 
138     /*
139      * Use the key schedule specified in the Standard (ANSI X3.92-1981).
140      */
141 
142     static byte[]    pc1 =
143         {
144             56, 48, 40, 32, 24, 16,  8,   0, 57, 49, 41, 33, 25, 17,
145              9,  1, 58, 50, 42, 34, 26,  18, 10,  2, 59, 51, 43, 35,
146             62, 54, 46, 38, 30, 22, 14,   6, 61, 53, 45, 37, 29, 21,
147             13,  5, 60, 52, 44, 36, 28,  20, 12,  4, 27, 19, 11,  3
148         };
149 
150     static byte[] totrot =
151         {
152             1, 2, 4, 6, 8, 10, 12, 14,
153             15, 17, 19, 21, 23, 25, 27, 28
154         };
155 
156     static byte[] pc2 =
157         {
158             13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
159             22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
160             40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
161             43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
162         };
163 
164     static int[] SP1 = {
165         0x01010400, 0x00000000, 0x00010000, 0x01010404,
166         0x01010004, 0x00010404, 0x00000004, 0x00010000,
167         0x00000400, 0x01010400, 0x01010404, 0x00000400,
168         0x01000404, 0x01010004, 0x01000000, 0x00000004,
169         0x00000404, 0x01000400, 0x01000400, 0x00010400,
170         0x00010400, 0x01010000, 0x01010000, 0x01000404,
171         0x00010004, 0x01000004, 0x01000004, 0x00010004,
172         0x00000000, 0x00000404, 0x00010404, 0x01000000,
173         0x00010000, 0x01010404, 0x00000004, 0x01010000,
174         0x01010400, 0x01000000, 0x01000000, 0x00000400,
175         0x01010004, 0x00010000, 0x00010400, 0x01000004,
176         0x00000400, 0x00000004, 0x01000404, 0x00010404,
177         0x01010404, 0x00010004, 0x01010000, 0x01000404,
178         0x01000004, 0x00000404, 0x00010404, 0x01010400,
179         0x00000404, 0x01000400, 0x01000400, 0x00000000,
180         0x00010004, 0x00010400, 0x00000000, 0x01010004
181     };
182 
183     static int[] SP2 = {
184         0x80108020, 0x80008000, 0x00008000, 0x00108020,
185         0x00100000, 0x00000020, 0x80100020, 0x80008020,
186         0x80000020, 0x80108020, 0x80108000, 0x80000000,
187         0x80008000, 0x00100000, 0x00000020, 0x80100020,
188         0x00108000, 0x00100020, 0x80008020, 0x00000000,
189         0x80000000, 0x00008000, 0x00108020, 0x80100000,
190         0x00100020, 0x80000020, 0x00000000, 0x00108000,
191         0x00008020, 0x80108000, 0x80100000, 0x00008020,
192         0x00000000, 0x00108020, 0x80100020, 0x00100000,
193         0x80008020, 0x80100000, 0x80108000, 0x00008000,
194         0x80100000, 0x80008000, 0x00000020, 0x80108020,
195         0x00108020, 0x00000020, 0x00008000, 0x80000000,
196         0x00008020, 0x80108000, 0x00100000, 0x80000020,
197         0x00100020, 0x80008020, 0x80000020, 0x00100020,
198         0x00108000, 0x00000000, 0x80008000, 0x00008020,
199         0x80000000, 0x80100020, 0x80108020, 0x00108000
200     };
201 
202     static int[] SP3 = {
203         0x00000208, 0x08020200, 0x00000000, 0x08020008,
204         0x08000200, 0x00000000, 0x00020208, 0x08000200,
205         0x00020008, 0x08000008, 0x08000008, 0x00020000,
206         0x08020208, 0x00020008, 0x08020000, 0x00000208,
207         0x08000000, 0x00000008, 0x08020200, 0x00000200,
208         0x00020200, 0x08020000, 0x08020008, 0x00020208,
209         0x08000208, 0x00020200, 0x00020000, 0x08000208,
210         0x00000008, 0x08020208, 0x00000200, 0x08000000,
211         0x08020200, 0x08000000, 0x00020008, 0x00000208,
212         0x00020000, 0x08020200, 0x08000200, 0x00000000,
213         0x00000200, 0x00020008, 0x08020208, 0x08000200,
214         0x08000008, 0x00000200, 0x00000000, 0x08020008,
215         0x08000208, 0x00020000, 0x08000000, 0x08020208,
216         0x00000008, 0x00020208, 0x00020200, 0x08000008,
217         0x08020000, 0x08000208, 0x00000208, 0x08020000,
218         0x00020208, 0x00000008, 0x08020008, 0x00020200
219     };
220 
221     static int[] SP4 = {
222         0x00802001, 0x00002081, 0x00002081, 0x00000080,
223         0x00802080, 0x00800081, 0x00800001, 0x00002001,
224         0x00000000, 0x00802000, 0x00802000, 0x00802081,
225         0x00000081, 0x00000000, 0x00800080, 0x00800001,
226         0x00000001, 0x00002000, 0x00800000, 0x00802001,
227         0x00000080, 0x00800000, 0x00002001, 0x00002080,
228         0x00800081, 0x00000001, 0x00002080, 0x00800080,
229         0x00002000, 0x00802080, 0x00802081, 0x00000081,
230         0x00800080, 0x00800001, 0x00802000, 0x00802081,
231         0x00000081, 0x00000000, 0x00000000, 0x00802000,
232         0x00002080, 0x00800080, 0x00800081, 0x00000001,
233         0x00802001, 0x00002081, 0x00002081, 0x00000080,
234         0x00802081, 0x00000081, 0x00000001, 0x00002000,
235         0x00800001, 0x00002001, 0x00802080, 0x00800081,
236         0x00002001, 0x00002080, 0x00800000, 0x00802001,
237         0x00000080, 0x00800000, 0x00002000, 0x00802080
238     };
239 
240     static int[] SP5 = {
241         0x00000100, 0x02080100, 0x02080000, 0x42000100,
242         0x00080000, 0x00000100, 0x40000000, 0x02080000,
243         0x40080100, 0x00080000, 0x02000100, 0x40080100,
244         0x42000100, 0x42080000, 0x00080100, 0x40000000,
245         0x02000000, 0x40080000, 0x40080000, 0x00000000,
246         0x40000100, 0x42080100, 0x42080100, 0x02000100,
247         0x42080000, 0x40000100, 0x00000000, 0x42000000,
248         0x02080100, 0x02000000, 0x42000000, 0x00080100,
249         0x00080000, 0x42000100, 0x00000100, 0x02000000,
250         0x40000000, 0x02080000, 0x42000100, 0x40080100,
251         0x02000100, 0x40000000, 0x42080000, 0x02080100,
252         0x40080100, 0x00000100, 0x02000000, 0x42080000,
253         0x42080100, 0x00080100, 0x42000000, 0x42080100,
254         0x02080000, 0x00000000, 0x40080000, 0x42000000,
255         0x00080100, 0x02000100, 0x40000100, 0x00080000,
256         0x00000000, 0x40080000, 0x02080100, 0x40000100
257     };
258 
259     static int[] SP6 = {
260         0x20000010, 0x20400000, 0x00004000, 0x20404010,
261         0x20400000, 0x00000010, 0x20404010, 0x00400000,
262         0x20004000, 0x00404010, 0x00400000, 0x20000010,
263         0x00400010, 0x20004000, 0x20000000, 0x00004010,
264         0x00000000, 0x00400010, 0x20004010, 0x00004000,
265         0x00404000, 0x20004010, 0x00000010, 0x20400010,
266         0x20400010, 0x00000000, 0x00404010, 0x20404000,
267         0x00004010, 0x00404000, 0x20404000, 0x20000000,
268         0x20004000, 0x00000010, 0x20400010, 0x00404000,
269         0x20404010, 0x00400000, 0x00004010, 0x20000010,
270         0x00400000, 0x20004000, 0x20000000, 0x00004010,
271         0x20000010, 0x20404010, 0x00404000, 0x20400000,
272         0x00404010, 0x20404000, 0x00000000, 0x20400010,
273         0x00000010, 0x00004000, 0x20400000, 0x00404010,
274         0x00004000, 0x00400010, 0x20004010, 0x00000000,
275         0x20404000, 0x20000000, 0x00400010, 0x20004010
276     };
277 
278     static int[] SP7 = {
279         0x00200000, 0x04200002, 0x04000802, 0x00000000,
280         0x00000800, 0x04000802, 0x00200802, 0x04200800,
281         0x04200802, 0x00200000, 0x00000000, 0x04000002,
282         0x00000002, 0x04000000, 0x04200002, 0x00000802,
283         0x04000800, 0x00200802, 0x00200002, 0x04000800,
284         0x04000002, 0x04200000, 0x04200800, 0x00200002,
285         0x04200000, 0x00000800, 0x00000802, 0x04200802,
286         0x00200800, 0x00000002, 0x04000000, 0x00200800,
287         0x04000000, 0x00200800, 0x00200000, 0x04000802,
288         0x04000802, 0x04200002, 0x04200002, 0x00000002,
289         0x00200002, 0x04000000, 0x04000800, 0x00200000,
290         0x04200800, 0x00000802, 0x00200802, 0x04200800,
291         0x00000802, 0x04000002, 0x04200802, 0x04200000,
292         0x00200800, 0x00000000, 0x00000002, 0x04200802,
293         0x00000000, 0x00200802, 0x04200000, 0x00000800,
294         0x04000002, 0x04000800, 0x00000800, 0x00200002
295     };
296 
297     static int[] SP8 = {
298         0x10001040, 0x00001000, 0x00040000, 0x10041040,
299         0x10000000, 0x10001040, 0x00000040, 0x10000000,
300         0x00040040, 0x10040000, 0x10041040, 0x00041000,
301         0x10041000, 0x00041040, 0x00001000, 0x00000040,
302         0x10040000, 0x10000040, 0x10001000, 0x00001040,
303         0x00041000, 0x00040040, 0x10040040, 0x10041000,
304         0x00001040, 0x00000000, 0x00000000, 0x10040040,
305         0x10000040, 0x10001000, 0x00041040, 0x00040000,
306         0x00041040, 0x00040000, 0x10041000, 0x00001000,
307         0x00000040, 0x10040040, 0x00001000, 0x00041040,
308         0x10001000, 0x00000040, 0x10000040, 0x10040000,
309         0x10040040, 0x10000000, 0x00040000, 0x10001040,
310         0x00000000, 0x10041040, 0x00040040, 0x10000040,
311         0x10040000, 0x10001000, 0x10001040, 0x00000000,
312         0x10041040, 0x00041000, 0x00041000, 0x00001040,
313         0x00001040, 0x00040040, 0x10000000, 0x10041000
314     };
315 
316     /**
317      * generate an integer based working key based on our secret key
318      * and what we processing we are planning to do.
319      *
320      * Acknowledgements for this routine go to James Gillogly & Phil Karn.
321      *         (whoever, and wherever they are!).
322      */
323     protected int[] generateWorkingKey(
324         boolean encrypting,
325         byte[]  key)
326     {
327         int[]       newKey = new int[32];
328         boolean[]   pc1m = new boolean[56],
329                     pcr = new boolean[56];
330 
331         for (int j = 0; j < 56; j++ )
332         {
333             int    l = pc1[j];
334 
335             pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
336         }
337 
338         for (int i = 0; i < 16; i++)
339         {
340             int    l, m, n;
341 
342             if (encrypting)
343             {
344                 m = i << 1;
345             }
346             else
347             {
348                 m = (15 - i) << 1;
349             }
350 
351             n = m + 1;
352             newKey[m] = newKey[n] = 0;
353 
354             for (int j = 0; j < 28; j++)
355             {
356                 l = j + totrot[i];
357                 if ( l < 28 )
358                 {
359                     pcr[j] = pc1m[l];
360                 }
361                 else
362                 {
363                     pcr[j] = pc1m[l - 28];
364                 }
365             }
366 
367             for (int j = 28; j < 56; j++)
368             {
369                 l = j + totrot[i];
370                 if (l < 56 )
371                 {
372                     pcr[j] = pc1m[l];
373                 }
374                 else
375                 {
376                     pcr[j] = pc1m[l - 28];
377                 }
378             }
379 
380             for (int j = 0; j < 24; j++)
381             {
382                 if (pcr[pc2[j]])
383                 {
384                     newKey[m] |= bigbyte[j];
385                 }
386 
387                 if (pcr[pc2[j + 24]])
388                 {
389                     newKey[n] |= bigbyte[j];
390                 }
391             }
392         }
393 
394         //
395         // store the processed key
396         //
397         for (int i = 0; i != 32; i += 2)
398         {
399             int    i1, i2;
400 
401             i1 = newKey[i];
402             i2 = newKey[i + 1];
403 
404             newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
405                                    | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
406 
407             newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
408                                    | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
409         }
410 
411         return newKey;
412     }
413 
414     /**
415      * the DES engine.
416      */
417     protected void desFunc(
418         int[]   wKey,
419         byte[]  in,
420         int     inOff,
421         byte[]  out,
422         int     outOff)
423     {
424         int     work, right, left;
425 
426         left     = (in[inOff + 0] & 0xff) << 24;
427         left    |= (in[inOff + 1] & 0xff) << 16;
428         left    |= (in[inOff + 2] & 0xff) << 8;
429         left    |= (in[inOff + 3] & 0xff);
430 
431         right     = (in[inOff + 4] & 0xff) << 24;
432         right    |= (in[inOff + 5] & 0xff) << 16;
433         right    |= (in[inOff + 6] & 0xff) << 8;
434         right    |= (in[inOff + 7] & 0xff);
435 
436         work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
437         right ^= work;
438         left ^= (work << 4);
439         work = ((left >>> 16) ^ right) & 0x0000ffff;
440         right ^= work;
441         left ^= (work << 16);
442         work = ((right >>> 2) ^ left) & 0x33333333;
443         left ^= work;
444         right ^= (work << 2);
445         work = ((right >>> 8) ^ left) & 0x00ff00ff;
446         left ^= work;
447         right ^= (work << 8);
448         right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
449         work = (left ^ right) & 0xaaaaaaaa;
450         left ^= work;
451         right ^= work;
452         left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
453 
454         for (int round = 0; round < 8; round++)
455         {
456             int     fval;
457 
458             work  = (right << 28) | (right >>> 4);
459             work ^= wKey[round * 4 + 0];
460             fval  = SP7[ work      & 0x3f];
461             fval |= SP5[(work >>>  8) & 0x3f];
462             fval |= SP3[(work >>> 16) & 0x3f];
463             fval |= SP1[(work >>> 24) & 0x3f];
464             work  = right ^ wKey[round * 4 + 1];
465             fval |= SP8[ work      & 0x3f];
466             fval |= SP6[(work >>>  8) & 0x3f];
467             fval |= SP4[(work >>> 16) & 0x3f];
468             fval |= SP2[(work >>> 24) & 0x3f];
469             left ^= fval;
470             work  = (left << 28) | (left >>> 4);
471             work ^= wKey[round * 4 + 2];
472             fval  = SP7[ work      & 0x3f];
473             fval |= SP5[(work >>>  8) & 0x3f];
474             fval |= SP3[(work >>> 16) & 0x3f];
475             fval |= SP1[(work >>> 24) & 0x3f];
476             work  = left ^ wKey[round * 4 + 3];
477             fval |= SP8[ work      & 0x3f];
478             fval |= SP6[(work >>>  8) & 0x3f];
479             fval |= SP4[(work >>> 16) & 0x3f];
480             fval |= SP2[(work >>> 24) & 0x3f];
481             right ^= fval;
482         }
483 
484         right = (right << 31) | (right >>> 1);
485         work = (left ^ right) & 0xaaaaaaaa;
486         left ^= work;
487         right ^= work;
488         left = (left << 31) | (left >>> 1);
489         work = ((left >>> 8) ^ right) & 0x00ff00ff;
490         right ^= work;
491         left ^= (work << 8);
492         work = ((left >>> 2) ^ right) & 0x33333333;
493         right ^= work;
494         left ^= (work << 2);
495         work = ((right >>> 16) ^ left) & 0x0000ffff;
496         left ^= work;
497         right ^= (work << 16);
498         work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
499         left ^= work;
500         right ^= (work << 4);
501 
502         out[outOff + 0] = (byte)((right >>> 24) & 0xff);
503         out[outOff + 1] = (byte)((right >>> 16) & 0xff);
504         out[outOff + 2] = (byte)((right >>>  8) & 0xff);
505         out[outOff + 3] = (byte)( right         & 0xff);
506         out[outOff + 4] = (byte)((left >>> 24) & 0xff);
507         out[outOff + 5] = (byte)((left >>> 16) & 0xff);
508         out[outOff + 6] = (byte)((left >>>  8) & 0xff);
509         out[outOff + 7] = (byte)( left         & 0xff);
510     }
511 }