1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   DES Encryption Standard (DES)                                       */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #include "nx_api.h"
24 #include "nx_des.h"
25 
26 
27 /* Define macros for the DES transform function.  */
28 
29 
30 /* Define the eight S-box data structures used in the permutation. Keep them static, since there is no
31    reason to have these symbols referenced outside this file. */
32 
33 static ULONG sb1[64] =
34 {
35 
36     0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
37     0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
38     0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
39     0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
40     0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
41     0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
42     0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
43     0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
44 };
45 
46 static ULONG sb2[64] =
47 {
48 
49     0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
50     0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
51     0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
52     0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
53     0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
54     0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
55     0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
56     0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
57 };
58 
59 static ULONG sb3[64] =
60 {
61 
62     0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
63     0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
64     0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
65     0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
66     0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
67     0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
68     0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
69     0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
70 };
71 
72 static ULONG sb4[64] =
73 {
74 
75     0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
76     0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
77     0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
78     0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
79     0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
80     0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
81     0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
82     0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
83 };
84 
85 static ULONG sb5[64] =
86 {
87 
88     0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
89     0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
90     0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
91     0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
92     0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
93     0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
94     0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
95     0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
96 };
97 
98 static ULONG sb6[64] =
99 {
100 
101     0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
102     0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
103     0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
104     0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
105     0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
106     0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
107     0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
108     0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
109 };
110 
111 static ULONG sb7[64] =
112 {
113 
114     0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
115     0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
116     0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
117     0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
118     0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
119     0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
120     0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
121     0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
122 };
123 
124 static ULONG sb8[64] =
125 {
126 
127     0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
128     0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
129     0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
130     0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
131     0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
132     0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
133     0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
134     0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
135 };
136 
137 
138 /* Define the left half bit swap table.  */
139 
140 static ULONG left_half_bit_swap[16] =
141 {
142 
143     0x00000000UL, 0x00000001UL, 0x00000100UL, 0x00000101UL,
144     0x00010000UL, 0x00010001UL, 0x00010100UL, 0x00010101UL,
145     0x01000000UL, 0x01000001UL, 0x01000100UL, 0x01000101UL,
146     0x01010000UL, 0x01010001UL, 0x01010100UL, 0x01010101UL
147 };
148 
149 /* Define the right half bit swap table.  */
150 
151 static ULONG right_half_bit_swap[16] =
152 {
153   0x00000000UL, 0x01000000UL, 0x00010000UL, 0x01010000UL,
154   0x00000100UL, 0x01000100UL, 0x00010100UL, 0x01010100UL,
155   0x00000001UL, 0x01000001UL, 0x00010001UL, 0x01010001UL,
156   0x00000101UL, 0x01000101UL, 0x00010101UL, 0x01010101UL
157 };
158 
159 
160 /**************************************************************************/
161 /*                                                                        */
162 /*  FUNCTION                                               RELEASE        */
163 /*                                                                        */
164 /*    _nx_des_key_set                                     PORTABLE C      */
165 /*                                                           6.1          */
166 /*  AUTHOR                                                                */
167 /*                                                                        */
168 /*    Yuxin Zhou, Microsoft Corporation                                   */
169 /*                                                                        */
170 /*  DESCRIPTION                                                           */
171 /*                                                                        */
172 /*    This function sets up the 32 encryption keys as well as the 32      */
173 /*    decryption keys for the DES algorithm. It must be called before     */
174 /*    either _nx_des_encrypt or _nx_des_decrypt can be called.            */
175 /*    destination.                                                        */
176 /*                                                                        */
177 /*  INPUT                                                                 */
178 /*                                                                        */
179 /*    context                               DES context pointer           */
180 /*    key                                   8-byte (64-bit) key           */
181 /*                                                                        */
182 /*  OUTPUT                                                                */
183 /*                                                                        */
184 /*    status                                Completion status             */
185 /*                                                                        */
186 /*  CALLS                                                                 */
187 /*                                                                        */
188 /*    None                                                                */
189 /*                                                                        */
190 /*  CALLED BY                                                             */
191 /*                                                                        */
192 /*    NetX Applications                                                   */
193 /*                                                                        */
194 /*  RELEASE HISTORY                                                       */
195 /*                                                                        */
196 /*    DATE              NAME                      DESCRIPTION             */
197 /*                                                                        */
198 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
199 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
200 /*                                            resulting in version 6.1    */
201 /*                                                                        */
202 /**************************************************************************/
_nx_des_key_set(NX_DES * context,UCHAR key[8])203 UINT  _nx_des_key_set(NX_DES *context, UCHAR key[8])
204 {
205 
206 ULONG   left, right, temp;
207 ULONG   *encrypt_keys_ptr;
208 ULONG   *decrypt_keys_ptr;
209 UINT    round;
210 
211 
212     /* Determine if the context is non-null.  */
213     if (context == NX_NULL)
214         return(NX_PTR_ERROR);
215 
216     /* First, convert the 8-byte raw key into two ULONG halves, in an endian neutral fashion.  */
217     left =  (((ULONG) key[0]) << 24) | (((ULONG) key[1]) << 16) | (((ULONG) key[2]) << 8) | ((ULONG) key[3]);
218     right =  (((ULONG) key[4]) << 24) | (((ULONG) key[5]) << 16) | (((ULONG) key[6]) << 8) | ((ULONG) key[7]);
219 
220     /* Perform permutation on the key halves.  */
221     temp =  ((right >> 4) ^ left) & 0x0F0F0F0FUL;
222     left =  left ^ temp;
223     right =  right ^ (temp << 4);
224     temp =  (right ^ left) & 0x10101010;
225     left =  left ^ temp;
226     right =  right ^ temp;
227 
228     left =  (left_half_bit_swap[(left) & 0xf] << 3) | (left_half_bit_swap[(left >> 8) & 0xf] << 2) |
229             (left_half_bit_swap[(left >> 16) & 0xf] << 1) | (left_half_bit_swap[(left >> 24) & 0xf]) |
230             (left_half_bit_swap[(left >> 5) & 0xf] << 7) | (left_half_bit_swap[(left >> 13) & 0xf] << 6) |
231             (left_half_bit_swap[(left >> 21) & 0xf] << 5) | (left_half_bit_swap[(left >> 29) & 0xf] << 4);
232     left =  left & 0x0fffffff;
233 
234     right = (right_half_bit_swap[(right >> 1) & 0xf] << 3) | (right_half_bit_swap[(right >> 9) & 0xf] << 2) |
235             (right_half_bit_swap[(right >> 17) & 0xf] << 1) | (right_half_bit_swap[(right >> 25) & 0xf]) |
236             (right_half_bit_swap[(right >> 4) & 0xf] << 7) | (right_half_bit_swap[(right >> 12) & 0xf] << 6) |
237             (right_half_bit_swap[(right >> 20) & 0xf] << 5) | (right_half_bit_swap[(right >> 28) & 0xf] << 4);
238     right = right & 0x0fffffff;
239 
240     /* Setup encryption keys pointer.  */
241     encrypt_keys_ptr =  context -> nx_des_encryption_keys;
242 
243     /* Calculate the encryption keys.  */
244     for (round = 0; round < 16; round++)
245     {
246 
247         /* Modify the left and right portions of the keys.  */
248         if ((round < 2) || (round == 8) || (round == 15))
249         {
250 
251             left =   ((left << 1) | (left >> 27)) & 0x0FFFFFFFUL;
252             right =  ((right << 1) | (right >> 27)) & 0x0FFFFFFFUL;
253         }
254         else
255         {
256 
257             left =   ((left << 2) | (left >> 26)) & 0x0FFFFFFFUL;
258             right =  ((right << 2) | (right >> 26)) & 0x0FFFFFFFUL;
259         }
260 
261         /* Setup the key.  */
262         *encrypt_keys_ptr++ =  ((left << 4)   & 0x24000000UL) | ((left << 28)  & 0x10000000UL) |
263                                ((left << 14)  & 0x08000000UL) | ((left << 18)  & 0x02080000UL) |
264                                ((left << 6)   & 0x01000000UL) | ((left << 9)   & 0x00200000UL) |
265                                ((left >> 1)   & 0x00100000UL) | ((left << 10)  & 0x00040000UL) |
266                                ((left << 2)   & 0x00020000UL) | ((left >> 10)  & 0x00010000UL) |
267                                ((right >> 13) & 0x00002000UL) | ((right >> 4)  & 0x00001000UL) |
268                                ((right << 6)  & 0x00000800UL) | ((right >> 1)  & 0x00000400UL) |
269                                ((right >> 14) & 0x00000200UL) | (right         & 0x00000100UL) |
270                                ((right >> 5)  & 0x00000020UL) | ((right >> 10) & 0x00000010UL) |
271                                ((right >> 3)  & 0x00000008UL) | ((right >> 18) & 0x00000004UL) |
272                                ((right >> 26) & 0x00000002UL) | ((right >> 24) & 0x00000001UL);
273 
274         /* Setup the next key.  */
275         *encrypt_keys_ptr++ =  ((left << 15)  & 0x20000000UL) | ((left << 17)  & 0x10000000UL) |
276                                ((left << 10)  & 0x08000000UL) | ((left << 22)  & 0x04000000UL) |
277                                ((left >> 2)   & 0x02000000UL) | ((left << 1)   & 0x01000000UL) |
278                                ((left << 16)  & 0x00200000UL) | ((left << 11)  & 0x00100000UL) |
279                                ((left << 3)   & 0x00080000UL) | ((left >> 6)   & 0x00040000UL) |
280                                ((left << 15)  & 0x00020000UL) | ((left >> 4)   & 0x00010000UL) |
281                                ((right >> 2)  & 0x00002000UL) | ((right << 8)  & 0x00001000UL) |
282                                ((right >> 14) & 0x00000808UL) | ((right >> 9)  & 0x00000400UL) |
283                                ((right)       & 0x00000200UL) | ((right << 7)  & 0x00000100UL) |
284                                ((right >> 7)  & 0x00000020UL) | ((right >> 3)  & 0x00000011UL) |
285                                ((right << 2)  & 0x00000004UL) | ((right >> 21) & 0x00000002UL);
286     }
287 
288     /* Reposition the encryption key pointer.  */
289     encrypt_keys_ptr =  encrypt_keys_ptr - 2;
290 
291     /* Setup decryption pointer.  */
292     decrypt_keys_ptr =  context -> nx_des_decryption_keys;
293 
294     /* Now setup decryption keys.  */
295     for (round = 0; round < 16; round++)
296     {
297 
298         /* Copy the reverse of the encryption keys.  */
299         *decrypt_keys_ptr++ =  *encrypt_keys_ptr;
300         *decrypt_keys_ptr++ =  *(encrypt_keys_ptr + 1);
301 
302         /* Adjust the encryption keys pointer.  */
303         encrypt_keys_ptr =  encrypt_keys_ptr - 2;
304     }
305 
306     /* Return successful completion.  */
307     return(NX_SUCCESS);
308 }
309 
310 
311 /**************************************************************************/
312 /*                                                                        */
313 /*  FUNCTION                                               RELEASE        */
314 /*                                                                        */
315 /*    _nx_des_encrypt                                     PORTABLE C      */
316 /*                                                           6.1          */
317 /*  AUTHOR                                                                */
318 /*                                                                        */
319 /*    Yuxin Zhou, Microsoft Corporation                                   */
320 /*                                                                        */
321 /*  DESCRIPTION                                                           */
322 /*                                                                        */
323 /*    This function uses the DES algorithm to encrypt 8-bytes (64-bits).  */
324 /*    The result is 8 encrypted bytes. Note that the caller must make     */
325 /*    sure the source and destination are 8-bytes in size!                */
326 /*                                                                        */
327 /*  INPUT                                                                 */
328 /*                                                                        */
329 /*    context                               DES context pointer           */
330 /*    source                                8-byte source                 */
331 /*    destination                           8-byte destination            */
332 /*                                                                        */
333 /*  OUTPUT                                                                */
334 /*                                                                        */
335 /*    status                                Completion status             */
336 /*                                                                        */
337 /*  CALLS                                                                 */
338 /*                                                                        */
339 /*    _nx_des_process_block                 Encrypt 8-bytes of source     */
340 /*                                                                        */
341 /*  CALLED BY                                                             */
342 /*                                                                        */
343 /*    NetX Applications                                                   */
344 /*                                                                        */
345 /*  RELEASE HISTORY                                                       */
346 /*                                                                        */
347 /*    DATE              NAME                      DESCRIPTION             */
348 /*                                                                        */
349 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
350 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
351 /*                                            resulting in version 6.1    */
352 /*                                                                        */
353 /**************************************************************************/
_nx_des_encrypt(NX_DES * context,UCHAR source[8],UCHAR destination[8])354 UINT  _nx_des_encrypt(NX_DES *context, UCHAR source[8], UCHAR destination[8])
355 {
356 
357     /* Determine if the context is non-null.  */
358     if (context == NX_NULL)
359         return(NX_PTR_ERROR);
360 
361     /* Encrypt the block by supplying the encryption key set.  */
362     _nx_des_process_block(source, destination, context -> nx_des_encryption_keys);
363 
364     /* Return successful completion.  */
365     return(NX_SUCCESS);
366 }
367 
368 
369 /**************************************************************************/
370 /*                                                                        */
371 /*  FUNCTION                                               RELEASE        */
372 /*                                                                        */
373 /*    _nx_des_decrypt                                     PORTABLE C      */
374 /*                                                           6.1          */
375 /*  AUTHOR                                                                */
376 /*                                                                        */
377 /*    Yuxin Zhou, Microsoft Corporation                                   */
378 /*                                                                        */
379 /*  DESCRIPTION                                                           */
380 /*                                                                        */
381 /*    This function uses the DES algorithm to decrypt 8-bytes (64-bits).  */
382 /*    The result is 8 original source bytes. Note that the caller must    */
383 /*    make sure the source and destination are 8-bytes in size!           */
384 /*                                                                        */
385 /*  INPUT                                                                 */
386 /*                                                                        */
387 /*    context                               DES context pointer           */
388 /*    source                                8-byte source                 */
389 /*    destination                           8-byte destination            */
390 /*                                                                        */
391 /*  OUTPUT                                                                */
392 /*                                                                        */
393 /*    status                                Completion status             */
394 /*                                                                        */
395 /*  CALLS                                                                 */
396 /*                                                                        */
397 /*    _nx_des_process_block                 Decrypt 8-bytes of source     */
398 /*                                                                        */
399 /*  CALLED BY                                                             */
400 /*                                                                        */
401 /*    NetX Applications                                                   */
402 /*                                                                        */
403 /*  RELEASE HISTORY                                                       */
404 /*                                                                        */
405 /*    DATE              NAME                      DESCRIPTION             */
406 /*                                                                        */
407 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
408 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
409 /*                                            resulting in version 6.1    */
410 /*                                                                        */
411 /**************************************************************************/
_nx_des_decrypt(NX_DES * context,UCHAR source[8],UCHAR destination[8])412 UINT  _nx_des_decrypt(NX_DES *context, UCHAR source[8], UCHAR destination[8])
413 {
414 
415     /* Determine if the context is non-null.  */
416     if (context == NX_NULL)
417         return(NX_PTR_ERROR);
418 
419     /* Decrypt the block by supplying the decryption key set.  */
420     _nx_des_process_block(source, destination, context -> nx_des_decryption_keys);
421 
422     /* Return successful completion.  */
423     return(NX_SUCCESS);
424 }
425 
426 
427 /**************************************************************************/
428 /*                                                                        */
429 /*  FUNCTION                                               RELEASE        */
430 /*                                                                        */
431 /*    _nx_des_process_block                               PORTABLE C      */
432 /*                                                           6.1          */
433 /*  AUTHOR                                                                */
434 /*                                                                        */
435 /*    Yuxin Zhou, Microsoft Corporation                                   */
436 /*                                                                        */
437 /*  DESCRIPTION                                                           */
438 /*                                                                        */
439 /*    This function uses the DES algorithm to decrypt 8-bytes (64-bits).  */
440 /*    The result is 8 original source bytes. Note that the caller must    */
441 /*    make sure the source and destination are 8-bytes in size!           */
442 /*                                                                        */
443 /*  INPUT                                                                 */
444 /*                                                                        */
445 /*    source                                8-byte source                 */
446 /*    destination                           8-byte destination            */
447 /*    keys                                  Pointer to either the encrypt */
448 /*                                            or decrypt keys             */
449 /*                                                                        */
450 /*  OUTPUT                                                                */
451 /*                                                                        */
452 /*    status                                Completion status             */
453 /*                                                                        */
454 /*  CALLS                                                                 */
455 /*                                                                        */
456 /*    None                                                                */
457 /*                                                                        */
458 /*  CALLED BY                                                             */
459 /*                                                                        */
460 /*    NetX Applications                                                   */
461 /*                                                                        */
462 /*  RELEASE HISTORY                                                       */
463 /*                                                                        */
464 /*    DATE              NAME                      DESCRIPTION             */
465 /*                                                                        */
466 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
467 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
468 /*                                            resulting in version 6.1    */
469 /*                                                                        */
470 /**************************************************************************/
_nx_des_process_block(UCHAR source[8],UCHAR destination[8],ULONG keys[32])471 VOID  _nx_des_process_block(UCHAR source[8], UCHAR destination[8], ULONG keys[32])
472 {
473 
474 ULONG   left, right, temp;
475 ULONG   *key_ptr;
476 UINT    round;
477 
478 
479     /* First, convert the 8-byte source into two ULONG halves, in an endian neutral fashion.  */
480     left =  (((ULONG) source[0]) << 24) | (((ULONG) source[1]) << 16) | (((ULONG) source[2]) << 8) | ((ULONG) source[3]);
481     right =  (((ULONG) source[4]) << 24) | (((ULONG) source[5]) << 16) | (((ULONG) source[6]) << 8) | ((ULONG) source[7]);
482 
483     /* Compute the initial permutation.  */
484     temp =   ((left >> 4) ^ right) & 0x0F0F0F0FUL;
485     right =  right ^ temp;
486     left =   left ^ (temp << 4);
487     temp =   ((left >> 16) ^ right) & 0x0000FFFFUL;
488     right =  right ^ temp;
489     left =   left ^ (temp << 16);
490     temp =   ((right >> 2) ^ left) & 0x33333333UL;
491     left =   left ^ temp;
492     right =  right ^ (temp << 2);
493     temp =   ((right >> 8) ^ left) & 0x00FF00FFUL;
494     left =   left ^ temp;
495     right =  right ^ (temp << 8);
496     right =  ((right << 1) | (right >> 31)) & 0xFFFFFFFFUL;
497     temp =   (left ^ right) & 0xAAAAAAAAUL;
498     right =  right ^ temp;
499     left =   left ^ temp;
500     left =   ((left << 1) | (left >> 31)) & 0xFFFFFFFFUL;
501 
502     /* Setup pointer to input keys.  */
503     key_ptr =  keys;
504 
505     /* Now process the 16 rounds of the DES computation. There are two rounds per
506        loop.  */
507     for (round = 0; round < 8; round++)
508     {
509 
510         /* Calculate the left half.  */
511         temp =  *key_ptr++ ^ right;
512         left =  left ^ sb8[temp & 0x3F] ^ sb6[(temp >> 8) & 0x3F] ^ sb4[(temp >> 16) & 0x3F] ^ sb2[(temp >> 24) & 0x3F];
513 
514         temp =  *key_ptr++ ^ ((right << 28) | (right >> 4));
515         left =  left ^ sb7[temp & 0x3F] ^ sb5[(temp >> 8) & 0x3F] ^ sb3[(temp >> 16) & 0x3F] ^ sb1[(temp >> 24) & 0x3F];
516 
517         /* Calculate the right half.  */
518         temp =  *key_ptr++ ^ left;
519         right =  right ^ sb8[temp & 0x3F] ^ sb6[(temp >> 8) & 0x3F] ^ sb4[(temp >> 16) & 0x3F] ^ sb2[(temp >> 24) & 0x3F];
520 
521         temp =  *key_ptr++ ^ ((left << 28) | (left >> 4));
522         right =  right ^ sb7[temp & 0x3F] ^ sb5[(temp >> 8) & 0x3F] ^ sb3[(temp >> 16) & 0x3F] ^ sb1[(temp >> 24) & 0x3F];
523     }
524 
525     /* Now compute the final permutation.  */
526     right =  ((right << 31) | (right >> 1)) & 0xFFFFFFFFUL;
527     temp =   (right ^ left) & 0xAAAAAAAAUL;
528     right =  right ^ temp;
529     left =   left ^ temp;
530     left =   ((left << 31) | (left >> 1)) & 0xFFFFFFFFUL;
531     temp =   ((left >> 8) ^ right) & 0x00FF00FFUL;
532     right =  right ^ temp;
533     left =   left ^  (temp << 8);
534     temp =   ((left >> 2) ^ right) & 0x33333333UL;
535     right =  right ^ temp;
536     left =   left ^ (temp << 2);
537     temp =   ((right >> 16) ^ left) & 0x0000FFFFUL;
538     left =   left ^ temp;
539     right =  right ^ (temp << 16);
540     temp =   ((right >> 4) ^ left) & 0x0F0F0F0FUL;
541     left =   left ^ temp;
542     right =  right ^ (temp << 4);
543 
544     /* Finally, build the output.  */
545     destination[0] =  (UCHAR) (right >> 24);
546     destination[1] =  (UCHAR) (right >> 16);
547     destination[2] =  (UCHAR) (right >> 8);
548     destination[3] =  (UCHAR) (right);
549     destination[4] =  (UCHAR) (left >> 24);
550     destination[5] =  (UCHAR) (left >> 16);
551     destination[6] =  (UCHAR) (left >> 8);
552     destination[7] =  (UCHAR) (left);
553 }
554 
555