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-2019 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 1.9.6
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 //Initial permutation
50 #define DES_IP(left, right) \
51 { \
52  temp = ((left >> 4) ^ right) & 0x0F0F0F0F; \
53  right ^= temp; \
54  left ^= temp << 4; \
55  temp = ((left >> 16) ^ right) & 0x0000FFFF; \
56  right ^= temp; \
57  left ^= temp << 16; \
58  temp = ((right >> 2) ^ left) & 0x33333333; \
59  left ^= temp; \
60  right ^= temp << 2; \
61  temp = ((right >> 8) ^ left) & 0x00FF00FF; \
62  left ^= temp; \
63  right ^= temp << 8; \
64  temp = ((left >> 1) ^ right) & 0x55555555; \
65  right ^= temp; \
66  left ^= temp << 1; \
67  left = ROL32(left, 1); \
68  right = ROL32(right, 1); \
69 }
70 
71 //Final permutation
72 #define DES_FP(left, right) \
73 { \
74  left = ROR32(left, 1); \
75  right = ROR32(right, 1); \
76  temp = ((left >> 1) ^ right) & 0x55555555; \
77  right ^= temp; \
78  left ^= temp << 1; \
79  temp = ((right >> 8) ^ left) & 0x00FF00FF; \
80  left ^= temp; \
81  right ^= temp << 8; \
82  temp = ((right >> 2) ^ left) & 0x33333333; \
83  left ^= temp; \
84  right ^= temp << 2; \
85  temp = ((left >> 16) ^ right) & 0x0000FFFF; \
86  right ^= temp; \
87  left ^= temp << 16; \
88  temp = ((left >> 4) ^ right) & 0x0F0F0F0F; \
89  right ^= temp; \
90  left ^= temp << 4; \
91 }
92 
93 //DES round
94 #define DES_ROUND(left, right, ks) \
95 { \
96  temp = right ^ *(ks); \
97  left ^= sp2[(temp >> 24) & 0x3F]; \
98  left ^= sp4[(temp >> 16) & 0x3F]; \
99  left ^= sp6[(temp >> 8) & 0x3F]; \
100  left ^= sp8[temp & 0x3F]; \
101  temp = ROR32(right, 4) ^ *(ks + 1); \
102  left ^= sp1[(temp >> 24) & 0x3F]; \
103  left ^= sp3[(temp >> 16) & 0x3F]; \
104  left ^= sp5[(temp >> 8) & 0x3F]; \
105  left ^= sp7[temp & 0x3F]; \
106  temp = right; \
107  right = left; \
108  left = temp; \
109 }
110 
111 //Permuted choice 1
112 #define DES_PC1(left, right) \
113 { \
114  uint32_t temp; \
115  temp = ((left >> 4) ^ right) & 0x0F0F0F0F; \
116  right ^= temp; \
117  left ^= (temp << 4); \
118  temp = ((right >> 16) ^ left) & 0x0000FFFF; \
119  left ^= temp; \
120  right ^= (temp << 16); \
121  temp = ((left >> 2) ^ right) & 0x33333333; \
122  right ^= temp; \
123  left ^= (temp << 2); \
124  temp = ((right >> 16) ^ left) & 0x0000FFFF; \
125  left ^= temp; \
126  right ^= (temp << 16); \
127  temp = ((left >> 1) ^ right) & 0x55555555; \
128  right ^= temp; \
129  left ^= (temp << 1); \
130  temp = ((right >> 8) ^ left) & 0x00FF00FF; \
131  left ^= temp; \
132  right ^= (temp << 8); \
133  temp = ((left >> 1) ^ right) & 0x55555555; \
134  right ^= temp; \
135  left ^= (temp << 1); \
136  temp = (left << 8) | ((right >> 20) & 0x000000F0); \
137  left = ((right << 20) & 0x0FF00000); \
138  left |= ((right << 4) & 0x000FF000); \
139  left |= ((right >> 12) & 0x00000FF0); \
140  left |= ((right >> 28) & 0x0000000F); \
141  right = temp >> 4; \
142 }
143 
144 //Selection function 1
145 static const uint32_t sp1[64] =
146 {
147  0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
148  0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
149  0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
150  0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
151  0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
152  0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
153  0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
154  0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004
155 };
156 
157 //Selection function 2
158 static const uint32_t sp2[64] =
159 {
160  0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
161  0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
162  0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
163  0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
164  0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
165  0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
166  0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
167  0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000
168 };
169 
170 //Selection function 3
171 static const uint32_t sp3[64] =
172 {
173  0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
174  0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
175  0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
176  0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
177  0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
178  0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
179  0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
180  0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200
181 };
182 
183 //Selection function 4
184 static const uint32_t sp4[64] =
185 {
186  0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
187  0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
188  0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
189  0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
190  0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
191  0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
192  0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
193  0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080
194 };
195 
196 //Selection function 5
197 static const uint32_t sp5[64] =
198 {
199  0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
200  0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
201  0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
202  0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
203  0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
204  0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
205  0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
206  0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100
207 };
208 
209 //Selection function 6
210 static const uint32_t sp6[64] =
211 {
212  0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
213  0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
214  0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
215  0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
216  0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
217  0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
218  0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
219  0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010
220 };
221 
222 //Selection function 7
223 static const uint32_t sp7[64] =
224 {
225  0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
226  0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
227  0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
228  0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
229  0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
230  0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
231  0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
232  0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002
233 };
234 
235 //Selection function 8
236 static const uint32_t sp8[64] =
237 {
238  0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
239  0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
240  0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
241  0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
242  0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
243  0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
244  0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
245  0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000
246 };
247 
248 //Common interface for encryption algorithms
250 {
251  "DES",
252  sizeof(DesContext),
256  NULL,
257  NULL,
260 };
261 
262 
263 /**
264  * @brief Initialize a DES context using the supplied key
265  * @param[in] context Pointer to the DES context to initialize
266  * @param[in] key Pointer to the key
267  * @param[in] keyLen Length of the key (must be set to 8)
268  * @return Error code
269  **/
270 
271 error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
272 {
273  uint_t i;
274  uint32_t c;
275  uint32_t d;
276 
277  //Check parameters
278  if(context == NULL || key == NULL)
280 
281  //Invalid key length?
282  if(keyLen != 8)
284 
285  //Copy the key
286  c = LOAD32BE(key + 0);
287  d = LOAD32BE(key + 4);
288 
289  //Permuted choice 1
290  DES_PC1(c, d);
291 
292  //Generate the key schedule
293  for(i = 0; i < 16; i++)
294  {
295  //Individual blocks are shifted left
296  if(i == 0 || i == 1 || i == 8 || i == 15)
297  {
298  c = ROL28(c, 1);
299  d = ROL28(d, 1);
300  }
301  else
302  {
303  c = ROL28(c, 2);
304  d = ROL28(d, 2);
305  }
306 
307  //Permuted choice 2
308  context->ks[2 * i] =
309  ((c << 4) & 0x24000000) | ((c << 28) & 0x10000000) |
310  ((c << 14) & 0x08000000) | ((c << 18) & 0x02080000) |
311  ((c << 6) & 0x01000000) | ((c << 9) & 0x00200000) |
312  ((c >> 1) & 0x00100000) | ((c << 10) & 0x00040000) |
313  ((c << 2) & 0x00020000) | ((c >> 10) & 0x00010000) |
314  ((d >> 13) & 0x00002000) | ((d >> 4) & 0x00001000) |
315  ((d << 6) & 0x00000800) | ((d >> 1) & 0x00000400) |
316  ((d >> 14) & 0x00000200) | ((d) & 0x00000100) |
317  ((d >> 5) & 0x00000020) | ((d >> 10) & 0x00000010) |
318  ((d >> 3) & 0x00000008) | ((d >> 18) & 0x00000004) |
319  ((d >> 26) & 0x00000002) | ((d >> 24) & 0x00000001);
320 
321  context->ks[2 * i + 1] =
322  ((c << 15) & 0x20000000) | ((c << 17) & 0x10000000) |
323  ((c << 10) & 0x08000000) | ((c << 22) & 0x04000000) |
324  ((c >> 2) & 0x02000000) | ((c << 1) & 0x01000000) |
325  ((c << 16) & 0x00200000) | ((c << 11) & 0x00100000) |
326  ((c << 3) & 0x00080000) | ((c >> 6) & 0x00040000) |
327  ((c << 15) & 0x00020000) | ((c >> 4) & 0x00010000) |
328  ((d >> 2) & 0x00002000) | ((d << 8) & 0x00001000) |
329  ((d >> 14) & 0x00000808) | ((d >> 9) & 0x00000400) |
330  ((d) & 0x00000200) | ((d << 7) & 0x00000100) |
331  ((d >> 7) & 0x00000020) | ((d >> 3) & 0x00000011) |
332  ((d << 2) & 0x00000004) | ((d >> 21) & 0x00000002);
333  }
334 
335  //No error to report
336  return NO_ERROR;
337 }
338 
339 
340 /**
341  * @brief Encrypt a 8-byte block using DES algorithm
342  * @param[in] context Pointer to the DES context
343  * @param[in] input Plaintext block to encrypt
344  * @param[out] output Ciphertext block resulting from encryption
345  **/
346 
347 void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
348 {
349  uint_t i;
350  uint32_t left;
351  uint32_t right;
352  uint32_t temp;
353 
354  //Key schedule
355  uint32_t *ks = context->ks;
356 
357  //Copy the plaintext from the input buffer
358  left = LOAD32BE(input + 0);
359  right = LOAD32BE(input + 4);
360 
361  //Initial permutation
362  DES_IP(left, right);
363 
364  //16 rounds of computation are needed
365  for(i = 0; i < 16; i++, ks += 2)
366  {
367  DES_ROUND(left, right, ks);
368  }
369 
370  //Inverse IP permutation
371  DES_FP(right, left);
372 
373  //Copy the resulting ciphertext
374  STORE32BE(right, output + 0);
375  STORE32BE(left, output + 4);
376 }
377 
378 
379 /**
380  * @brief Decrypt a 8-byte block using DES algorithm
381  * @param[in] context Pointer to the DES context
382  * @param[in] input Ciphertext block to decrypt
383  * @param[out] output Plaintext block resulting from decryption
384  **/
385 
386 void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
387 {
388  uint_t i;
389  uint32_t left;
390  uint32_t right;
391  uint32_t temp;
392 
393  //Keys in the key schedule must be applied in reverse order
394  uint32_t *ks = context->ks + 30;
395 
396  //Copy the ciphertext from the input buffer
397  left = LOAD32BE(input + 0);
398  right = LOAD32BE(input + 4);
399 
400  //Initial permutation
401  DES_IP(left, right);
402 
403  //16 rounds of computation are needed
404  for(i = 0; i < 16; i++, ks -= 2)
405  {
406  DES_ROUND(left, right, ks);
407  }
408 
409  //Inverse IP permutation
410  DES_FP(right, left);
411 
412  //Copy the resulting plaintext
413  STORE32BE(right, output + 0);
414  STORE32BE(left, output + 4);
415 }
416 
417 #endif
#define DES_FP(left, right)
Definition: des.c:72
void(* CipherAlgoEncryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1103
#define LOAD32BE(p)
Definition: cpu_endian.h:194
@ CIPHER_ALGO_TYPE_BLOCK
Definition: crypto.h:1069
#define ROL28(a, n)
Definition: des.c:47
DES algorithm context.
Definition: des.h:52
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:42
void(* CipherAlgoDecryptBlock)(void *context, const uint8_t *input, uint8_t *output)
Definition: crypto.h:1104
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:105
General definitions for cryptographic algorithms.
void desEncryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Encrypt a 8-byte block using DES algorithm.
Definition: des.c:347
DES (Data Encryption Standard)
error_t(* CipherAlgoInit)(void *context, const uint8_t *key, size_t keyLen)
Definition: crypto.h:1100
#define DES_IP(left, right)
Definition: des.c:50
#define DES_BLOCK_SIZE
Definition: des.h:38
Common interface for encryption algorithms.
Definition: crypto.h:1150
error_t desInit(DesContext *context, const uint8_t *key, size_t keyLen)
Initialize a DES context using the supplied key.
Definition: des.c:271
void desDecryptBlock(DesContext *context, const uint8_t *input, uint8_t *output)
Decrypt a 8-byte block using DES algorithm.
Definition: des.c:386
unsigned int uint_t
Definition: compiler_port.h:45
#define DES_ROUND(left, right, ks)
Definition: des.c:94
const CipherAlgo desCipherAlgo
Definition: des.c:249
uint32_t ks[32]
Definition: des.h:54
#define STORE32BE(a, p)
Definition: cpu_endian.h:270
#define DES_PC1(left, right)
Definition: des.c:112
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513