des.c
Go to the documentation of this file.
1 /**
2  * @file des.c
3  * @brief DES (Data Encryption Standard)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * DES is an encryption algorithm designed to encipher and decipher blocks of
30  * 64 bits under control of a 64-bit key. Refer to FIPS 46-3 for more details
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.4.4
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "cipher/des.h"
42 
43 //Check crypto library configuration
44 #if (DES_SUPPORT == ENABLED || DES3_SUPPORT == ENABLED)
45 
46 //Rotate left operation
47 #define ROL28(a, n) ((((a) << (n)) | ((a) >> (28 - (n)))) & 0x0FFFFFFF)
48 
49 //Permutation of bit fields between words (Eric Young's technique)
50 #define SWAPMOVE(a, b, n, m) \
51 { \
52  t = ((a >> n) ^ b) & m; \
53  b ^= t; \
54  a ^= t << n; \
55 }
56 
57 //Initial permutation
58 #define IP(l, r) \
59 { \
60  SWAPMOVE(l, r, 4, 0x0F0F0F0F); \
61  SWAPMOVE(l, r, 16, 0x0000FFFF); \
62  SWAPMOVE(r, l, 2, 0x33333333); \
63  SWAPMOVE(r, l, 8, 0x00FF00FF); \
64  SWAPMOVE(l, r, 1, 0x55555555); \
65  l = ROL32(l, 1); \
66  r = ROL32(r, 1); \
67 }
68 
69 //Inverse of initial permutation
70 #define IP_INV(l, r) \
71 { \
72  l = ROR32(l, 1); \
73  r = ROR32(r, 1); \
74  SWAPMOVE(l, r, 1, 0x55555555); \
75  SWAPMOVE(r, l, 8, 0x00FF00FF); \
76  SWAPMOVE(r, l, 2, 0x33333333); \
77  SWAPMOVE(l, r, 16, 0x0000FFFF); \
78  SWAPMOVE(l, r, 4, 0x0F0F0F0F); \
79 }
80 
81 //Permuted choice 1
82 #define PC1(c, d) \
83 { \
84  SWAPMOVE(c, d, 4, 0x0F0F0F0F); \
85  SWAPMOVE(c, d, 16, 0x0000FFFF); \
86  SWAPMOVE(d, c, 2, 0x33333333); \
87  SWAPMOVE(d, c, 8, 0x00FF00FF); \
88  SWAPMOVE(c, d, 1, 0x55555555); \
89  SWAPMOVE(d, c, 8, 0x00FF00FF); \
90  SWAPMOVE(c, d, 16, 0x0000FFFF); \
91  t = (c << 4) & 0x0FFFFFF0; \
92  t |= (d >> 24) & 0x0000000F; \
93  c = (d << 20) & 0x0FF00000; \
94  c |= (d << 4) & 0x000FF000; \
95  c |= (d >> 12) & 0x00000FF0; \
96  c |= (d >> 28) & 0x0000000F; \
97  d = t; \
98 }
99 
100 //Permuted choice 2 (first half)
101 #define PC2_L(c, d) \
102  (((c << 4) & 0x24000000) | \
103  ((c << 28) & 0x10000000) | \
104  ((c << 14) & 0x08000000) | \
105  ((c << 18) & 0x02080000) | \
106  ((c << 6) & 0x01000000) | \
107  ((c << 9) & 0x00200000) | \
108  ((c >> 1) & 0x00100000) | \
109  ((c << 10) & 0x00040000) | \
110  ((c << 2) & 0x00020000) | \
111  ((c >> 10) & 0x00010000) | \
112  ((d >> 13) & 0x00002000) | \
113  ((d >> 4) & 0x00001000) | \
114  ((d << 6) & 0x00000800) | \
115  ((d >> 1) & 0x00000400) | \
116  ((d >> 14) & 0x00000200) | \
117  ((d >> 0) & 0x00000100) | \
118  ((d >> 5) & 0x00000020) | \
119  ((d >> 10) & 0x00000010) | \
120  ((d >> 3) & 0x00000008) | \
121  ((d >> 18) & 0x00000004) | \
122  ((d >> 26) & 0x00000002) | \
123  ((d >> 24) & 0x00000001))
124 
125 //Permuted choice 2 (second half)
126 #define PC2_R(c, d) \
127  (((c << 15) & 0x20000000) | \
128  ((c << 17) & 0x10000000) | \
129  ((c << 10) & 0x08000000) | \
130  ((c << 22) & 0x04000000) | \
131  ((c >> 2) & 0x02000000) | \
132  ((c << 1) & 0x01000000) | \
133  ((c << 16) & 0x00200000) | \
134  ((c << 11) & 0x00100000) | \
135  ((c << 3) & 0x00080000) | \
136  ((c >> 6) & 0x00040000) | \
137  ((c << 15) & 0x00020000) | \
138  ((c >> 4) & 0x00010000) | \
139  ((d >> 2) & 0x00002000) | \
140  ((d << 8) & 0x00001000) | \
141  ((d >> 14) & 0x00000808) | \
142  ((d >> 9) & 0x00000400) | \
143  ((d >> 0) & 0x00000200) | \
144  ((d << 7) & 0x00000100) | \
145  ((d >> 7) & 0x00000020) | \
146  ((d >> 3) & 0x00000011) | \
147  ((d << 2) & 0x00000004) | \
148  ((d >> 21) & 0x00000002))
149 
150 //Round function
151 #define ROUND(l, r, k1, k2) \
152 { \
153  t = r ^ k1; \
154  l ^= sp2[(t >> 24) & 0x3F]; \
155  l ^= sp4[(t >> 16) & 0x3F]; \
156  l ^= sp6[(t >> 8) & 0x3F]; \
157  l ^= sp8[t & 0x3F]; \
158  t = ROR32(r, 4) ^ k2; \
159  l ^= sp1[(t >> 24) & 0x3F]; \
160  l ^= sp3[(t >> 16) & 0x3F]; \
161  l ^= sp5[(t >> 8) & 0x3F]; \
162  l ^= sp7[t & 0x3F]; \
163 }
164 
165 //Selection function 1
166 static const uint32_t sp1[64] =
167 {
168  0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
169  0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
170  0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
171  0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
172  0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
173  0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
174  0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
175  0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004
176 };
177 
178 //Selection function 2
179 static const uint32_t sp2[64] =
180 {
181  0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
182  0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
183  0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
184  0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
185  0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
186  0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
187  0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
188  0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000
189 };
190 
191 //Selection function 3
192 static const uint32_t sp3[64] =
193 {
194  0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
195  0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
196  0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
197  0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
198  0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
199  0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
200  0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
201  0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200
202 };
203 
204 //Selection function 4
205 static const uint32_t sp4[64] =
206 {
207  0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
208  0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
209  0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
210  0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
211  0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
212  0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
213  0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
214  0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080
215 };
216 
217 //Selection function 5
218 static const uint32_t sp5[64] =
219 {
220  0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
221  0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
222  0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
223  0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
224  0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
225  0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
226  0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
227  0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100
228 };
229 
230 //Selection function 6
231 static const uint32_t sp6[64] =
232 {
233  0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
234  0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
235  0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
236  0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
237  0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
238  0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
239  0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
240  0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010
241 };
242 
243 //Selection function 7
244 static const uint32_t sp7[64] =
245 {
246  0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
247  0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
248  0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
249  0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
250  0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
251  0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
252  0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
253  0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002
254 };
255 
256 //Selection function 8
257 static const uint32_t sp8[64] =
258 {
259  0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
260  0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
261  0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
262  0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
263  0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
264  0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
265  0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
266  0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000
267 };
268 
269 //DES-CBC OID (1.3.14.3.2.7)
270 const uint8_t DES_CBC_OID[5] = {0x2B, 0x0E, 0x03, 0x02, 0x07};
271 
272 //Common interface for encryption algorithms
274 {
275  "DES",
276  sizeof(DesContext),
280  NULL,
281  NULL,
285 };
286 
287 
288 /**
289  * @brief Initialize a DES context using the supplied key
290  * @param[in] context Pointer to the DES context to initialize
291  * @param[in] key Pointer to the key
292  * @param[in] keyLen Length of the key (must be set to 8)
293  * @return Error code
294  **/
295 
296 __weak_func error_t desInit(DesContext *context, const uint8_t *key,
297  size_t keyLen)
298 {
299  uint_t i;
300  uint32_t c;
301  uint32_t d;
302  uint32_t t;
303 
304  //Check parameters
305  if(context == NULL || key == NULL)
307 
308  //Invalid key length?
309  if(keyLen != 8)
311 
312  //Copy the key
313  c = LOAD32BE(key + 0);
314  d = LOAD32BE(key + 4);
315 
316  //Permuted choice 1
317  PC1(c, d);
318 
319  //Generate the key schedule
320  for(i = 0; i < 16; i++)
321  {
322  //Individual blocks are shifted left
323  if(i == 0 || i == 1 || i == 8 || i == 15)
324  {
325  c = ROL28(c, 1);
326  d = ROL28(d, 1);
327  }
328  else
329  {
330  c = ROL28(c, 2);
331  d = ROL28(d, 2);
332  }
333 
334  //Permuted choice 2
335  context->ks[2 * i] = PC2_L(c, d);
336  context->ks[2 * i + 1] = PC2_R(c, d);
337  }
338 
339  //No error to report
340  return NO_ERROR;
341 }
342 
343 
344 /**
345  * @brief Encrypt a 8-byte block using DES algorithm
346  * @param[in] context Pointer to the DES context
347  * @param[in] input Plaintext block to encrypt
348  * @param[out] output Ciphertext block resulting from encryption
349  **/
350 
351 __weak_func void desEncryptBlock(DesContext *context, const uint8_t *input,
352  uint8_t *output)
353 {
354  uint_t i;
355  uint32_t l;
356  uint32_t r;
357  uint32_t t;
358 
359  //Copy the plaintext from the input buffer
360  l = LOAD32BE(input + 0);
361  r = LOAD32BE(input + 4);
362 
363  //Initial permutation
364  IP(l, r);
365 
366  //16 rounds of computation are needed
367  for(i = 0; i < 32; i += 4)
368  {
369  //Apply odd round function
370  ROUND(l, r, context->ks[i], context->ks[i + 1]);
371  //Apply even round function
372  ROUND(r, l, context->ks[i + 2], context->ks[i + 3]);
373  }
374 
375  //Inverse of initial permutation
376  IP_INV(r, l);
377 
378  //Copy the resulting ciphertext
379  STORE32BE(r, output + 0);
380  STORE32BE(l, output + 4);
381 }
382 
383 
384 /**
385  * @brief Decrypt a 8-byte block using DES algorithm
386  * @param[in] context Pointer to the DES context
387  * @param[in] input Ciphertext block to decrypt
388  * @param[out] output Plaintext block resulting from decryption
389  **/
390 
391 __weak_func void desDecryptBlock(DesContext *context, const uint8_t *input,
392  uint8_t *output)
393 {
394  uint_t i;
395  uint32_t l;
396  uint32_t r;
397  uint32_t t;
398 
399  //Copy the ciphertext from the input buffer
400  r = LOAD32BE(input + 0);
401  l = LOAD32BE(input + 4);
402 
403  //Initial permutation
404  IP(r, l);
405 
406  //For decryption, keys in the key schedule must be applied in reverse order
407  for(i = 32; i > 0; i -= 4)
408  {
409  //Apply even round function
410  ROUND(r, l, context->ks[i - 2], context->ks[i - 1]);
411  //Apply odd round function
412  ROUND(l, r, context->ks[i - 4], context->ks[i - 3]);
413  }
414 
415  //Inverse of initial permutation
416  IP_INV(l, r);
417 
418  //Copy the resulting plaintext
419  STORE32BE(l, output + 0);
420  STORE32BE(r, output + 4);
421 }
422 
423 
424 /**
425  * @brief Release DES context
426  * @param[in] context Pointer to the DES context
427  **/
428 
429 __weak_func void desDeinit(DesContext *context)
430 {
431  //Clear DES context
432  osMemset(context, 0, sizeof(DesContext));
433 }
434 
435 #endif
void(* CipherAlgoEncryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1009
#define LOAD32BE(p)
Definition: cpu_endian.h:210
@ CIPHER_ALGO_TYPE_BLOCK
Definition: crypto.h:953
uint8_t t
Definition: lldp_ext_med.h:212
#define ROL28(a, n)
Definition: des.c:47
#define PC2_L(c, d)
Definition: des.c:101
const uint8_t DES_CBC_OID[5]
Definition: des.c:270
#define IP(l, r)
Definition: des.c:58
uint8_t r
Definition: ndp.h:346
DES algorithm context.
Definition: des.h:58
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:43
void(* CipherAlgoDecryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1012
#define PC1(c, d)
Definition: des.c:82
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
General definitions for cryptographic algorithms.
__weak_func error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
Initialize a DES context using the supplied key.
Definition: des.c:296
#define PC2_R(c, d)
Definition: des.c:126
__weak_func void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using DES algorithm.
Definition: des.c:391
#define ROUND(l, r, k1, k2)
Definition: des.c:151
DES (Data Encryption Standard)
error_t(* CipherAlgoInit)(void *context, const uint8_t *key, size_t keyLen)
Definition: crypto.h:1000
#define IP_INV(l, r)
Definition: des.c:70
uint8_t l
Definition: ndp.h:412
#define DES_BLOCK_SIZE
Definition: des.h:43
Common interface for encryption algorithms.
Definition: crypto.h:1068
__weak_func void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using DES algorithm.
Definition: des.c:351
__weak_func void desDeinit(DesContext *context)
Release DES context.
Definition: des.c:429
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
void(* CipherAlgoDeinit)(void *context)
Definition: crypto.h:1015
const CipherAlgo desCipherAlgo
Definition: des.c:273
uint32_t ks[32]
Definition: des.h:59
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514