mirror from https://www.codeaurora.org/git/projects/hisense-ts7008/repository/
[huawei.git] / AMSS / diagd3des.c
1 /* D3DES \r
2  *\r
3  * A portable, public domain, version of the Data Encryption Standard.\r
4  *\r
5  * Copyright (c) 2004 by Hisense Incorporated. All Rights Reserved.\r
6  */\r
7 \r
8 #include "diagd3des.h"\r
9 \r
10 static void diag_scrunch(unsigned char *, unsigned long *);\r
11 static void diag_unscrun(unsigned long *, unsigned char *);\r
12 static void diag_desfunc(unsigned long *, unsigned long *);\r
13 static void diag_cookey(unsigned long *);\r
14 \r
15 static unsigned long diag_knl[32] = { 0L };\r
16 \r
17 static const unsigned short diag_bytebit[8]     = {\r
18         0200, 0100, 040, 020, 010, 04, 02, 01 };\r
19 \r
20 static const unsigned long diag_bigbyte[24] = {\r
21         0x800000L,      0x400000L,      0x200000L,      0x100000L,\r
22         0x80000L,       0x40000L,       0x20000L,       0x10000L,\r
23         0x8000L,        0x4000L,        0x2000L,        0x1000L,\r
24         0x800L,         0x400L,         0x200L,         0x100L,\r
25         0x80L,          0x40L,          0x20L,          0x10L,\r
26         0x8L,           0x4L,           0x2L,           0x1L    };\r
27 \r
28 /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */\r
29 \r
30 static const unsigned char diag_pc1[56] = {\r
31         56, 48, 40, 32, 24, 16,  8,      0, 57, 49, 41, 33, 25, 17,\r
32          9,  1, 58, 50, 42, 34, 26,     18, 10,  2, 59, 51, 43, 35,\r
33         62, 54, 46, 38, 30, 22, 14,      6, 61, 53, 45, 37, 29, 21,\r
34         13,  5, 60, 52, 44, 36, 28,     20, 12,  4, 27, 19, 11,  3 };\r
35 \r
36 static const unsigned char diag_totrot[16] = {\r
37         1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };\r
38 \r
39 static const unsigned char diag_pc2[48] = {\r
40         13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,\r
41         22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,\r
42         40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,\r
43         43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };\r
44 \r
45 void diag_deskey(unsigned char *key, short edf) /* Thanks to James Gillogly & Phil Karn! */\r
46 {\r
47         register int i, j, l, m, n;\r
48         unsigned char diag_pc1m[56], pcr[56];\r
49         unsigned long kn[32];\r
50 \r
51         for ( j = 0; j < 56; j++ ) {\r
52                 l = diag_pc1[j];\r
53                 m = l & 07;\r
54                 diag_pc1m[j] = (key[l >> 3] & diag_bytebit[m]) ? 1 : 0;\r
55                 }\r
56         for( i = 0; i < 16; i++ ) {\r
57                 if( edf == DE1 ) m = (15 - i) << 1;\r
58                 else m = i << 1;\r
59                 n = m + 1;\r
60                 kn[m] = kn[n] = 0L;\r
61                 for( j = 0; j < 28; j++ ) {\r
62                         l = j + diag_totrot[i];\r
63                         if( l < 28 ) pcr[j] = diag_pc1m[l];\r
64                         else pcr[j] = diag_pc1m[l - 28];\r
65                         }\r
66                 for( j = 28; j < 56; j++ ) {\r
67                     l = j + diag_totrot[i];\r
68                     if( l < 56 ) pcr[j] = diag_pc1m[l];\r
69                     else pcr[j] = diag_pc1m[l - 28];\r
70                     }\r
71                 for( j = 0; j < 24; j++ ) {\r
72                         if( pcr[diag_pc2[j]] ) kn[m] |= diag_bigbyte[j];\r
73                         if( pcr[diag_pc2[j+24]] ) kn[n] |= diag_bigbyte[j];\r
74                         }\r
75                 }\r
76         diag_cookey(kn);\r
77         return;\r
78         }\r
79 \r
80 static void diag_cookey(register unsigned long *raw1)\r
81 {\r
82         register unsigned long *cook, *raw0;\r
83         unsigned long dough[32];\r
84         register int i;\r
85 \r
86         cook = dough;\r
87         for( i = 0; i < 16; i++, raw1++ ) {\r
88                 raw0 = raw1++;\r
89                 *cook    = (*raw0 & 0x00fc0000L) << 6;\r
90                 *cook   |= (*raw0 & 0x00000fc0L) << 10;\r
91                 *cook   |= (*raw1 & 0x00fc0000L) >> 10;\r
92                 *cook++ |= (*raw1 & 0x00000fc0L) >> 6;\r
93                 *cook    = (*raw0 & 0x0003f000L) << 12;\r
94                 *cook   |= (*raw0 & 0x0000003fL) << 16;\r
95                 *cook   |= (*raw1 & 0x0003f000L) >> 4;\r
96                 *cook++ |= (*raw1 & 0x0000003fL);\r
97                 }\r
98         diag_usekey(dough);\r
99         return;\r
100         }\r
101 \r
102 void diag_cpkey(register unsigned long *into)\r
103 {\r
104         register unsigned long *from, *endp;\r
105 \r
106         from = diag_knl, endp = &diag_knl[32];\r
107         while( from < endp ) *into++ = *from++;\r
108         return;\r
109         }\r
110 \r
111 void diag_usekey(register unsigned long *from)\r
112 {\r
113         register unsigned long *to, *endp;\r
114 \r
115         to = diag_knl, endp = &diag_knl[32];\r
116         while( to < endp ) *to++ = *from++;\r
117         return;\r
118         }\r
119 \r
120 void diag_des(unsigned char *inblock, unsigned char *outblock)\r
121 {\r
122         unsigned long work[2];\r
123 \r
124         diag_scrunch(inblock, work);\r
125         diag_desfunc(work, diag_knl);\r
126         diag_unscrun(work, outblock);\r
127         return;\r
128         }\r
129 \r
130 static void diag_scrunch(register unsigned char *outof, register unsigned long *into)\r
131 {\r
132         *into    = (*outof++ & 0xffL) << 24;\r
133         *into   |= (*outof++ & 0xffL) << 16;\r
134         *into   |= (*outof++ & 0xffL) << 8;\r
135         *into++ |= (*outof++ & 0xffL);\r
136         *into    = (*outof++ & 0xffL) << 24;\r
137         *into   |= (*outof++ & 0xffL) << 16;\r
138         *into   |= (*outof++ & 0xffL) << 8;\r
139         *into   |= (*outof   & 0xffL);\r
140         return;\r
141         }\r
142 \r
143 static void diag_unscrun(register unsigned long *outof, register unsigned char *into)\r
144 {\r
145         *into++ = (*outof >> 24) & 0xffL;\r
146         *into++ = (*outof >> 16) & 0xffL;\r
147         *into++ = (*outof >>  8) & 0xffL;\r
148         *into++ =  *outof++      & 0xffL;\r
149         *into++ = (*outof >> 24) & 0xffL;\r
150         *into++ = (*outof >> 16) & 0xffL;\r
151         *into++ = (*outof >>  8) & 0xffL;\r
152         *into   =  *outof        & 0xffL;\r
153         return;\r
154         }\r
155 \r
156 static const unsigned long diag_SP1[64] = {\r
157         0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,\r
158         0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,\r
159         0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,\r
160         0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,\r
161         0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,\r
162         0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,\r
163         0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,\r
164         0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,\r
165         0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,\r
166         0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,\r
167         0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,\r
168         0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,\r
169         0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,\r
170         0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,\r
171         0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,\r
172         0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };\r
173 \r
174 static const unsigned long diag_SP2[64] = {\r
175         0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,\r
176         0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,\r
177         0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,\r
178         0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,\r
179         0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,\r
180         0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,\r
181         0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,\r
182         0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,\r
183         0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,\r
184         0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,\r
185         0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,\r
186         0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,\r
187         0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,\r
188         0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,\r
189         0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,\r
190         0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };\r
191 \r
192 static const unsigned long diag_SP3[64] = {\r
193         0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,\r
194         0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,\r
195         0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,\r
196         0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,\r
197         0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,\r
198         0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,\r
199         0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,\r
200         0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,\r
201         0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,\r
202         0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,\r
203         0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,\r
204         0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,\r
205         0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,\r
206         0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,\r
207         0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,\r
208         0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };\r
209 \r
210 static const unsigned long diag_SP4[64] = {\r
211         0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,\r
212         0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,\r
213         0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,\r
214         0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,\r
215         0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,\r
216         0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,\r
217         0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,\r
218         0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,\r
219         0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,\r
220         0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,\r
221         0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,\r
222         0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,\r
223         0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,\r
224         0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,\r
225         0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,\r
226         0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };\r
227 \r
228 static const unsigned long diag_SP5[64] = {\r
229         0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,\r
230         0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,\r
231         0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,\r
232         0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,\r
233         0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,\r
234         0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,\r
235         0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,\r
236         0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,\r
237         0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,\r
238         0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,\r
239         0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,\r
240         0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,\r
241         0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,\r
242         0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,\r
243         0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,\r
244         0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };\r
245 \r
246 static const unsigned long diag_SP6[64] = {\r
247         0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,\r
248         0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,\r
249         0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,\r
250         0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,\r
251         0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,\r
252         0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,\r
253         0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,\r
254         0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,\r
255         0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,\r
256         0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,\r
257         0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,\r
258         0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,\r
259         0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,\r
260         0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,\r
261         0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,\r
262         0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };\r
263 \r
264 static const unsigned long diag_SP7[64] = {\r
265         0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,\r
266         0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,\r
267         0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,\r
268         0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,\r
269         0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,\r
270         0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,\r
271         0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,\r
272         0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,\r
273         0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,\r
274         0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,\r
275         0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,\r
276         0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,\r
277         0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,\r
278         0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,\r
279         0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,\r
280         0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };\r
281 \r
282 static const unsigned long diag_SP8[64] = {\r
283         0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,\r
284         0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,\r
285         0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,\r
286         0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,\r
287         0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,\r
288         0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,\r
289         0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,\r
290         0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,\r
291         0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,\r
292         0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,\r
293         0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,\r
294         0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,\r
295         0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,\r
296         0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,\r
297         0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,\r
298         0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };\r
299 \r
300 static void diag_desfunc(register unsigned long *block, register unsigned long *keys)\r
301 {\r
302         register unsigned long fval, work, right, leftt;\r
303         register int round;\r
304 \r
305         leftt = block[0];\r
306         right = block[1];\r
307         work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;\r
308         right ^= work;\r
309         leftt ^= (work << 4);\r
310         work = ((leftt >> 16) ^ right) & 0x0000ffffL;\r
311         right ^= work;\r
312         leftt ^= (work << 16);\r
313         work = ((right >> 2) ^ leftt) & 0x33333333L;\r
314         leftt ^= work;\r
315         right ^= (work << 2);\r
316         work = ((right >> 8) ^ leftt) & 0x00ff00ffL;\r
317         leftt ^= work;\r
318         right ^= (work << 8);\r
319         right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;\r
320         work = (leftt ^ right) & 0xaaaaaaaaL;\r
321         leftt ^= work;\r
322         right ^= work;\r
323         leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;\r
324 \r
325         for( round = 0; round < 8; round++ ) {\r
326                 work  = (right << 28) | (right >> 4);\r
327                 work ^= *keys++;\r
328                 fval  = diag_SP7[ work           & 0x3fL];\r
329                 fval |= diag_SP5[(work >>  8) & 0x3fL];\r
330                 fval |= diag_SP3[(work >> 16) & 0x3fL];\r
331                 fval |= diag_SP1[(work >> 24) & 0x3fL];\r
332                 work  = right ^ *keys++;\r
333                 fval |= diag_SP8[ work           & 0x3fL];\r
334                 fval |= diag_SP6[(work >>  8) & 0x3fL];\r
335                 fval |= diag_SP4[(work >> 16) & 0x3fL];\r
336                 fval |= diag_SP2[(work >> 24) & 0x3fL];\r
337                 leftt ^= fval;\r
338                 work  = (leftt << 28) | (leftt >> 4);\r
339                 work ^= *keys++;\r
340                 fval  = diag_SP7[ work           & 0x3fL];\r
341                 fval |= diag_SP5[(work >>  8) & 0x3fL];\r
342                 fval |= diag_SP3[(work >> 16) & 0x3fL];\r
343                 fval |= diag_SP1[(work >> 24) & 0x3fL];\r
344                 work  = leftt ^ *keys++;\r
345                 fval |= diag_SP8[ work           & 0x3fL];\r
346                 fval |= diag_SP6[(work >>  8) & 0x3fL];\r
347                 fval |= diag_SP4[(work >> 16) & 0x3fL];\r
348                 fval |= diag_SP2[(work >> 24) & 0x3fL];\r
349                 right ^= fval;\r
350                 }\r
351 \r
352         right = (right << 31) | (right >> 1);\r
353         work = (leftt ^ right) & 0xaaaaaaaaL;\r
354         leftt ^= work;\r
355         right ^= work;\r
356         leftt = (leftt << 31) | (leftt >> 1);\r
357         work = ((leftt >> 8) ^ right) & 0x00ff00ffL;\r
358         right ^= work;\r
359         leftt ^= (work << 8);\r
360         work = ((leftt >> 2) ^ right) & 0x33333333L;\r
361         right ^= work;\r
362         leftt ^= (work << 2);\r
363         work = ((right >> 16) ^ leftt) & 0x0000ffffL;\r
364         leftt ^= work;\r
365         right ^= (work << 16);\r
366         work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;\r
367         leftt ^= work;\r
368         right ^= (work << 4);\r
369         *block++ = right;\r
370         *block = leftt;\r
371         return;\r
372         }\r
373 \r
374  /*\r
375  *Validation sets:\r
376  *\r
377  * Single-length key, single-length plaintext -\r
378  * Key    : 0123 4567 89ab cdef\r
379  * Plain  : 0123 4567 89ab cde7\r
380  * Cipher : c957 4425 6a5e d31d\r
381  *\r
382  * Double-length key, single-length plaintext -\r
383  * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210\r
384  * Plain  : 0123 4567 89ab cde7\r
385  * Cipher : 7f1d 0a77 826b 8aff\r
386  *\r
387  * Double-length key, double-length plaintext -\r
388  * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210\r
389  * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff\r
390  * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7\r
391  *\r
392  * Triple-length key, single-length plaintext -\r
393  * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567\r
394  * Plain  : 0123 4567 89ab cde7\r
395  * Cipher : de0b 7c06 ae5e 0ed5\r
396  *\r
397  * Triple-length key, double-length plaintext -\r
398  * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567\r
399  * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff\r
400  * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5\r
401  *\r
402  * d3des V5.0a rwo 9208.07 18:44 Graven Imagery\r
403  */\r