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