K2.6 patches and update.
[tomato.git] / release / src-rt / bcmcrypto / sms4.c
blob8a05986517771dab694f8108c0631cc61942cc58
1 #ifdef BCMWAPI_WPI
2 /*
3 * sms4.c
4 * SMS-4 block cipher
6 * Copyright (C) 2010, Broadcom Corporation
7 * All Rights Reserved.
8 *
9 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
10 * the contents of this file may not be disclosed to third parties, copied
11 * or duplicated in any form, in whole or in part, without the prior
12 * written permission of Broadcom Corporation.
14 * $Id: sms4.c,v 1.23 2009-10-22 00:10:59 Exp $
17 #include <typedefs.h>
18 #include <bcmendian.h>
19 #include <proto/802.11.h>
20 #include <bcmcrypto/sms4.h>
22 #include <bcmutils.h>
24 #ifdef BCMDRIVER
25 #include <osl.h>
26 #else
27 #include <stddef.h> /* for size_t */
28 #if defined(__GNUC__)
29 extern void bcopy(const void *src, void *dst, size_t len);
30 extern int bcmp(const void *b1, const void *b2, size_t len);
31 extern void bzero(void *b, size_t len);
32 #else
33 #define bcopy(src, dst, len) memcpy((dst), (src), (len))
34 #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
35 #define bzero(b, len) memset((b), 0, (len))
36 #endif /* __GNUC__ */
37 #endif /* BCMDRIVER */
39 #define ROTATE(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
41 static void
42 sms4_print_bytes(char *name, const uchar *data, int len)
46 #if !defined(__i386__)
47 static const uint8 S_box[] = {
48 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
49 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
50 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
51 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
52 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
53 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
54 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
55 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
56 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
57 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
58 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
59 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
60 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
61 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
62 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
63 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
64 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
65 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
66 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
67 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
68 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
69 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
70 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
71 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
72 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
73 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
74 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
75 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
76 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
77 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
78 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
79 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
81 #else /* __i386__ */
82 /* slightly better performance on Pentium, worse performance on ARM CM3 */
83 static const uint32 S_box0[] = {
84 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
85 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
86 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
87 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
88 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
89 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
90 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
91 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
92 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
93 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
94 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
95 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
96 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
97 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
98 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
99 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
100 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
101 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
102 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
103 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
104 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
105 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
106 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
107 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
108 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
109 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
110 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
111 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
112 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
113 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
114 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
115 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
118 static const uint32 S_box1[] = {
119 0xd600, 0x9000, 0xe900, 0xfe00, 0xcc00, 0xe100, 0x3d00, 0xb700,
120 0x1600, 0xb600, 0x1400, 0xc200, 0x2800, 0xfb00, 0x2c00, 0x0500,
121 0x2b00, 0x6700, 0x9a00, 0x7600, 0x2a00, 0xbe00, 0x0400, 0xc300,
122 0xaa00, 0x4400, 0x1300, 0x2600, 0x4900, 0x8600, 0x0600, 0x9900,
123 0x9c00, 0x4200, 0x5000, 0xf400, 0x9100, 0xef00, 0x9800, 0x7a00,
124 0x3300, 0x5400, 0x0b00, 0x4300, 0xed00, 0xcf00, 0xac00, 0x6200,
125 0xe400, 0xb300, 0x1c00, 0xa900, 0xc900, 0x0800, 0xe800, 0x9500,
126 0x8000, 0xdf00, 0x9400, 0xfa00, 0x7500, 0x8f00, 0x3f00, 0xa600,
127 0x4700, 0x0700, 0xa700, 0xfc00, 0xf300, 0x7300, 0x1700, 0xba00,
128 0x8300, 0x5900, 0x3c00, 0x1900, 0xe600, 0x8500, 0x4f00, 0xa800,
129 0x6800, 0x6b00, 0x8100, 0xb200, 0x7100, 0x6400, 0xda00, 0x8b00,
130 0xf800, 0xeb00, 0x0f00, 0x4b00, 0x7000, 0x5600, 0x9d00, 0x3500,
131 0x1e00, 0x2400, 0x0e00, 0x5e00, 0x6300, 0x5800, 0xd100, 0xa200,
132 0x2500, 0x2200, 0x7c00, 0x3b00, 0x0100, 0x2100, 0x7800, 0x8700,
133 0xd400, 0x0000, 0x4600, 0x5700, 0x9f00, 0xd300, 0x2700, 0x5200,
134 0x4c00, 0x3600, 0x0200, 0xe700, 0xa000, 0xc400, 0xc800, 0x9e00,
135 0xea00, 0xbf00, 0x8a00, 0xd200, 0x4000, 0xc700, 0x3800, 0xb500,
136 0xa300, 0xf700, 0xf200, 0xce00, 0xf900, 0x6100, 0x1500, 0xa100,
137 0xe000, 0xae00, 0x5d00, 0xa400, 0x9b00, 0x3400, 0x1a00, 0x5500,
138 0xad00, 0x9300, 0x3200, 0x3000, 0xf500, 0x8c00, 0xb100, 0xe300,
139 0x1d00, 0xf600, 0xe200, 0x2e00, 0x8200, 0x6600, 0xca00, 0x6000,
140 0xc000, 0x2900, 0x2300, 0xab00, 0x0d00, 0x5300, 0x4e00, 0x6f00,
141 0xd500, 0xdb00, 0x3700, 0x4500, 0xde00, 0xfd00, 0x8e00, 0x2f00,
142 0x0300, 0xff00, 0x6a00, 0x7200, 0x6d00, 0x6c00, 0x5b00, 0x5100,
143 0x8d00, 0x1b00, 0xaf00, 0x9200, 0xbb00, 0xdd00, 0xbc00, 0x7f00,
144 0x1100, 0xd900, 0x5c00, 0x4100, 0x1f00, 0x1000, 0x5a00, 0xd800,
145 0x0a00, 0xc100, 0x3100, 0x8800, 0xa500, 0xcd00, 0x7b00, 0xbd00,
146 0x2d00, 0x7400, 0xd000, 0x1200, 0xb800, 0xe500, 0xb400, 0xb000,
147 0x8900, 0x6900, 0x9700, 0x4a00, 0x0c00, 0x9600, 0x7700, 0x7e00,
148 0x6500, 0xb900, 0xf100, 0x0900, 0xc500, 0x6e00, 0xc600, 0x8400,
149 0x1800, 0xf000, 0x7d00, 0xec00, 0x3a00, 0xdc00, 0x4d00, 0x2000,
150 0x7900, 0xee00, 0x5f00, 0x3e00, 0xd700, 0xcb00, 0x3900, 0x4800
153 static const uint32 S_box2[] = {
154 0xd60000, 0x900000, 0xe90000, 0xfe0000,
155 0xcc0000, 0xe10000, 0x3d0000, 0xb70000,
156 0x160000, 0xb60000, 0x140000, 0xc20000,
157 0x280000, 0xfb0000, 0x2c0000, 0x050000,
158 0x2b0000, 0x670000, 0x9a0000, 0x760000,
159 0x2a0000, 0xbe0000, 0x040000, 0xc30000,
160 0xaa0000, 0x440000, 0x130000, 0x260000,
161 0x490000, 0x860000, 0x060000, 0x990000,
162 0x9c0000, 0x420000, 0x500000, 0xf40000,
163 0x910000, 0xef0000, 0x980000, 0x7a0000,
164 0x330000, 0x540000, 0x0b0000, 0x430000,
165 0xed0000, 0xcf0000, 0xac0000, 0x620000,
166 0xe40000, 0xb30000, 0x1c0000, 0xa90000,
167 0xc90000, 0x080000, 0xe80000, 0x950000,
168 0x800000, 0xdf0000, 0x940000, 0xfa0000,
169 0x750000, 0x8f0000, 0x3f0000, 0xa60000,
170 0x470000, 0x070000, 0xa70000, 0xfc0000,
171 0xf30000, 0x730000, 0x170000, 0xba0000,
172 0x830000, 0x590000, 0x3c0000, 0x190000,
173 0xe60000, 0x850000, 0x4f0000, 0xa80000,
174 0x680000, 0x6b0000, 0x810000, 0xb20000,
175 0x710000, 0x640000, 0xda0000, 0x8b0000,
176 0xf80000, 0xeb0000, 0x0f0000, 0x4b0000,
177 0x700000, 0x560000, 0x9d0000, 0x350000,
178 0x1e0000, 0x240000, 0x0e0000, 0x5e0000,
179 0x630000, 0x580000, 0xd10000, 0xa20000,
180 0x250000, 0x220000, 0x7c0000, 0x3b0000,
181 0x010000, 0x210000, 0x780000, 0x870000,
182 0xd40000, 0x000000, 0x460000, 0x570000,
183 0x9f0000, 0xd30000, 0x270000, 0x520000,
184 0x4c0000, 0x360000, 0x020000, 0xe70000,
185 0xa00000, 0xc40000, 0xc80000, 0x9e0000,
186 0xea0000, 0xbf0000, 0x8a0000, 0xd20000,
187 0x400000, 0xc70000, 0x380000, 0xb50000,
188 0xa30000, 0xf70000, 0xf20000, 0xce0000,
189 0xf90000, 0x610000, 0x150000, 0xa10000,
190 0xe00000, 0xae0000, 0x5d0000, 0xa40000,
191 0x9b0000, 0x340000, 0x1a0000, 0x550000,
192 0xad0000, 0x930000, 0x320000, 0x300000,
193 0xf50000, 0x8c0000, 0xb10000, 0xe30000,
194 0x1d0000, 0xf60000, 0xe20000, 0x2e0000,
195 0x820000, 0x660000, 0xca0000, 0x600000,
196 0xc00000, 0x290000, 0x230000, 0xab0000,
197 0x0d0000, 0x530000, 0x4e0000, 0x6f0000,
198 0xd50000, 0xdb0000, 0x370000, 0x450000,
199 0xde0000, 0xfd0000, 0x8e0000, 0x2f0000,
200 0x030000, 0xff0000, 0x6a0000, 0x720000,
201 0x6d0000, 0x6c0000, 0x5b0000, 0x510000,
202 0x8d0000, 0x1b0000, 0xaf0000, 0x920000,
203 0xbb0000, 0xdd0000, 0xbc0000, 0x7f0000,
204 0x110000, 0xd90000, 0x5c0000, 0x410000,
205 0x1f0000, 0x100000, 0x5a0000, 0xd80000,
206 0x0a0000, 0xc10000, 0x310000, 0x880000,
207 0xa50000, 0xcd0000, 0x7b0000, 0xbd0000,
208 0x2d0000, 0x740000, 0xd00000, 0x120000,
209 0xb80000, 0xe50000, 0xb40000, 0xb00000,
210 0x890000, 0x690000, 0x970000, 0x4a0000,
211 0x0c0000, 0x960000, 0x770000, 0x7e0000,
212 0x650000, 0xb90000, 0xf10000, 0x090000,
213 0xc50000, 0x6e0000, 0xc60000, 0x840000,
214 0x180000, 0xf00000, 0x7d0000, 0xec0000,
215 0x3a0000, 0xdc0000, 0x4d0000, 0x200000,
216 0x790000, 0xee0000, 0x5f0000, 0x3e0000,
217 0xd70000, 0xcb0000, 0x390000, 0x480000
220 static const uint32 S_box3[] = {
221 0xd6000000, 0x90000000, 0xe9000000, 0xfe000000,
222 0xcc000000, 0xe1000000, 0x3d000000, 0xb7000000,
223 0x16000000, 0xb6000000, 0x14000000, 0xc2000000,
224 0x28000000, 0xfb000000, 0x2c000000, 0x05000000,
225 0x2b000000, 0x67000000, 0x9a000000, 0x76000000,
226 0x2a000000, 0xbe000000, 0x04000000, 0xc3000000,
227 0xaa000000, 0x44000000, 0x13000000, 0x26000000,
228 0x49000000, 0x86000000, 0x06000000, 0x99000000,
229 0x9c000000, 0x42000000, 0x50000000, 0xf4000000,
230 0x91000000, 0xef000000, 0x98000000, 0x7a000000,
231 0x33000000, 0x54000000, 0x0b000000, 0x43000000,
232 0xed000000, 0xcf000000, 0xac000000, 0x62000000,
233 0xe4000000, 0xb3000000, 0x1c000000, 0xa9000000,
234 0xc9000000, 0x08000000, 0xe8000000, 0x95000000,
235 0x80000000, 0xdf000000, 0x94000000, 0xfa000000,
236 0x75000000, 0x8f000000, 0x3f000000, 0xa6000000,
237 0x47000000, 0x07000000, 0xa7000000, 0xfc000000,
238 0xf3000000, 0x73000000, 0x17000000, 0xba000000,
239 0x83000000, 0x59000000, 0x3c000000, 0x19000000,
240 0xe6000000, 0x85000000, 0x4f000000, 0xa8000000,
241 0x68000000, 0x6b000000, 0x81000000, 0xb2000000,
242 0x71000000, 0x64000000, 0xda000000, 0x8b000000,
243 0xf8000000, 0xeb000000, 0x0f000000, 0x4b000000,
244 0x70000000, 0x56000000, 0x9d000000, 0x35000000,
245 0x1e000000, 0x24000000, 0x0e000000, 0x5e000000,
246 0x63000000, 0x58000000, 0xd1000000, 0xa2000000,
247 0x25000000, 0x22000000, 0x7c000000, 0x3b000000,
248 0x01000000, 0x21000000, 0x78000000, 0x87000000,
249 0xd4000000, 0x00000000, 0x46000000, 0x57000000,
250 0x9f000000, 0xd3000000, 0x27000000, 0x52000000,
251 0x4c000000, 0x36000000, 0x02000000, 0xe7000000,
252 0xa0000000, 0xc4000000, 0xc8000000, 0x9e000000,
253 0xea000000, 0xbf000000, 0x8a000000, 0xd2000000,
254 0x40000000, 0xc7000000, 0x38000000, 0xb5000000,
255 0xa3000000, 0xf7000000, 0xf2000000, 0xce000000,
256 0xf9000000, 0x61000000, 0x15000000, 0xa1000000,
257 0xe0000000, 0xae000000, 0x5d000000, 0xa4000000,
258 0x9b000000, 0x34000000, 0x1a000000, 0x55000000,
259 0xad000000, 0x93000000, 0x32000000, 0x30000000,
260 0xf5000000, 0x8c000000, 0xb1000000, 0xe3000000,
261 0x1d000000, 0xf6000000, 0xe2000000, 0x2e000000,
262 0x82000000, 0x66000000, 0xca000000, 0x60000000,
263 0xc0000000, 0x29000000, 0x23000000, 0xab000000,
264 0x0d000000, 0x53000000, 0x4e000000, 0x6f000000,
265 0xd5000000, 0xdb000000, 0x37000000, 0x45000000,
266 0xde000000, 0xfd000000, 0x8e000000, 0x2f000000,
267 0x03000000, 0xff000000, 0x6a000000, 0x72000000,
268 0x6d000000, 0x6c000000, 0x5b000000, 0x51000000,
269 0x8d000000, 0x1b000000, 0xaf000000, 0x92000000,
270 0xbb000000, 0xdd000000, 0xbc000000, 0x7f000000,
271 0x11000000, 0xd9000000, 0x5c000000, 0x41000000,
272 0x1f000000, 0x10000000, 0x5a000000, 0xd8000000,
273 0x0a000000, 0xc1000000, 0x31000000, 0x88000000,
274 0xa5000000, 0xcd000000, 0x7b000000, 0xbd000000,
275 0x2d000000, 0x74000000, 0xd0000000, 0x12000000,
276 0xb8000000, 0xe5000000, 0xb4000000, 0xb0000000,
277 0x89000000, 0x69000000, 0x97000000, 0x4a000000,
278 0x0c000000, 0x96000000, 0x77000000, 0x7e000000,
279 0x65000000, 0xb9000000, 0xf1000000, 0x09000000,
280 0xc5000000, 0x6e000000, 0xc6000000, 0x84000000,
281 0x18000000, 0xf0000000, 0x7d000000, 0xec000000,
282 0x3a000000, 0xdc000000, 0x4d000000, 0x20000000,
283 0x79000000, 0xee000000, 0x5f000000, 0x3e000000,
284 0xd7000000, 0xcb000000, 0x39000000, 0x48000000
286 #endif /* __i386__ */
288 /* Non-linear transform
289 * A = (a0, a1, a2, a3)
290 * B = (b0, b1, b2, b3)
291 * (b0, b1, b2, b3) = tau(A) = (Sbox(a0), Sbox(a1), Sbox(a2), Sbox(a3))
293 static INLINE uint32
294 tau(uint32 A)
296 uint32 B;
298 #if !defined(__i386__)
299 B = (S_box[A & 0xff] |
300 (S_box[(A & 0xff00) >> 8] << 8) |
301 (S_box[(A & 0xff0000) >> 16] << 16) |
302 (S_box[(A & 0xff000000) >> 24] << 24));
303 #else /* __i386__ */
304 /* slightly better performance on Pentium, worse performance on ARM CM3 */
305 B = (S_box0[A & 0xff] |
306 S_box1[(A & 0xff00) >> 8] |
307 S_box2[(A & 0xff0000) >> 16] |
308 S_box3[(A & 0xff000000) >> 24]);
309 #endif /* __i386__ */
311 return (B);
314 /* Linear transform
315 * C = L(B) = B ^ (B<<<2) ^ (B<<<10) ^ (B<<<18) ^ (B<<<24)
316 * where "<<<" is a circular left shift
318 static INLINE uint32
319 L(uint32 B)
321 uint32 Ba = B ^ ROTATE(B, 24);
322 return (Ba ^ ROTATE((ROTATE(Ba, 16) ^ B), 2));
325 /* Compound Transform
326 * T(.) = L(tau(.))
328 static INLINE uint32
329 T(uint32 X)
331 return (L(tau(X)));
334 /* Round Function
335 * F(X0,X1,X2,X3,RK) = X0 ^ T(X1^X2^X3^RK)
336 * static INLINE uint32
337 * F(uint32 *X, uint32 RK)
339 * return (X[0] ^ T(X[1] ^ X[2] ^ X[3] ^ RK));
343 /* Encryption/decryption algorithm
344 * Xi+4 = F(Xi, Xi+1, Xi+2, Xi+3, RKj) = Xi ^ T(Xi+1 ^ Xi+2 ^ Xi+3 ^ RKj)
345 * i=0,1,...31, j=i(enc) or j=31-i(dec)
346 * (Y0, Y1, Y2, Y3) = (X35, X34, X33, X32)
349 /* define SMS4_FULL_UNROLL to completely unroll F() - results in slightly faster but bigger code */
350 #define SMS4_FULL_UNROLL
352 void
353 sms4_enc(uint32 *Y, uint32 *X, const uint32 *RK)
355 uint32 z0 = X[0], z1 = X[1], z2 = X[2], z3 = X[3];
356 #ifndef SMS4_FULL_UNROLL
357 int i;
359 for (i = 0; i < SMS4_RK_WORDS; i += 4) {
360 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
361 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
362 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
363 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
365 #else /* SMS4_FULL_UNROLL */
366 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
367 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
368 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
369 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
370 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
371 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
372 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
373 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
374 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
375 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
376 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
377 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
378 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
379 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
380 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
381 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
382 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
383 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
384 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
385 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
386 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
387 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
388 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
389 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
390 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
391 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
392 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
393 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
394 z0 ^= T(z1 ^ z2 ^ z3 ^ *RK++);
395 z1 ^= T(z2 ^ z3 ^ z0 ^ *RK++);
396 z2 ^= T(z3 ^ z0 ^ z1 ^ *RK++);
397 z3 ^= T(z0 ^ z1 ^ z2 ^ *RK++);
398 #endif /* SMS4_FULL_UNROLL */
400 Y[0] = z3;
401 Y[1] = z2;
402 Y[2] = z1;
403 Y[3] = z0;
406 void
407 sms4_dec(uint32 *Y, uint32 *X, uint32 *RK)
409 uint32 z0 = X[0], z1 = X[1], z2 = X[2], z3 = X[3];
410 int i;
412 RK += 32;
414 for (i = 0; i < SMS4_RK_WORDS; i += 4) {
415 z0 ^= T(z1 ^ z2 ^ z3 ^ *--RK);
416 z1 ^= T(z2 ^ z3 ^ z0 ^ *--RK);
417 z2 ^= T(z3 ^ z0 ^ z1 ^ *--RK);
418 z3 ^= T(z0 ^ z1 ^ z2 ^ *--RK);
421 Y[0] = z3;
422 Y[1] = z2;
423 Y[2] = z1;
424 Y[3] = z0;
427 static const uint32 CK[] = {
428 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
429 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
430 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
431 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
432 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
433 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
434 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
435 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
438 static const uint32 FK[] = {
439 0xA3B1BAC6,
440 0x56AA3350,
441 0x677D9197,
442 0xB27022DC
445 /* Key Expansion Linear transform
446 * Lprime(B) = B ^ (B<<<13) ^ (B<<<23)
447 * where "<<<" is a circular left shift
449 static INLINE uint32
450 Lprime(uint32 B)
452 return (B ^ ROTATE(B, 13) ^ ROTATE(B, 23));
455 /* Key Expansion Compound Transform
456 * Tprime(.) = Lprime(tau(.))
458 static INLINE uint32
459 Tprime(uint32 X)
461 return (Lprime(tau(X)));
464 /* Key Expansion
465 * Encryption key MK = (MK0, MK1, MK2, MK3)
466 * (K0, K1, K2, K3) = (MK0 ^ FK0, MK1 ^ FK1, MK2 ^ FK2, MK3 ^ FK3)
467 * RKi = Ki+4 = Ki ^ Tprime(Ki+1 ^ Ki+2 ^ Ki+3 ^ CKi+4)
469 void
470 sms4_key_exp(uint32 *MK, uint32 *RK)
472 int i;
473 uint32 K[36];
475 for (i = 0; i < 4; i++)
476 K[i] = MK[i] ^ FK[i];
478 for (i = 0; i < SMS4_RK_WORDS; i++) {
479 K[i+4] = K[i] ^ Tprime(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]);
480 RK[i] = K[i+4];
483 return;
486 /* SMS4-CBC-MAC mode for WPI
487 * - computes SMS4_WPI_CBC_MAC_LEN MAC
488 * - Integrity Check Key must be SMS4_KEY_LEN bytes
489 * - PN must be SMS4_WPI_PN_LEN bytes
490 * - AAD inludes Key Index, Reserved, and L (data len) fields
491 * - For MAC calculation purposes, the aad and data are each padded with
492 * NULLs to a multiple of the block size
493 * - ptxt must have sufficient tailroom for storing the MAC
494 * - returns -1 on error
495 * - returns SMS4_WPI_SUCCESS on success, SMS4_WPI_CBC_MAC_ERROR on error
498 sms4_wpi_cbc_mac(const uint8 *ick,
499 const uint8 *pn,
500 const size_t aad_len,
501 const uint8 *aad,
502 uint8 *ptxt)
504 int k, j, rem_len;
505 uint32 RK[SMS4_RK_WORDS];
506 uint32 X[SMS4_BLOCK_WORDS], Y[SMS4_BLOCK_WORDS];
507 uint8 tmp[SMS4_BLOCK_SZ];
508 uint16 data_len = (aad[aad_len-2] << 8) | (aad[aad_len-1]);
510 if (data_len > SMS4_WPI_MAX_MPDU_LEN)
511 return (SMS4_WPI_CBC_MAC_ERROR);
513 sms4_print_bytes("MIC Key", (uchar *)ick, SMS4_WPI_CBC_MAC_LEN);
514 sms4_print_bytes("PN ", (uchar *)pn, SMS4_WPI_PN_LEN);
515 sms4_print_bytes("MIC data: PART1", (uchar *)aad, aad_len);
516 sms4_print_bytes("MIC data: PART 2", (uchar *)ptxt, data_len);
518 /* Prepare the round key */
519 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
520 if ((uintptr)ick & 3)
521 X[k] = ntoh32_ua(ick + (SMS4_WORD_SZ * k));
522 else
523 X[k] = ntoh32(*(uint32 *)(ick + (SMS4_WORD_SZ * k)));
524 sms4_key_exp(X, RK);
526 /* First block: PN */
527 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
528 if ((uintptr)pn & 3)
529 X[k] = ntoh32_ua(pn + (SMS4_WORD_SZ * k));
530 else
531 X[k] = ntoh32(*(uint32 *)(pn + (SMS4_WORD_SZ * k)));
532 sms4_enc(Y, X, RK);
534 /* Next blocks: AAD */
535 for (j = 0; j < aad_len/SMS4_BLOCK_SZ; j++) {
536 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
537 if ((uintptr)aad & 3)
538 X[k] = Y[k] ^ ntoh32_ua(aad + (SMS4_WORD_SZ * k));
539 else
540 X[k] = Y[k] ^ ntoh32(*(uint32 *)(aad + (SMS4_WORD_SZ * k)));
541 aad += SMS4_BLOCK_SZ;
542 sms4_enc(Y, X, RK);
544 /* If the last block is partial, pad with NULLs */
545 rem_len = aad_len % SMS4_BLOCK_SZ;
546 if (rem_len) {
547 bcopy(aad, tmp, rem_len);
548 bzero(tmp + rem_len, SMS4_BLOCK_SZ - rem_len);
549 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
550 if ((uintptr)tmp & 3)
551 X[k] = Y[k] ^ ntoh32_ua(tmp + (SMS4_WORD_SZ * k));
552 else
553 X[k] = Y[k] ^ ntoh32(*(uint32 *)(tmp + (SMS4_WORD_SZ * k)));
554 sms4_enc(Y, X, RK);
557 /* Then the message data */
558 for (j = 0; j < (data_len / SMS4_BLOCK_SZ); j++) {
559 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
560 if ((uintptr)ptxt & 3)
561 X[k] = Y[k] ^ ntoh32_ua(ptxt + (SMS4_WORD_SZ * k));
562 else
563 X[k] = Y[k] ^ ntoh32(*(uint32 *)(ptxt + (SMS4_WORD_SZ * k)));
564 ptxt += SMS4_BLOCK_SZ;
565 sms4_enc(Y, X, RK);
567 /* If the last block is partial, pad with NULLs */
568 rem_len = data_len % SMS4_BLOCK_SZ;
569 if (rem_len) {
570 bcopy(ptxt, tmp, rem_len);
571 bzero(tmp + rem_len, SMS4_BLOCK_SZ - rem_len);
572 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
573 if ((uintptr)tmp & 3)
574 X[k] = Y[k] ^ ntoh32_ua(tmp + (SMS4_WORD_SZ * k));
575 else
576 X[k] = Y[k] ^ ntoh32(*(uint32 *)(tmp + (SMS4_WORD_SZ * k)));
577 ptxt += data_len % SMS4_BLOCK_SZ;
578 sms4_enc(Y, X, RK);
581 for (k = 0; k < SMS4_BLOCK_WORDS; k++) {
582 hton32_ua_store(Y[k], ptxt);
583 ptxt += SMS4_WORD_SZ;
586 return (SMS4_WPI_SUCCESS);
590 * ick pn ptxt result
591 * ltoh ltoh ltoh fail
592 * ntoh ltoh ltoh fail
593 * ltoh ntoh ltoh fail
594 * ntoh ntoh ltoh fail
596 * ltoh ltoh ntoh fail
597 * ntoh ltoh ntoh fail
598 * ltoh ntoh ntoh fail
599 * ntoh ntoh ntoh fail
602 #define s_ick(a) ntoh32_ua(a)
603 #define s_pn(a) ntoh32_ua(a)
604 #define s_ptxt(a) ntoh32_ua(a)
606 #ifdef BCMSMS4_TEST
607 static int sms4_cbc_mac(const uint8 *ick, const uint8 *pn, const size_t data_len,
608 uint8 *ptxt, uint8 *mac);
609 static int
610 sms4_cbc_mac(const uint8 *ick,
611 const uint8 *pn,
612 const size_t data_len,
613 uint8 *ptxt,
614 uint8 *mac)
616 int k, j, rem_len;
617 uint32 RK[SMS4_RK_WORDS];
618 uint32 X[SMS4_BLOCK_WORDS], Y[SMS4_BLOCK_WORDS];
619 uint8 tmp[SMS4_BLOCK_SZ];
621 if (data_len > SMS4_WPI_MAX_MPDU_LEN)
622 return (SMS4_WPI_CBC_MAC_ERROR);
624 /* Prepare the round key */
625 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
626 X[k] = s_ick(ick + (SMS4_WORD_SZ * k));
627 sms4_key_exp(X, RK);
629 /* First block: PN */
630 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
631 X[k] = s_pn(pn + (SMS4_WORD_SZ * k));
632 sms4_enc(Y, X, RK);
634 /* Then the message data */
635 for (j = 0; j < (data_len / SMS4_BLOCK_SZ); j++) {
636 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
637 X[k] = Y[k] ^ s_ptxt(ptxt + (SMS4_WORD_SZ * k));
638 ptxt += SMS4_BLOCK_SZ;
639 sms4_enc(Y, X, RK);
641 /* If the last block is partial, pad with NULLs */
642 rem_len = data_len % SMS4_BLOCK_SZ;
643 if (rem_len) {
644 bcopy(ptxt, tmp, rem_len);
645 bzero(tmp + rem_len, SMS4_BLOCK_SZ - rem_len);
646 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
647 X[k] = Y[k] ^ s_ptxt(tmp + (SMS4_WORD_SZ * k));
648 ptxt += data_len % SMS4_BLOCK_SZ;
649 sms4_enc(Y, X, RK);
652 for (k = 0; k < SMS4_BLOCK_WORDS; k++) {
653 hton32_ua_store(Y[k], mac);
654 mac += SMS4_WORD_SZ;
657 return (SMS4_WPI_SUCCESS);
659 #endif /* BCMSMS4_TEST */
661 /* SMS4-OFB mode encryption/decryption algorithm
662 * - PN must be SMS4_WPI_PN_LEN bytes
663 * - assumes PN is ready to use as-is (i.e. any
664 * randomization of PN is handled by the caller)
665 * - encrypts data in place
666 * - returns SMS4_WPI_SUCCESS on success, SMS4_WPI_OFB_ERROR on error
669 sms4_ofb_crypt(const uint8 *ek,
670 const uint8 *pn,
671 const size_t data_len,
672 uint8 *ptxt)
674 size_t j, k;
675 uint8 tmp[SMS4_BLOCK_SZ];
676 uint32 RK[SMS4_RK_WORDS];
677 uint32 X[SMS4_BLOCK_WORDS];
679 if (data_len > SMS4_WPI_MAX_MPDU_LEN) return (SMS4_WPI_OFB_ERROR);
681 sms4_print_bytes("ENC Key", (uchar *)ek, SMS4_WPI_CBC_MAC_LEN);
682 sms4_print_bytes("PN ", (uint8 *)pn, SMS4_WPI_PN_LEN);
683 sms4_print_bytes("data", (uchar *)ptxt, data_len);
685 /* Prepare the round key */
686 for (k = 0; k < SMS4_BLOCK_WORDS; k++)
687 if ((uintptr)ek & 3)
688 X[k] = ntoh32_ua(ek + (SMS4_WORD_SZ * k));
689 else
690 X[k] = ntoh32(*(uint32 *)(ek + (SMS4_WORD_SZ * k)));
691 sms4_key_exp(X, RK);
693 for (k = 0; k < SMS4_BLOCK_WORDS; k++) {
694 if ((uintptr)pn & 3)
695 X[k] = ntoh32_ua(pn + (SMS4_WORD_SZ * k));
696 else
697 X[k] = ntoh32(*(uint32 *)(pn + (SMS4_WORD_SZ * k)));
700 for (k = 0; k < (data_len / SMS4_BLOCK_SZ); k++) {
701 sms4_enc(X, X, RK);
702 for (j = 0; j < SMS4_BLOCK_WORDS; j++) {
703 hton32_ua_store(X[j], &tmp[j * SMS4_WORD_SZ]);
705 xor_128bit_block(ptxt, tmp, ptxt);
706 ptxt += SMS4_BLOCK_SZ;
709 /* handle partial block */
710 if (data_len % SMS4_BLOCK_SZ) {
711 sms4_enc(X, X, RK);
712 for (j = 0; j < SMS4_BLOCK_WORDS; j++) {
713 hton32_ua_store(X[j], &tmp[j * SMS4_WORD_SZ]);
715 for (k = 0; k < (data_len % SMS4_BLOCK_SZ); k++)
716 ptxt[k] ^= tmp[k];
719 return (SMS4_WPI_SUCCESS);
722 /* SMS4-WPI mode encryption of 802.11 packet
723 * - constructs aad and pn from provided frame
724 * - calls sms4_wpi_cbc_mac() to compute MAC
725 * - calls sms4_ofb_crypt() to encrypt frame
726 * - encrypts data in place
727 * - supplied packet must have sufficient tailroom for CBC-MAC MAC
728 * - data_len includes 802.11 header and CBC-MAC MAC
729 * - returns SMS4_WPI_SUCCESS on success, SMS4_WPI_ENCRYPT_ERROR on error
732 sms4_wpi_pkt_encrypt(const uint8 *ek,
733 const uint8 *ick,
734 const size_t data_len,
735 uint8 *p)
737 uint8 aad[SMS4_WPI_MAX_AAD_LEN];
738 uint8 *paad = aad;
739 struct dot11_header *h = (struct dot11_header *)p;
740 struct wpi_iv *iv_data;
741 uint16 fc, seq;
742 uint header_len, aad_len, qos_len = 0, hdr_add_len = 0;
743 bool wds = FALSE;
744 uint8 tmp[SMS4_BLOCK_SZ];
745 int k;
747 bzero(aad, SMS4_WPI_MAX_AAD_LEN);
749 fc = ltoh16_ua(&(h->fc));
751 /* WPI only supports protection of DATA frames */
752 if (FC_TYPE(fc) != FC_TYPE_DATA)
753 return (SMS4_WPI_ENCRYPT_ERROR);
755 /* frame must have Protected flag set */
756 if (!(fc & FC_WEP))
757 return (SMS4_WPI_ENCRYPT_ERROR);
759 /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */
760 if (FC_SUBTYPE(fc) & FC_SUBTYPE_QOS_DATA)
761 qos_len += 2;
763 /* length of A4, if using wds frames */
764 wds = ((fc & (FC_TODS | FC_FROMDS)) == (FC_TODS | FC_FROMDS));
765 if (wds)
766 hdr_add_len += ETHER_ADDR_LEN;
768 /* length of MPDU header, including PN */
769 header_len = DOT11_A3_HDR_LEN + SMS4_WPI_IV_LEN + hdr_add_len + qos_len;
771 /* pointer to IV */
772 iv_data = (struct wpi_iv *)(p + DOT11_A3_HDR_LEN + qos_len + hdr_add_len);
774 /* Payload must be > 0 bytes */
775 if (data_len <= (header_len + SMS4_WPI_CBC_MAC_LEN))
776 return (SMS4_WPI_ENCRYPT_ERROR);
778 /* aad: maskedFC || A1 || A2 || maskedSC || A3 || A4 || KeyIdx || Reserved || L */
780 fc &= SMS4_WPI_FC_MASK;
781 *paad++ = (uint8)(fc & 0xff);
782 *paad++ = (uint8)((fc >> 8) & 0xff);
784 bcopy((uchar *)&h->a1, paad, 2*ETHER_ADDR_LEN);
785 paad += 2*ETHER_ADDR_LEN;
787 seq = ltoh16_ua(&(h->seq));
788 seq &= FRAGNUM_MASK;
790 *paad++ = (uint8)(seq & 0xff);
791 *paad++ = (uint8)((seq >> 8) & 0xff);
793 bcopy((uchar *)&h->a3, paad, ETHER_ADDR_LEN);
794 paad += ETHER_ADDR_LEN;
796 if (wds) {
797 bcopy((uchar *)&h->a4, paad, ETHER_ADDR_LEN);
799 /* A4 for the MIC, even when there is no A4 in the packet */
800 paad += ETHER_ADDR_LEN;
802 if (qos_len) {
803 *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len];
804 *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len + 1];
807 *paad++ = iv_data->key_idx;
808 *paad++ = iv_data->reserved;
810 *paad++ = ((data_len - header_len - SMS4_WPI_CBC_MAC_LEN) >> 8) & 0xff;
811 *paad++ = (data_len - header_len - SMS4_WPI_CBC_MAC_LEN) & 0xff;
813 /* length of AAD */
814 aad_len = SMS4_WPI_MIN_AAD_LEN + qos_len;
816 for (k = 0; k < SMS4_BLOCK_SZ; k++)
817 tmp[SMS4_BLOCK_SZ-(k+1)] = (iv_data->PN)[k];
819 /* calculate MAC */
820 if (sms4_wpi_cbc_mac(ick, tmp, aad_len, aad, p + header_len))
821 return (SMS4_WPI_ENCRYPT_ERROR);
823 /* encrypt data */
824 if (sms4_ofb_crypt(ek, tmp, data_len - header_len, p + header_len))
825 return (SMS4_WPI_ENCRYPT_ERROR);
827 return (SMS4_WPI_SUCCESS);
830 /* SMS4-WPI mode decryption of 802.11 packet
831 * - constructs aad and pn from provided frame
832 * - calls sms4_ofb_crypt() to decrypt frame
833 * - calls sms4_wpi_cbc_mac() to compute MAC
834 * - decrypts in place
835 * - data_len includes 802.11 header and CBC-MAC MAC
836 * - returns SMS4_WPI_DECRYPT_ERROR on general error
839 sms4_wpi_pkt_decrypt(const uint8 *ek,
840 const uint8 *ick,
841 const size_t data_len,
842 uint8 *p)
844 uint8 aad[SMS4_WPI_MAX_AAD_LEN];
845 uint8 MAC[SMS4_WPI_CBC_MAC_LEN];
846 uint8 *paad = aad;
847 struct dot11_header *h = (struct dot11_header *)p;
848 struct wpi_iv *iv_data;
849 uint16 fc, seq;
850 uint header_len, aad_len, qos_len = 0, hdr_add_len = 0;
851 bool wds = FALSE;
852 uint8 tmp[SMS4_BLOCK_SZ];
853 int k;
855 bzero(aad, SMS4_WPI_MAX_AAD_LEN);
857 fc = ltoh16_ua(&(h->fc));
859 /* WPI only supports protection of DATA frames */
860 if (FC_TYPE(fc) != FC_TYPE_DATA)
861 return (SMS4_WPI_DECRYPT_ERROR);
863 /* frame must have Protected flag set */
864 if (!(fc & FC_WEP))
865 return (SMS4_WPI_DECRYPT_ERROR);
867 /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */
868 if ((FC_SUBTYPE(fc) & FC_SUBTYPE_QOS_DATA))
869 qos_len += 2;
871 /* length of A4, if using wds frames */
872 wds = ((fc & (FC_TODS | FC_FROMDS)) == (FC_TODS | FC_FROMDS));
873 if (wds)
874 hdr_add_len += ETHER_ADDR_LEN;
876 /* length of MPDU header, including PN */
877 header_len = DOT11_A3_HDR_LEN + SMS4_WPI_IV_LEN + hdr_add_len + qos_len;
879 /* pointer to IV */
880 iv_data = (struct wpi_iv *)(p + DOT11_A3_HDR_LEN + qos_len + hdr_add_len);
882 /* Payload must be > 0 bytes plus MAC */
883 if (data_len <= (header_len + SMS4_WPI_CBC_MAC_LEN))
884 return (SMS4_WPI_DECRYPT_ERROR);
886 /* aad: maskedFC || A1 || A2 || maskedSC || A3 || A4 || KeyIdx || Reserved || L */
888 fc &= SMS4_WPI_FC_MASK;
889 *paad++ = (uint8)(fc & 0xff);
890 *paad++ = (uint8)((fc >> 8) & 0xff);
892 bcopy((uchar *)&h->a1, paad, 2*ETHER_ADDR_LEN);
893 paad += 2*ETHER_ADDR_LEN;
895 seq = ltoh16_ua(&(h->seq));
896 seq &= FRAGNUM_MASK;
898 *paad++ = (uint8)(seq & 0xff);
899 *paad++ = (uint8)((seq >> 8) & 0xff);
901 bcopy((uchar *)&h->a3, paad, ETHER_ADDR_LEN);
902 paad += ETHER_ADDR_LEN;
904 if (wds) {
905 bcopy((uchar *)&h->a4, paad, ETHER_ADDR_LEN);
907 /* A4 for the MIC, even when there is no A4 in the packet */
908 paad += ETHER_ADDR_LEN;
910 if (qos_len) {
911 *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len];
912 *paad++ = p[DOT11_A3_HDR_LEN + hdr_add_len + 1];
915 *paad++ = iv_data->key_idx;
916 *paad++ = iv_data->reserved;
918 *paad++ = ((data_len - header_len - SMS4_WPI_CBC_MAC_LEN) >> 8) & 0xff;
919 *paad++ = (data_len - header_len - SMS4_WPI_CBC_MAC_LEN) & 0xff;
921 /* length of AAD */
922 aad_len = SMS4_WPI_MIN_AAD_LEN + qos_len;
924 for (k = 0; k < SMS4_BLOCK_SZ; k++)
925 tmp[SMS4_BLOCK_SZ-(k+1)] = (iv_data->PN)[k];
927 /* decrypt data */
928 if (sms4_ofb_crypt(ek, tmp, data_len - header_len,
929 p + header_len))
930 return (SMS4_WPI_DECRYPT_ERROR);
932 /* store MAC */
933 bcopy(p + data_len - SMS4_WPI_CBC_MAC_LEN, MAC, SMS4_WPI_CBC_MAC_LEN);
935 /* calculate MAC */
936 if (sms4_wpi_cbc_mac(ick, tmp, aad_len, aad, p + header_len))
937 return (SMS4_WPI_DECRYPT_ERROR);
939 /* compare MAC */
940 if (bcmp(p + data_len - SMS4_WPI_CBC_MAC_LEN, MAC, SMS4_WPI_CBC_MAC_LEN))
941 return (SMS4_WPI_CBC_MAC_ERROR);
943 return (SMS4_WPI_SUCCESS);
946 #ifdef BCMSMS4_TEST
947 #include <stdlib.h>
948 #include <bcmcrypto/sms4_vectors.h>
950 #ifdef BCMSMS4_TEST_EMBED
952 /* Number of iterations is sensitive to the state of the test vectors since
953 * encrypt and decrypt are done in place
955 #define SMS4_TIMING_ITER 100
956 #define dbg(args)
957 #define pres(label, len, data)
959 /* returns current time in msec */
960 static void
961 get_time(uint *t)
963 *t = hndrte_time();
966 #else
967 #ifdef BCMDRIVER
969 /* Number of iterations is sensitive to the state of the test vectors since
970 * encrypt and decrypt are done in place
972 #define SMS4_TIMING_ITER 1000
973 #define dbg(args) printk args
974 #define pres(label, len, data)
976 /* returns current time in msec */
977 static void
978 get_time(uint *t)
980 *t = jiffies_to_msecs(jiffies);
983 #else
985 #define SMS4_TIMING_ITER 10000
986 #include <stdio.h>
987 #define dbg(args) printf args
989 #include <sys/time.h>
991 /* returns current time in msec */
992 static void
993 get_time(uint *t)
995 struct timeval ts;
996 gettimeofday(&ts, NULL);
997 *t = ts.tv_sec * 1000 + ts.tv_usec / 1000;
1000 void
1001 pres(const char *label, const size_t len, const uint8 *data)
1003 int k;
1004 printf("%s\n", label);
1005 for (k = 0; k < len; k++) {
1006 printf("0x%02x, ", data[k]);
1007 if (!((k + 1) % (SMS4_BLOCK_SZ/2)))
1008 printf("\n");
1010 printf("\n");
1012 #endif /* BCMDRIVER */
1013 #endif /* BCMSMS4_TEST_EMBED */
1016 sms4_test_enc_dec()
1018 uint tstart, tend;
1019 int i, j, k, fail = 0;
1020 uint32 RK[32];
1021 uint32 X[SMS4_BLOCK_WORDS], Y[SMS4_BLOCK_WORDS];
1023 for (k = 0; k < NUM_SMS4_VECTORS; k++) {
1024 /* Note that the algorithm spec example output lists X[0] -
1025 * X[32], but those should really be labelled X[4] - X[35]
1026 * (they're the round output, not the input)
1029 dbg(("sms4_test_enc_dec: Instance %d:\n", k + 1));
1030 dbg(("sms4_test_enc_dec: Plain Text:\n"));
1031 for (i = 0; i < SMS4_BLOCK_WORDS; i++)
1032 dbg(("sms4_test_enc_dec: PlainText[%02d] = 0x%08x\n",
1033 i, sms4_vec[k].input[i]));
1035 dbg(("sms4_test_enc_dec: Encryption Master Key:\n"));
1036 for (i = 0; i < SMS4_BLOCK_WORDS; i++)
1037 dbg(("sms4_test_enc_dec: MK[%02d] = 0x%08x\n",
1038 i, sms4_vec[k].key[i]));
1040 sms4_key_exp(sms4_vec[k].key, RK);
1041 dbg(("sms4_test_enc_dec: Round Key:\n"));
1042 for (i = 0; i < SMS4_RK_WORDS; i++)
1043 dbg(("sms4_test_enc_dec: rk[%02d] = 0x%08x\n",
1044 i, RK[i]));
1046 for (j = 0; j < SMS4_BLOCK_WORDS; j++)
1047 Y[j] = sms4_vec[k].input[j];
1048 get_time(&tstart);
1049 for (i = 0; i < *sms4_vec[k].niter; i++) {
1050 for (j = 0; j < SMS4_BLOCK_WORDS; j++)
1051 X[j] = Y[j];
1052 sms4_enc(Y, X, RK);
1054 get_time(&tend);
1055 dbg(("sms4_test_enc_dec: Cipher Text:\n"));
1056 for (i = 0; i < SMS4_BLOCK_WORDS; i++)
1057 dbg(("sms4_test_enc_dec: CipherText[%02d] = 0x%08x\n",
1058 i, Y[i]));
1059 dbg(("sms4_test_enc_dec: Time for Instance %d Encrypt: %d msec\n",
1060 k + 1, tend - tstart));
1061 for (j = 0; j < SMS4_BLOCK_WORDS; j++) {
1062 if (Y[j] != sms4_vec[k].ref[j]) {
1063 dbg(("sms4_test_enc_dec: sms4_enc failed\n"));
1064 fail++;
1068 for (j = 0; j < SMS4_BLOCK_WORDS; j++)
1069 X[j] = sms4_vec[k].ref[j];
1070 get_time(&tstart);
1071 for (i = 0; i < *sms4_vec[k].niter; i++) {
1072 for (j = 0; j < SMS4_BLOCK_WORDS; j++)
1073 X[j] = Y[j];
1074 sms4_dec(Y, X, RK);
1076 get_time(&tend);
1077 dbg(("sms4_test_enc_dec: Decrypted Plain Text:\n"));
1078 for (i = 0; i < SMS4_BLOCK_WORDS; i++)
1079 dbg(("sms4_test_enc_dec: PlainText[%02d] = 0x%08x\n", i, Y[i]));
1080 dbg(("sms4_test_enc_dec: Time for Instance %d Decrypt: %d msec\n",
1081 k + 1, tend - tstart));
1082 for (j = 0; j < SMS4_BLOCK_WORDS; j++) {
1083 if (Y[j] != sms4_vec[k].input[j]) {
1084 dbg(("sms4_test_enc_dec: sms4_dec failed\n"));
1085 fail++;
1089 dbg(("\n"));
1092 return (fail);
1096 sms4_test_cbc_mac()
1098 int retv, k, fail = 0;
1100 uint8 mac[SMS4_WPI_CBC_MAC_LEN];
1102 for (k = 0; k < NUM_SMS4_CBC_MAC_VECTORS; k++) {
1103 dbg(("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC vector %d\n", k));
1104 retv = sms4_cbc_mac(sms4_cbc_mac_vec[k].ick,
1105 sms4_cbc_mac_vec[k].pn,
1106 sms4_cbc_mac_vec[k].al,
1107 sms4_cbc_mac_vec[k].input,
1108 mac);
1109 if (retv) {
1110 dbg(("sms4_test_cbc_mac: sms4_wpi_cbc_mac of vector %d returned error %d\n",
1111 k, retv));
1112 fail++;
1115 pres("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC computed: ", SMS4_WPI_CBC_MAC_LEN,
1116 mac);
1117 pres("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC reference: ", SMS4_WPI_CBC_MAC_LEN,
1118 sms4_cbc_mac_vec[k].ref);
1120 if (bcmp(mac, sms4_cbc_mac_vec[k].ref, SMS4_WPI_CBC_MAC_LEN) != 0) {
1121 dbg(("sms4_test_cbc_mac: sms4_wpi_cbc_mac of vector %d"
1122 " reference mismatch\n", k));
1123 fail++;
1127 dbg(("\n"));
1128 return (fail);
1132 sms4_test_ofb_crypt()
1134 int retv, k, fail = 0;
1136 for (k = 0; k < NUM_SMS4_OFB_VECTORS; k++) {
1137 dbg(("sms4_test_ofb_crypt: SMS4-OFB vector %d\n", k));
1138 retv = sms4_ofb_crypt(sms4_ofb_vec[k].ek,
1139 sms4_ofb_vec[k].pn,
1140 sms4_ofb_vec[k].il,
1141 sms4_ofb_vec[k].input);
1142 if (retv) {
1143 dbg(("sms4_test_ofb_crypt: encrypt of vector %d returned error %d\n",
1144 k, retv));
1145 fail++;
1148 pres("sms4_test_ofb_crypt: SMS4-OFB ctxt: ",
1149 sms4_ofb_vec[k].il, sms4_ofb_vec[k].input);
1151 pres("sms4_test_ofb_crypt: SMS4-OFB ref: ",
1152 sms4_ofb_vec[k].il, sms4_ofb_vec[k].ref);
1154 if (bcmp(sms4_ofb_vec[k].input, sms4_ofb_vec[k].ref,
1155 sms4_ofb_vec[k].il) != 0) {
1156 dbg(("sms4_test_ofb_crypt: sms4_ofb_crypt of vector %d"
1157 " reference mismatch\n", k));
1158 fail++;
1161 /* Run again to decrypt and restore vector */
1162 retv = sms4_ofb_crypt(sms4_ofb_vec[k].ek,
1163 sms4_ofb_vec[k].pn,
1164 sms4_ofb_vec[k].il,
1165 sms4_ofb_vec[k].input);
1166 if (retv) {
1167 dbg(("sms4_test_ofb_crypt: decrypt of vector %d returned error %d\n",
1168 k, retv));
1169 fail++;
1173 dbg(("\n"));
1174 return (fail);
1178 sms4_test_wpi_pkt_encrypt_decrypt_timing(int *t)
1180 uint tstart, tend;
1181 int retv, j, k, fail = 0;
1183 *t = 0;
1185 for (k = 0; k < NUM_SMS4_WPI_TIMING_VECTORS; k++) {
1186 dbg(("sms4_test_wpi_pkt_encrypt_decrypt_timing: timing SMS4-WPI vector %d\n", k));
1187 get_time(&tstart);
1188 for (j = 0; j < SMS4_TIMING_ITER; j++) {
1189 retv = sms4_wpi_pkt_encrypt(sms4_wpi_tpkt_vec[k].ek,
1190 sms4_wpi_tpkt_vec[k].ick,
1191 sms4_wpi_tpkt_vec[k].il,
1192 sms4_wpi_tpkt_vec[k].input);
1193 if (retv) {
1194 fail++;
1197 retv = sms4_wpi_pkt_decrypt(sms4_wpi_tpkt_vec[k].ek,
1198 sms4_wpi_tpkt_vec[k].ick,
1199 sms4_wpi_tpkt_vec[k].il,
1200 sms4_wpi_tpkt_vec[k].input);
1201 if (retv) {
1202 fail++;
1206 get_time(&tend);
1208 dbg(("sms4_test_wpi_pkt_encrypt_decrypt_timing: Time for %d iterations of SMS4-WPI "
1209 " vector %d (total MPDU length %d): %d msec\n",
1210 SMS4_TIMING_ITER, k, sms4_wpi_tpkt_vec[k].il, tend - tstart));
1212 *t += tend - tstart;
1216 return (fail);
1220 sms4_test_wpi_pkt_encrypt()
1222 int retv, k, fail = 0;
1224 for (k = 0; k < NUM_SMS4_WPI_PKT_VECTORS; k++) {
1225 dbg(("sms4_test_wpi_pkt_encrypt: SMS4-WPI packet vector %d\n", k));
1226 pres("sms4_test_wpi_pkt_encrypt: SMS4-WPI ptxt: ",
1227 sms4_wpi_pkt_vec[k].il,
1228 sms4_wpi_pkt_vec[k].input);
1230 retv = sms4_wpi_pkt_encrypt(sms4_wpi_pkt_vec[k].ek,
1231 sms4_wpi_pkt_vec[k].ick,
1232 sms4_wpi_pkt_vec[k].il,
1233 sms4_wpi_pkt_vec[k].input);
1234 if (retv) {
1235 dbg(("sms4_test_wpi_pkt_encrypt: sms4_wpi_pkt_encrypt of vector %d"
1236 " returned error %d\n", k, retv));
1237 fail++;
1240 pres("sms4_test_wpi_pkt_encrypt: SMS4-WPI ctxt: ",
1241 sms4_wpi_pkt_vec[k].il,
1242 sms4_wpi_pkt_vec[k].input);
1244 pres("sms4_test_wpi_pkt_encrypt: SMS4-WPI ref: ",
1245 sms4_wpi_pkt_vec[k].il,
1246 sms4_wpi_pkt_vec[k].ref);
1248 if (bcmp(sms4_wpi_pkt_vec[k].input, sms4_wpi_pkt_vec[k].ref,
1249 sms4_wpi_pkt_vec[k].il) != 0) {
1250 dbg(("sms4_test_wpi_pkt_encrypt: sms4_wpi_pkt_encrypt of vector %d"
1251 " reference mismatch\n", k));
1252 fail++;
1256 dbg(("\n"));
1257 return (fail);
1261 sms4_test_wpi_pkt_decrypt()
1263 int retv, k, fail = 0;
1265 for (k = 0; k < NUM_SMS4_WPI_PKT_VECTORS; k++) {
1266 dbg(("sms4_test_wpi_pkt_decrypt: SMS4-WPI packet vector %d\n", k));
1267 pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ctxt: ",
1268 sms4_wpi_pkt_vec[k].il,
1269 sms4_wpi_pkt_vec[k].input);
1271 pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ref: ",
1272 sms4_wpi_pkt_vec[k].il,
1273 sms4_wpi_pkt_vec[k].ref);
1275 retv = sms4_wpi_pkt_decrypt(sms4_wpi_pkt_vec[k].ek,
1276 sms4_wpi_pkt_vec[k].ick,
1277 sms4_wpi_pkt_vec[k].il,
1278 sms4_wpi_pkt_vec[k].input);
1279 if (retv) {
1280 dbg(("sms4_test_wpi_pkt_decrypt: sms4_wpi_pkt_decrypt of vector %d"
1281 " returned error %d\n", k, retv));
1282 fail++;
1285 pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ptxt: ",
1286 sms4_wpi_pkt_vec[k].il,
1287 sms4_wpi_pkt_vec[k].input);
1290 dbg(("\n"));
1291 return (fail);
1295 sms4_test_wpi_pkt_micfail()
1297 int retv, k, fail = 0;
1298 uint8 *pkt;
1300 for (k = 0; k < NUM_SMS4_WPI_PKT_VECTORS; k++) {
1301 /* copy the reference data, with an error in the last byte */
1302 pkt = malloc(sms4_wpi_pkt_vec[k].il);
1303 if (pkt == NULL) {
1304 dbg(("%s: out of memory\n", __FUNCTION__));
1305 fail++;
1306 return (fail);
1309 bcopy(sms4_wpi_pkt_vec[k].ref, pkt, sms4_wpi_pkt_vec[k].il);
1311 /* create an error in the last byte of the MIC */
1312 pkt[sms4_wpi_pkt_vec[k].il - 1]++;
1314 /* decrypt */
1315 dbg(("sms4_test_wpi_pkt_decrypt: SMS4-WPI packet vector %d\n", k));
1316 retv = sms4_wpi_pkt_decrypt(sms4_wpi_pkt_vec[k].ek,
1317 sms4_wpi_pkt_vec[k].ick,
1318 sms4_wpi_pkt_vec[k].il,
1319 pkt);
1320 if (!retv) {
1321 dbg(("sms4_test_wpi_pkt_decrypt: sms4_wpi_pkt_decrypt of vector %d"
1322 " did not return expected error %d\n", k, retv));
1323 fail++;
1326 free(pkt);
1329 dbg(("\n"));
1330 return (fail);
1334 sms4_test(int *t)
1336 int fail = 0;
1338 *t = 0;
1340 #ifndef BCMSMS4_TEST_EMBED
1341 fail += sms4_test_enc_dec();
1342 fail += sms4_test_cbc_mac();
1343 fail += sms4_test_ofb_crypt();
1344 #endif
1346 /* since encrypt and decrypt are done in place, and these
1347 * functions use the same vectors, the tests must be run in order
1349 fail += sms4_test_wpi_pkt_encrypt();
1350 fail += sms4_test_wpi_pkt_decrypt();
1351 fail += sms4_test_wpi_pkt_micfail();
1353 fail += sms4_test_wpi_pkt_encrypt_decrypt_timing(t);
1355 return (fail);
1358 #ifdef BCMSMS4_TEST_STANDALONE
1360 main(int argc, char **argv)
1362 int fail = 0, t;
1364 fail += sms4_test(&t);
1366 dbg(("%s: timing result: %d msec\n", __FUNCTION__, t));
1367 fprintf(stderr, "%s: %s\n", *argv, fail ? "FAILED" : "PASSED");
1368 return (fail);
1371 #endif /* BCMSMS4_TEST_STANDALONE */
1373 #endif /* BCMSMS4_TEST */
1375 #endif /* BCMWAPI_WPI */