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 Crypto Component */
16 /** */
17 /** DES Encryption Standard (DES) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #include "nx_crypto_des.h"
23
24
25 /* Define the eight S-box data structures used in the permutation. Keep them static,
26 since there is no reason to have these symbols referenced outside this file. */
27
28 static const ULONG sb1[64] =
29 {
30
31 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
32 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
33 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
34 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
35 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
36 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
37 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
38 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
39 };
40
41 static const ULONG sb2[64] =
42 {
43
44 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
45 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
46 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
47 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
48 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
49 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
50 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
51 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
52 };
53
54 static const ULONG sb3[64] =
55 {
56
57 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
58 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
59 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
60 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
61 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
62 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
63 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
64 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
65 };
66
67 static const ULONG sb4[64] =
68 {
69
70 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
71 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
72 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
73 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
74 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
75 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
76 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
77 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
78 };
79
80 static const ULONG sb5[64] =
81 {
82
83 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
84 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
85 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
86 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
87 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
88 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
89 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
90 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
91 };
92
93 static const ULONG sb6[64] =
94 {
95
96 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
97 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
98 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
99 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
100 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
101 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
102 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
103 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
104 };
105
106 static const ULONG sb7[64] =
107 {
108
109 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
110 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
111 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
112 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
113 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
114 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
115 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
116 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
117 };
118
119 static const ULONG sb8[64] =
120 {
121
122 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
123 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
124 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
125 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
126 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
127 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
128 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
129 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
130 };
131
132
133 /* Define the left half bit swap table. */
134
135 static const ULONG left_half_bit_swap[16] =
136 {
137
138 0x00000000UL, 0x00000001UL, 0x00000100UL, 0x00000101UL,
139 0x00010000UL, 0x00010001UL, 0x00010100UL, 0x00010101UL,
140 0x01000000UL, 0x01000001UL, 0x01000100UL, 0x01000101UL,
141 0x01010000UL, 0x01010001UL, 0x01010100UL, 0x01010101UL
142 };
143
144 /* Define the right half bit swap table. */
145
146 static const ULONG right_half_bit_swap[16] =
147 {
148 0x00000000UL, 0x01000000UL, 0x00010000UL, 0x01010000UL,
149 0x00000100UL, 0x01000100UL, 0x00010100UL, 0x01010100UL,
150 0x00000001UL, 0x01000001UL, 0x00010001UL, 0x01010001UL,
151 0x00000101UL, 0x01000101UL, 0x00010101UL, 0x01010101UL
152 };
153
154
155 /**************************************************************************/
156 /* */
157 /* FUNCTION RELEASE */
158 /* */
159 /* _nx_crypto_des_key_set PORTABLE C */
160 /* 6.1 */
161 /* AUTHOR */
162 /* */
163 /* Timothy Stapko, Microsoft Corporation */
164 /* */
165 /* DESCRIPTION */
166 /* */
167 /* This function sets up the 32 encryption keys as well as the 32 */
168 /* decryption keys for the DES algorithm. It must be called before */
169 /* either _nx_crypto_des_encrypt or _nx_crypto_des_decrypt can be */
170 /* called. */
171 /* */
172 /* INPUT */
173 /* */
174 /* context DES context pointer */
175 /* key 8-byte (64-bit) key */
176 /* */
177 /* OUTPUT */
178 /* */
179 /* status Completion status */
180 /* */
181 /* CALLS */
182 /* */
183 /* None */
184 /* */
185 /* CALLED BY */
186 /* */
187 /* _nx_crypto_3des_key_set Set the key for 3DES */
188 /* _nx_crypto_method_des_init Init the method for DES */
189 /* */
190 /* RELEASE HISTORY */
191 /* */
192 /* DATE NAME DESCRIPTION */
193 /* */
194 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
195 /* 09-30-2020 Timothy Stapko Modified comment(s), */
196 /* resulting in version 6.1 */
197 /* */
198 /**************************************************************************/
_nx_crypto_des_key_set(NX_CRYPTO_DES * context,UCHAR key[8])199 NX_CRYPTO_KEEP UINT _nx_crypto_des_key_set(NX_CRYPTO_DES *context, UCHAR key[8])
200 {
201
202 ULONG left, right, temp;
203 ULONG *encrypt_keys_ptr;
204 ULONG *decrypt_keys_ptr;
205 UINT round;
206
207
208 /* Determine if the context is non-null. */
209 if (context == NX_CRYPTO_NULL)
210 {
211 return(NX_CRYPTO_PTR_ERROR);
212 }
213
214 /* First, convert the 8-byte raw key into two ULONG halves, in an endian neutral fashion. */
215 left = (((ULONG)key[0]) << 24) | (((ULONG)key[1]) << 16) | (((ULONG)key[2]) << 8) | ((ULONG)key[3]);
216 right = (((ULONG)key[4]) << 24) | (((ULONG)key[5]) << 16) | (((ULONG)key[6]) << 8) | ((ULONG)key[7]);
217
218 /* Perform permutation on the key halves. */
219 temp = ((right >> 4) ^ left) & 0x0F0F0F0FUL;
220 left = left ^ temp;
221 right = right ^ (temp << 4);
222 temp = (right ^ left) & 0x10101010;
223 left = left ^ temp;
224 right = right ^ temp;
225
226 left = (left_half_bit_swap[(left) & 0xf] << 3) | (left_half_bit_swap[(left >> 8) & 0xf] << 2) |
227 (left_half_bit_swap[(left >> 16) & 0xf] << 1) | (left_half_bit_swap[(left >> 24) & 0xf]) |
228 (left_half_bit_swap[(left >> 5) & 0xf] << 7) | (left_half_bit_swap[(left >> 13) & 0xf] << 6) |
229 (left_half_bit_swap[(left >> 21) & 0xf] << 5) | (left_half_bit_swap[(left >> 29) & 0xf] << 4);
230 left = left & 0x0fffffff;
231
232 right = (right_half_bit_swap[(right >> 1) & 0xf] << 3) | (right_half_bit_swap[(right >> 9) & 0xf] << 2) |
233 (right_half_bit_swap[(right >> 17) & 0xf] << 1) | (right_half_bit_swap[(right >> 25) & 0xf]) |
234 (right_half_bit_swap[(right >> 4) & 0xf] << 7) | (right_half_bit_swap[(right >> 12) & 0xf] << 6) |
235 (right_half_bit_swap[(right >> 20) & 0xf] << 5) | (right_half_bit_swap[(right >> 28) & 0xf] << 4);
236 right = right & 0x0fffffff;
237
238 /* Setup encryption keys pointer. */
239 encrypt_keys_ptr = context -> nx_des_encryption_keys;
240
241 /* Calculate the encryption keys. */
242 for (round = 0; round < 16; round++)
243 {
244
245 /* Modify the left and right portions of the keys. */
246 if ((round < 2) || (round == 8) || (round == 15))
247 {
248
249 left = ((left << 1) | (left >> 27)) & 0x0FFFFFFFUL;
250 right = ((right << 1) | (right >> 27)) & 0x0FFFFFFFUL;
251 }
252 else
253 {
254
255 left = ((left << 2) | (left >> 26)) & 0x0FFFFFFFUL;
256 right = ((right << 2) | (right >> 26)) & 0x0FFFFFFFUL;
257 }
258
259 /* Setup the key. */
260 *encrypt_keys_ptr++ = ((left << 4) & 0x24000000UL) | ((left << 28) & 0x10000000UL) |
261 ((left << 14) & 0x08000000UL) | ((left << 18) & 0x02080000UL) |
262 ((left << 6) & 0x01000000UL) | ((left << 9) & 0x00200000UL) |
263 ((left >> 1) & 0x00100000UL) | ((left << 10) & 0x00040000UL) |
264 ((left << 2) & 0x00020000UL) | ((left >> 10) & 0x00010000UL) |
265 ((right >> 13) & 0x00002000UL) | ((right >> 4) & 0x00001000UL) |
266 ((right << 6) & 0x00000800UL) | ((right >> 1) & 0x00000400UL) |
267 ((right >> 14) & 0x00000200UL) | (right & 0x00000100UL) |
268 ((right >> 5) & 0x00000020UL) | ((right >> 10) & 0x00000010UL) |
269 ((right >> 3) & 0x00000008UL) | ((right >> 18) & 0x00000004UL) |
270 ((right >> 26) & 0x00000002UL) | ((right >> 24) & 0x00000001UL);
271
272 /* Setup the next key. */
273 *encrypt_keys_ptr++ = ((left << 15) & 0x20000000UL) | ((left << 17) & 0x10000000UL) |
274 ((left << 10) & 0x08000000UL) | ((left << 22) & 0x04000000UL) |
275 ((left >> 2) & 0x02000000UL) | ((left << 1) & 0x01000000UL) |
276 ((left << 16) & 0x00200000UL) | ((left << 11) & 0x00100000UL) |
277 ((left << 3) & 0x00080000UL) | ((left >> 6) & 0x00040000UL) |
278 ((left << 15) & 0x00020000UL) | ((left >> 4) & 0x00010000UL) |
279 ((right >> 2) & 0x00002000UL) | ((right << 8) & 0x00001000UL) |
280 ((right >> 14) & 0x00000808UL) | ((right >> 9) & 0x00000400UL) |
281 ((right) & 0x00000200UL) | ((right << 7) & 0x00000100UL) |
282 ((right >> 7) & 0x00000020UL) | ((right >> 3) & 0x00000011UL) |
283 ((right << 2) & 0x00000004UL) | ((right >> 21) & 0x00000002UL);
284 }
285
286 /* Reposition the encryption key pointer. */
287 encrypt_keys_ptr = encrypt_keys_ptr - 2;
288
289 /* Setup decryption pointer. */
290 decrypt_keys_ptr = context -> nx_des_decryption_keys;
291
292 /* Now setup decryption keys. */
293 for (round = 0; round < 16; round++)
294 {
295
296 /* Copy the reverse of the encryption keys. */
297 *decrypt_keys_ptr++ = *encrypt_keys_ptr;
298 *decrypt_keys_ptr++ = *(encrypt_keys_ptr + 1);
299
300 /* Adjust the encryption keys pointer. */
301 encrypt_keys_ptr = encrypt_keys_ptr - 2;
302 }
303
304 #ifdef NX_SECURE_KEY_CLEAR
305 left = 0; right = 0; temp = 0;
306 #endif /* NX_SECURE_KEY_CLEAR */
307
308 /* Return successful completion. */
309 return(NX_CRYPTO_SUCCESS);
310 }
311
312
313 /**************************************************************************/
314 /* */
315 /* FUNCTION RELEASE */
316 /* */
317 /* _nx_crypto_des_encrypt PORTABLE C */
318 /* 6.1.11 */
319 /* AUTHOR */
320 /* */
321 /* Timothy Stapko, Microsoft Corporation */
322 /* */
323 /* DESCRIPTION */
324 /* */
325 /* This function uses the DES algorithm to encrypt 8-bytes (64-bits). */
326 /* The result is 8 encrypted bytes. Note that the caller must make */
327 /* sure the source and destination are 8-bytes in size! */
328 /* */
329 /* INPUT */
330 /* */
331 /* context DES context pointer */
332 /* source 8-byte source */
333 /* destination 8-byte destination */
334 /* length The length of output buffer */
335 /* */
336 /* OUTPUT */
337 /* */
338 /* status Completion status */
339 /* */
340 /* CALLS */
341 /* */
342 /* _nx_crypto_des_process_block Encrypt 8-bytes of source */
343 /* */
344 /* CALLED BY */
345 /* */
346 /* _nx_crypto_3des_encrypt Perform 3DES mode encryption */
347 /* _nx_crypto_3des_decrypt Perform 3DES mode decryption */
348 /* */
349 /* RELEASE HISTORY */
350 /* */
351 /* DATE NAME DESCRIPTION */
352 /* */
353 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
354 /* 09-30-2020 Timothy Stapko Modified comment(s), */
355 /* updated constants, */
356 /* resulting in version 6.1 */
357 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
358 /* warning supression for */
359 /* obsolete DES/3DES, */
360 /* resulting in version 6.1.11 */
361 /* */
362 /**************************************************************************/
_nx_crypto_des_encrypt(NX_CRYPTO_DES * context,UCHAR source[8],UCHAR destination[8],UINT length)363 NX_CRYPTO_KEEP UINT _nx_crypto_des_encrypt(NX_CRYPTO_DES *context, UCHAR source[8], UCHAR destination[8], UINT length)
364 {
365 NX_CRYPTO_PARAMETER_NOT_USED(length);
366
367 /* Encrypt the block by supplying the encryption key set. */
368 _nx_crypto_des_process_block(source, destination, context -> nx_des_encryption_keys); /* lgtm[cpp/weak-cryptographic-algorithm] */
369
370 /* Return successful completion. */
371 return(NX_CRYPTO_SUCCESS);
372 }
373
374
375 /**************************************************************************/
376 /* */
377 /* FUNCTION RELEASE */
378 /* */
379 /* _nx_crypto_des_decrypt PORTABLE C */
380 /* 6.1.11 */
381 /* AUTHOR */
382 /* */
383 /* Timothy Stapko, Microsoft Corporation */
384 /* */
385 /* DESCRIPTION */
386 /* */
387 /* This function uses the DES algorithm to decrypt 8-bytes (64-bits). */
388 /* The result is 8 original source bytes. Note that the caller must */
389 /* make sure the source and destination are 8-bytes in size! */
390 /* */
391 /* INPUT */
392 /* */
393 /* context DES context pointer */
394 /* source 8-byte source */
395 /* destination 8-byte destination */
396 /* length The length of output buffer */
397 /* */
398 /* OUTPUT */
399 /* */
400 /* status Completion status */
401 /* */
402 /* CALLS */
403 /* */
404 /* _nx_crypto_des_process_block Decrypt 8-bytes of source */
405 /* */
406 /* CALLED BY */
407 /* */
408 /* _nx_crypto_3des_encrypt Perform 3DES mode encryption */
409 /* _nx_crypto_3des_decrypt Perform 3DES mode decryption */
410 /* */
411 /* RELEASE HISTORY */
412 /* */
413 /* DATE NAME DESCRIPTION */
414 /* */
415 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
416 /* 09-30-2020 Timothy Stapko Modified comment(s), */
417 /* updated constants, */
418 /* resulting in version 6.1 */
419 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
420 /* warning supression for */
421 /* obsolete DES/3DES, */
422 /* resulting in version 6.1.11 */
423 /* */
424 /**************************************************************************/
_nx_crypto_des_decrypt(NX_CRYPTO_DES * context,UCHAR source[8],UCHAR destination[8],UINT length)425 NX_CRYPTO_KEEP UINT _nx_crypto_des_decrypt(NX_CRYPTO_DES *context, UCHAR source[8], UCHAR destination[8], UINT length)
426 {
427 NX_CRYPTO_PARAMETER_NOT_USED(length);
428
429 /* Decrypt the block by supplying the decryption key set. */
430 _nx_crypto_des_process_block(source, destination, context -> nx_des_decryption_keys); /* lgtm[cpp/weak-cryptographic-algorithm] */
431
432 /* Return successful completion. */
433 return(NX_CRYPTO_SUCCESS);
434 }
435
436
437 /**************************************************************************/
438 /* */
439 /* FUNCTION RELEASE */
440 /* */
441 /* _nx_crypto_des_process_block PORTABLE C */
442 /* 6.1 */
443 /* AUTHOR */
444 /* */
445 /* Timothy Stapko, Microsoft Corporation */
446 /* */
447 /* DESCRIPTION */
448 /* */
449 /* This function uses the DES algorithm to decrypt 8-bytes (64-bits). */
450 /* The result is 8 original source bytes. Note that the caller must */
451 /* make sure the source and destination are 8-bytes in size! */
452 /* */
453 /* INPUT */
454 /* */
455 /* source 8-byte source */
456 /* destination 8-byte destination */
457 /* keys Pointer to either the encrypt */
458 /* or decrypt keys */
459 /* */
460 /* OUTPUT */
461 /* */
462 /* None */
463 /* */
464 /* CALLS */
465 /* */
466 /* None */
467 /* */
468 /* CALLED BY */
469 /* */
470 /* _nx_crypto_des_encrypt Perform DES mode encryption */
471 /* _nx_crypto_des_decrypt Perform DES mode decryption */
472 /* */
473 /* RELEASE HISTORY */
474 /* */
475 /* DATE NAME DESCRIPTION */
476 /* */
477 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
478 /* 09-30-2020 Timothy Stapko Modified comment(s), */
479 /* resulting in version 6.1 */
480 /* */
481 /**************************************************************************/
_nx_crypto_des_process_block(UCHAR source[8],UCHAR destination[8],ULONG keys[32])482 NX_CRYPTO_KEEP VOID _nx_crypto_des_process_block(UCHAR source[8], UCHAR destination[8], ULONG keys[32])
483 {
484
485 ULONG left, right, temp;
486 ULONG *key_ptr;
487 UINT round;
488
489
490 /* First, convert the 8-byte source into two ULONG halves, in an endian neutral fashion. */
491 left = (((ULONG)source[0]) << 24) | (((ULONG)source[1]) << 16) | (((ULONG)source[2]) << 8) | ((ULONG)source[3]);
492 right = (((ULONG)source[4]) << 24) | (((ULONG)source[5]) << 16) | (((ULONG)source[6]) << 8) | ((ULONG)source[7]);
493
494 /* Compute the initial permutation. */
495 temp = ((left >> 4) ^ right) & 0x0F0F0F0FUL;
496 right = right ^ temp;
497 left = left ^ (temp << 4);
498 temp = ((left >> 16) ^ right) & 0x0000FFFFUL;
499 right = right ^ temp;
500 left = left ^ (temp << 16);
501 temp = ((right >> 2) ^ left) & 0x33333333UL;
502 left = left ^ temp;
503 right = right ^ (temp << 2);
504 temp = ((right >> 8) ^ left) & 0x00FF00FFUL;
505 left = left ^ temp;
506 right = right ^ (temp << 8);
507 right = ((right << 1) | (right >> 31)) & 0xFFFFFFFFUL;
508 temp = (left ^ right) & 0xAAAAAAAAUL;
509 right = right ^ temp;
510 left = left ^ temp;
511 left = ((left << 1) | (left >> 31)) & 0xFFFFFFFFUL;
512
513 /* Setup pointer to input keys. */
514 key_ptr = keys;
515
516 /* Now process the 16 rounds of the DES computation. There are two rounds per
517 loop. */
518 for (round = 0; round < 8; round++)
519 {
520
521 /* Calculate the left half. */
522 temp = *key_ptr++ ^ right;
523 left = left ^ sb8[temp & 0x3F] ^ sb6[(temp >> 8) & 0x3F] ^ sb4[(temp >> 16) & 0x3F] ^ sb2[(temp >> 24) & 0x3F];
524
525 temp = *key_ptr++ ^ ((right << 28) | (right >> 4));
526 left = left ^ sb7[temp & 0x3F] ^ sb5[(temp >> 8) & 0x3F] ^ sb3[(temp >> 16) & 0x3F] ^ sb1[(temp >> 24) & 0x3F];
527
528 /* Calculate the right half. */
529 temp = *key_ptr++ ^ left;
530 right = right ^ sb8[temp & 0x3F] ^ sb6[(temp >> 8) & 0x3F] ^ sb4[(temp >> 16) & 0x3F] ^ sb2[(temp >> 24) & 0x3F];
531
532 temp = *key_ptr++ ^ ((left << 28) | (left >> 4));
533 right = right ^ sb7[temp & 0x3F] ^ sb5[(temp >> 8) & 0x3F] ^ sb3[(temp >> 16) & 0x3F] ^ sb1[(temp >> 24) & 0x3F];
534 }
535
536 /* Now compute the final permutation. */
537 right = ((right << 31) | (right >> 1)) & 0xFFFFFFFFUL;
538 temp = (right ^ left) & 0xAAAAAAAAUL;
539 right = right ^ temp;
540 left = left ^ temp;
541 left = ((left << 31) | (left >> 1)) & 0xFFFFFFFFUL;
542 temp = ((left >> 8) ^ right) & 0x00FF00FFUL;
543 right = right ^ temp;
544 left = left ^ (temp << 8);
545 temp = ((left >> 2) ^ right) & 0x33333333UL;
546 right = right ^ temp;
547 left = left ^ (temp << 2);
548 temp = ((right >> 16) ^ left) & 0x0000FFFFUL;
549 left = left ^ temp;
550 right = right ^ (temp << 16);
551 temp = ((right >> 4) ^ left) & 0x0F0F0F0FUL;
552 left = left ^ temp;
553 right = right ^ (temp << 4);
554
555 /* Finally, build the output. */
556 destination[0] = (UCHAR)(right >> 24);
557 destination[1] = (UCHAR)(right >> 16);
558 destination[2] = (UCHAR)(right >> 8);
559 destination[3] = (UCHAR)(right);
560 destination[4] = (UCHAR)(left >> 24);
561 destination[5] = (UCHAR)(left >> 16);
562 destination[6] = (UCHAR)(left >> 8);
563 destination[7] = (UCHAR)(left);
564
565 #ifdef NX_SECURE_KEY_CLEAR
566 left = 0; right = 0; temp = 0;
567 #endif /* NX_SECURE_KEY_CLEAR */
568 }
569
570
571 /**************************************************************************/
572 /* */
573 /* FUNCTION RELEASE */
574 /* */
575 /* _nx_crypto_method_des_init PORTABLE C */
576 /* 6.3.0 */
577 /* AUTHOR */
578 /* */
579 /* Timothy Stapko, Microsoft Corporation */
580 /* */
581 /* DESCRIPTION */
582 /* */
583 /* This function is the common crypto method init callback for */
584 /* Microsoft supported 3DES cryptographic algorithm. */
585 /* */
586 /* INPUT */
587 /* */
588 /* method Pointer to crypto method */
589 /* key Pointer to key */
590 /* key_size_in_bits Length of key size in bits */
591 /* handler Returned crypto handler */
592 /* crypto_metadata Metadata area */
593 /* crypto_metadata_size Size of the metadata area */
594 /* */
595 /* OUTPUT */
596 /* */
597 /* status Completion status */
598 /* */
599 /* CALLS */
600 /* */
601 /* _nx_crypto_des_key_set Set the key for DES */
602 /* */
603 /* CALLED BY */
604 /* */
605 /* Application Code */
606 /* */
607 /* RELEASE HISTORY */
608 /* */
609 /* DATE NAME DESCRIPTION */
610 /* */
611 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
612 /* 09-30-2020 Timothy Stapko Modified comment(s), */
613 /* resulting in version 6.1 */
614 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
615 /* warning supression for */
616 /* obsolete DES/3DES, */
617 /* resulting in version 6.1.11 */
618 /* 10-31-2023 Yanwu Cai Modified comment(s), */
619 /* resulting in version 6.3.0 */
620 /* */
621 /**************************************************************************/
_nx_crypto_method_des_init(struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,VOID ** handle,VOID * crypto_metadata,ULONG crypto_metadata_size)622 NX_CRYPTO_KEEP UINT _nx_crypto_method_des_init(struct NX_CRYPTO_METHOD_STRUCT *method,
623 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits, VOID **handle,
624 VOID *crypto_metadata,
625 ULONG crypto_metadata_size)
626 {
627 NX_CRYPTO_DES *des_context_ptr;
628
629 NX_CRYPTO_PARAMETER_NOT_USED(handle);
630
631 NX_CRYPTO_STATE_CHECK
632
633 /* Validate input parameters. */
634 if ((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
635 {
636 return(NX_CRYPTO_PTR_ERROR);
637 }
638
639 if ((key_size_in_bits != NX_CRYPTO_DES_KEY_LEN_IN_BITS) || (crypto_metadata_size < sizeof(NX_CRYPTO_DES))) /* lgtm[cpp/weak-cryptographic-algorithm] */
640 {
641 return(NX_CRYPTO_SIZE_ERROR);
642 }
643
644 /* Verify the metadata address is 4-byte aligned. */
645 if((((ULONG)crypto_metadata) & 0x3) != 0)
646 {
647 return(NX_CRYPTO_PTR_ERROR);
648 }
649
650 des_context_ptr = (NX_CRYPTO_DES *)(crypto_metadata);
651
652 _nx_crypto_des_key_set(des_context_ptr, key); /* lgtm[cpp/weak-cryptographic-algorithm] */
653
654 return(NX_CRYPTO_SUCCESS);
655 }
656
657
658 /**************************************************************************/
659 /* */
660 /* FUNCTION RELEASE */
661 /* */
662 /* _nx_crypto_method_des_cleanup PORTABLE C */
663 /* 6.1 */
664 /* AUTHOR */
665 /* */
666 /* Timothy Stapko, Microsoft Corporation */
667 /* */
668 /* DESCRIPTION */
669 /* */
670 /* This function cleans up the crypto metadata. */
671 /* */
672 /* INPUT */
673 /* */
674 /* crypto_metadata Crypto metadata */
675 /* */
676 /* OUTPUT */
677 /* */
678 /* status Completion status */
679 /* */
680 /* CALLS */
681 /* */
682 /* NX_CRYPTO_MEMSET Set the memory */
683 /* */
684 /* CALLED BY */
685 /* */
686 /* Application Code */
687 /* */
688 /* RELEASE HISTORY */
689 /* */
690 /* DATE NAME DESCRIPTION */
691 /* */
692 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
693 /* 09-30-2020 Timothy Stapko Modified comment(s), */
694 /* resulting in version 6.1 */
695 /* */
696 /**************************************************************************/
_nx_crypto_method_des_cleanup(VOID * crypto_metadata)697 NX_CRYPTO_KEEP UINT _nx_crypto_method_des_cleanup(VOID *crypto_metadata)
698 {
699
700 NX_CRYPTO_STATE_CHECK
701
702 #ifdef NX_SECURE_KEY_CLEAR
703 if (!crypto_metadata)
704 return (NX_CRYPTO_SUCCESS);
705
706 /* Clean up the crypto metadata. */
707 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_DES));
708 #else
709 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
710 #endif/* NX_SECURE_KEY_CLEAR */
711
712 return(NX_CRYPTO_SUCCESS);
713 }
714
715
716 /**************************************************************************/
717 /* */
718 /* FUNCTION RELEASE */
719 /* */
720 /* _nx_crypto_method_des_operation PORTABLE C */
721 /* 6.3.0 */
722 /* AUTHOR */
723 /* */
724 /* Timothy Stapko, Microsoft Corporation */
725 /* */
726 /* DESCRIPTION */
727 /* */
728 /* This function handles des encrpt or decrypt operations. */
729 /* */
730 /* INPUT */
731 /* */
732 /* op Operation Type */
733 /* Encrypt, Decrypt, Authenticate*/
734 /* handler Pointer to crypto context */
735 /* method Pointer to crypto method */
736 /* key Pointer to key */
737 /* key_size_in_bits Length of key size in bits */
738 /* input Input Stream */
739 /* input_length_in_byte Input Stream Length */
740 /* iv_ptr Initialized Vector */
741 /* output Output Stream */
742 /* output_length_in_byte Output Stream Length */
743 /* crypto_metadata Metadata area */
744 /* crypto_metadata_size Size of the metadata area */
745 /* packet_ptr Pointer to packet */
746 /* nx_crypto_hw_process_callback Callback function pointer */
747 /* */
748 /* OUTPUT */
749 /* */
750 /* status Completion status */
751 /* */
752 /* CALLS */
753 /* */
754 /* _nx_crypto_cbc_encrypt Perform CBC mode encryption */
755 /* _nx_crypto_cbc_decrypt Perform CBC mode decryption */
756 /* */
757 /* CALLED BY */
758 /* */
759 /* Application Code */
760 /* */
761 /* RELEASE HISTORY */
762 /* */
763 /* DATE NAME DESCRIPTION */
764 /* */
765 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
766 /* 09-30-2020 Timothy Stapko Modified comment(s), */
767 /* resulting in version 6.1 */
768 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
769 /* warning supression for */
770 /* obsolete DES/3DES, */
771 /* resulting in version 6.1.11 */
772 /* 10-31-2023 Yanwu Cai Modified comment(s), */
773 /* resulting in version 6.3.0 */
774 /* */
775 /**************************************************************************/
_nx_crypto_method_des_operation(UINT op,VOID * handler,struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,UCHAR * input,ULONG input_length_in_byte,UCHAR * iv_ptr,UCHAR * output,ULONG output_length_in_byte,VOID * crypto_metadata,ULONG crypto_metadata_size,VOID * packet_ptr,VOID (* nx_crypto_hw_process_callback)(VOID * packet_ptr,UINT status))776 NX_CRYPTO_KEEP UINT _nx_crypto_method_des_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
777 VOID *handler, /* Crypto handler */
778 struct NX_CRYPTO_METHOD_STRUCT *method,
779 UCHAR *key,
780 NX_CRYPTO_KEY_SIZE key_size_in_bits,
781 UCHAR *input,
782 ULONG input_length_in_byte,
783 UCHAR *iv_ptr,
784 UCHAR *output,
785 ULONG output_length_in_byte,
786 VOID *crypto_metadata,
787 ULONG crypto_metadata_size,
788 VOID *packet_ptr,
789 VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
790 {
791 UINT status = NX_CRYPTO_NOT_SUCCESSFUL;
792 NX_CRYPTO_DES *context;
793
794 NX_CRYPTO_PARAMETER_NOT_USED(handler);
795 NX_CRYPTO_PARAMETER_NOT_USED(key);
796 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
797 NX_CRYPTO_PARAMETER_NOT_USED(output_length_in_byte);
798 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
799 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
800
801 NX_CRYPTO_STATE_CHECK
802
803 if (op == NX_CRYPTO_AUTHENTICATE)
804 {
805 /* Incorrect Operation. */
806 return(NX_CRYPTO_NOT_SUCCESSFUL);
807 }
808
809 if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
810 {
811 return(NX_CRYPTO_PTR_ERROR);
812 }
813
814 /* Verify the metadata address is 4-byte aligned. */
815 if((((ULONG)crypto_metadata) & 0x3) != 0)
816 {
817 return(NX_CRYPTO_PTR_ERROR);
818 }
819
820 if(crypto_metadata_size < sizeof(NX_CRYPTO_DES))
821 {
822 return(NX_CRYPTO_PTR_ERROR);
823 }
824
825 if (method -> nx_crypto_algorithm != NX_CRYPTO_ENCRYPTION_DES_CBC) /* lgtm[cpp/weak-cryptographic-algorithm] */
826 {
827 /* Incorrect method. */
828 return(NX_CRYPTO_NOT_SUCCESSFUL);
829 }
830
831 context = (NX_CRYPTO_DES *)crypto_metadata;
832
833 switch (op)
834 {
835 case NX_CRYPTO_DECRYPT:
836 {
837 status = _nx_crypto_cbc_decrypt_init(&(context -> nx_crypto_cbc_context),
838 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
839 if (status)
840 {
841 break;
842 }
843
844 status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context),
845 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_decrypt,
846 input, output, input_length_in_byte,
847 (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
848 } break;
849
850 case NX_CRYPTO_ENCRYPT:
851 {
852 status = _nx_crypto_cbc_encrypt_init(&(context -> nx_crypto_cbc_context),
853 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
854 if (status)
855 {
856 break;
857 }
858
859 status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context),
860 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_encrypt,
861 input, output, input_length_in_byte,
862 (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
863 } break;
864
865 case NX_CRYPTO_DECRYPT_INITIALIZE:
866 {
867 status = _nx_crypto_cbc_decrypt_init(&(context -> nx_crypto_cbc_context),
868 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
869 } break;
870
871 case NX_CRYPTO_ENCRYPT_INITIALIZE:
872 {
873 status = _nx_crypto_cbc_encrypt_init(&(context -> nx_crypto_cbc_context),
874 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
875 } break;
876
877 case NX_CRYPTO_DECRYPT_UPDATE:
878 {
879 status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context),
880 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_decrypt,
881 input, output, input_length_in_byte,
882 (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
883 } break;
884
885 case NX_CRYPTO_ENCRYPT_UPDATE:
886 {
887 status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context),
888 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_encrypt,
889 input, output, input_length_in_byte,
890 (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
891 } break;
892
893 case NX_CRYPTO_ENCRYPT_CALCULATE:
894 /* fallthrough */
895 case NX_CRYPTO_DECRYPT_CALCULATE:
896 {
897
898 /* Nothing to do. */
899 status = NX_CRYPTO_SUCCESS;
900 } break;
901
902 default:
903 {
904 status = NX_CRYPTO_INVALID_ALGORITHM;
905 } break;
906 }
907
908 return(status);
909 }
910
911