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