6 * Copyright (C) 2010, Broadcom Corporation
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 $
18 #include <bcmendian.h>
19 #include <proto/802.11.h>
20 #include <bcmcrypto/sms4.h>
27 #include <stddef.h> /* for size_t */
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
);
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))
37 #endif /* BCMDRIVER */
39 #define ROTATE(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
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
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))
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));
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__ */
315 * C = L(B) = B ^ (B<<<2) ^ (B<<<10) ^ (B<<<18) ^ (B<<<24)
316 * where "<<<" is a circular left shift
321 uint32 Ba
= B
^ ROTATE(B
, 24);
322 return (Ba
^ ROTATE((ROTATE(Ba
, 16) ^ B
), 2));
325 /* Compound Transform
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
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
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 */
407 sms4_dec(uint32
*Y
, uint32
*X
, uint32
*RK
)
409 uint32 z0
= X
[0], z1
= X
[1], z2
= X
[2], z3
= X
[3];
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
);
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
[] = {
445 /* Key Expansion Linear transform
446 * Lprime(B) = B ^ (B<<<13) ^ (B<<<23)
447 * where "<<<" is a circular left shift
452 return (B
^ ROTATE(B
, 13) ^ ROTATE(B
, 23));
455 /* Key Expansion Compound Transform
456 * Tprime(.) = Lprime(tau(.))
461 return (Lprime(tau(X
)));
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)
470 sms4_key_exp(uint32
*MK
, uint32
*RK
)
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
]);
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
,
500 const size_t aad_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
));
523 X
[k
] = ntoh32(*(uint32
*)(ick
+ (SMS4_WORD_SZ
* k
)));
526 /* First block: PN */
527 for (k
= 0; k
< SMS4_BLOCK_WORDS
; k
++)
529 X
[k
] = ntoh32_ua(pn
+ (SMS4_WORD_SZ
* k
));
531 X
[k
] = ntoh32(*(uint32
*)(pn
+ (SMS4_WORD_SZ
* k
)));
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
));
540 X
[k
] = Y
[k
] ^ ntoh32(*(uint32
*)(aad
+ (SMS4_WORD_SZ
* k
)));
541 aad
+= SMS4_BLOCK_SZ
;
544 /* If the last block is partial, pad with NULLs */
545 rem_len
= aad_len
% SMS4_BLOCK_SZ
;
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
));
553 X
[k
] = Y
[k
] ^ ntoh32(*(uint32
*)(tmp
+ (SMS4_WORD_SZ
* k
)));
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
));
563 X
[k
] = Y
[k
] ^ ntoh32(*(uint32
*)(ptxt
+ (SMS4_WORD_SZ
* k
)));
564 ptxt
+= SMS4_BLOCK_SZ
;
567 /* If the last block is partial, pad with NULLs */
568 rem_len
= data_len
% SMS4_BLOCK_SZ
;
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
));
576 X
[k
] = Y
[k
] ^ ntoh32(*(uint32
*)(tmp
+ (SMS4_WORD_SZ
* k
)));
577 ptxt
+= data_len
% SMS4_BLOCK_SZ
;
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
);
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)
607 static int sms4_cbc_mac(const uint8
*ick
, const uint8
*pn
, const size_t data_len
,
608 uint8
*ptxt
, uint8
*mac
);
610 sms4_cbc_mac(const uint8
*ick
,
612 const size_t data_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
));
629 /* First block: PN */
630 for (k
= 0; k
< SMS4_BLOCK_WORDS
; k
++)
631 X
[k
] = s_pn(pn
+ (SMS4_WORD_SZ
* k
));
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
;
641 /* If the last block is partial, pad with NULLs */
642 rem_len
= data_len
% SMS4_BLOCK_SZ
;
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
;
652 for (k
= 0; k
< SMS4_BLOCK_WORDS
; k
++) {
653 hton32_ua_store(Y
[k
], mac
);
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
,
671 const size_t data_len
,
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
++)
688 X
[k
] = ntoh32_ua(ek
+ (SMS4_WORD_SZ
* k
));
690 X
[k
] = ntoh32(*(uint32
*)(ek
+ (SMS4_WORD_SZ
* k
)));
693 for (k
= 0; k
< SMS4_BLOCK_WORDS
; k
++) {
695 X
[k
] = ntoh32_ua(pn
+ (SMS4_WORD_SZ
* k
));
697 X
[k
] = ntoh32(*(uint32
*)(pn
+ (SMS4_WORD_SZ
* k
)));
700 for (k
= 0; k
< (data_len
/ SMS4_BLOCK_SZ
); k
++) {
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
) {
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
++)
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
,
734 const size_t data_len
,
737 uint8 aad
[SMS4_WPI_MAX_AAD_LEN
];
739 struct dot11_header
*h
= (struct dot11_header
*)p
;
740 struct wpi_iv
*iv_data
;
742 uint header_len
, aad_len
, qos_len
= 0, hdr_add_len
= 0;
744 uint8 tmp
[SMS4_BLOCK_SZ
];
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 */
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
)
763 /* length of A4, if using wds frames */
764 wds
= ((fc
& (FC_TODS
| FC_FROMDS
)) == (FC_TODS
| FC_FROMDS
));
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
;
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
));
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
;
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
;
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;
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
];
820 if (sms4_wpi_cbc_mac(ick
, tmp
, aad_len
, aad
, p
+ header_len
))
821 return (SMS4_WPI_ENCRYPT_ERROR
);
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
,
841 const size_t data_len
,
844 uint8 aad
[SMS4_WPI_MAX_AAD_LEN
];
845 uint8 MAC
[SMS4_WPI_CBC_MAC_LEN
];
847 struct dot11_header
*h
= (struct dot11_header
*)p
;
848 struct wpi_iv
*iv_data
;
850 uint header_len
, aad_len
, qos_len
= 0, hdr_add_len
= 0;
852 uint8 tmp
[SMS4_BLOCK_SZ
];
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 */
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
))
871 /* length of A4, if using wds frames */
872 wds
= ((fc
& (FC_TODS
| FC_FROMDS
)) == (FC_TODS
| FC_FROMDS
));
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
;
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
));
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
;
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
;
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;
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
];
928 if (sms4_ofb_crypt(ek
, tmp
, data_len
- header_len
,
930 return (SMS4_WPI_DECRYPT_ERROR
);
933 bcopy(p
+ data_len
- SMS4_WPI_CBC_MAC_LEN
, MAC
, SMS4_WPI_CBC_MAC_LEN
);
936 if (sms4_wpi_cbc_mac(ick
, tmp
, aad_len
, aad
, p
+ header_len
))
937 return (SMS4_WPI_DECRYPT_ERROR
);
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
);
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
957 #define pres(label, len, data)
959 /* returns current time in msec */
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 */
980 *t
= jiffies_to_msecs(jiffies
);
985 #define SMS4_TIMING_ITER 10000
987 #define dbg(args) printf args
989 #include <sys/time.h>
991 /* returns current time in msec */
996 gettimeofday(&ts
, NULL
);
997 *t
= ts
.tv_sec
* 1000 + ts
.tv_usec
/ 1000;
1001 pres(const char *label
, const size_t len
, const uint8
*data
)
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)))
1012 #endif /* BCMDRIVER */
1013 #endif /* BCMSMS4_TEST_EMBED */
1019 int i
, j
, k
, fail
= 0;
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",
1046 for (j
= 0; j
< SMS4_BLOCK_WORDS
; j
++)
1047 Y
[j
] = sms4_vec
[k
].input
[j
];
1049 for (i
= 0; i
< *sms4_vec
[k
].niter
; i
++) {
1050 for (j
= 0; j
< SMS4_BLOCK_WORDS
; j
++)
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",
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"));
1068 for (j
= 0; j
< SMS4_BLOCK_WORDS
; j
++)
1069 X
[j
] = sms4_vec
[k
].ref
[j
];
1071 for (i
= 0; i
< *sms4_vec
[k
].niter
; i
++) {
1072 for (j
= 0; j
< SMS4_BLOCK_WORDS
; j
++)
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"));
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
,
1110 dbg(("sms4_test_cbc_mac: sms4_wpi_cbc_mac of vector %d returned error %d\n",
1115 pres("sms4_test_cbc_mac: SMS4-WPI-CBC-MAC computed: ", SMS4_WPI_CBC_MAC_LEN
,
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
));
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
,
1141 sms4_ofb_vec
[k
].input
);
1143 dbg(("sms4_test_ofb_crypt: encrypt of vector %d returned error %d\n",
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
));
1161 /* Run again to decrypt and restore vector */
1162 retv
= sms4_ofb_crypt(sms4_ofb_vec
[k
].ek
,
1165 sms4_ofb_vec
[k
].input
);
1167 dbg(("sms4_test_ofb_crypt: decrypt of vector %d returned error %d\n",
1178 sms4_test_wpi_pkt_encrypt_decrypt_timing(int *t
)
1181 int retv
, j
, k
, fail
= 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
));
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
);
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
);
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
;
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
);
1235 dbg(("sms4_test_wpi_pkt_encrypt: sms4_wpi_pkt_encrypt of vector %d"
1236 " returned error %d\n", k
, retv
));
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
));
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
);
1280 dbg(("sms4_test_wpi_pkt_decrypt: sms4_wpi_pkt_decrypt of vector %d"
1281 " returned error %d\n", k
, retv
));
1285 pres("sms4_test_wpi_pkt_decrypt: SMS4-WPI ptxt: ",
1286 sms4_wpi_pkt_vec
[k
].il
,
1287 sms4_wpi_pkt_vec
[k
].input
);
1295 sms4_test_wpi_pkt_micfail()
1297 int retv
, k
, fail
= 0;
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
);
1304 dbg(("%s: out of memory\n", __FUNCTION__
));
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]++;
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
,
1321 dbg(("sms4_test_wpi_pkt_decrypt: sms4_wpi_pkt_decrypt of vector %d"
1322 " did not return expected error %d\n", k
, retv
));
1340 #ifndef BCMSMS4_TEST_EMBED
1341 fail
+= sms4_test_enc_dec();
1342 fail
+= sms4_test_cbc_mac();
1343 fail
+= sms4_test_ofb_crypt();
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
);
1358 #ifdef BCMSMS4_TEST_STANDALONE
1360 main(int argc
, char **argv
)
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");
1371 #endif /* BCMSMS4_TEST_STANDALONE */
1373 #endif /* BCMSMS4_TEST */
1375 #endif /* BCMWAPI_WPI */