1 | /* |
---|
2 | * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. |
---|
3 | * |
---|
4 | * This program is free software; you can redistribute it and/or |
---|
5 | * modify it under the terms of the GNU General Public License as |
---|
6 | * published by the Free Software Foundation; either version 2 of the |
---|
7 | * License, or any later version. |
---|
8 | * |
---|
9 | * This program is distributed in the hope that it will be useful, but |
---|
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
12 | * General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU General Public License |
---|
15 | * along with this program; if not, write to the Free Software |
---|
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
17 | */ |
---|
18 | |
---|
19 | FILE_LICENCE ( GPL2_OR_LATER ); |
---|
20 | |
---|
21 | #include <gpxe/net80211.h> |
---|
22 | #include <gpxe/crypto.h> |
---|
23 | #include <gpxe/hmac.h> |
---|
24 | #include <gpxe/sha1.h> |
---|
25 | #include <gpxe/md5.h> |
---|
26 | #include <gpxe/crc32.h> |
---|
27 | #include <gpxe/arc4.h> |
---|
28 | #include <gpxe/wpa.h> |
---|
29 | #include <byteswap.h> |
---|
30 | #include <errno.h> |
---|
31 | |
---|
32 | /** @file |
---|
33 | * |
---|
34 | * Backend for WPA using the TKIP encryption standard. |
---|
35 | */ |
---|
36 | |
---|
37 | /** Context for one direction of TKIP, either encryption or decryption */ |
---|
38 | struct tkip_dir_ctx |
---|
39 | { |
---|
40 | /** High 32 bits of last sequence counter value used */ |
---|
41 | u32 tsc_hi; |
---|
42 | |
---|
43 | /** Low 32 bits of last sequence counter value used */ |
---|
44 | u16 tsc_lo; |
---|
45 | |
---|
46 | /** MAC address used to derive TTAK */ |
---|
47 | u8 mac[ETH_ALEN]; |
---|
48 | |
---|
49 | /** If TRUE, TTAK is valid */ |
---|
50 | u16 ttak_ok; |
---|
51 | |
---|
52 | /** TKIP-mixed transmit address and key, depends on tsc_hi and MAC */ |
---|
53 | u16 ttak[5]; |
---|
54 | }; |
---|
55 | |
---|
56 | /** Context for TKIP encryption and decryption */ |
---|
57 | struct tkip_ctx |
---|
58 | { |
---|
59 | /** Temporal key to use */ |
---|
60 | struct tkip_tk tk; |
---|
61 | |
---|
62 | /** State for encryption */ |
---|
63 | struct tkip_dir_ctx enc; |
---|
64 | |
---|
65 | /** State for decryption */ |
---|
66 | struct tkip_dir_ctx dec; |
---|
67 | }; |
---|
68 | |
---|
69 | /** Header structure at the beginning of TKIP frame data */ |
---|
70 | struct tkip_head |
---|
71 | { |
---|
72 | u8 tsc1; /**< High byte of low 16 bits of TSC */ |
---|
73 | u8 seed1; /**< Second byte of WEP seed */ |
---|
74 | u8 tsc0; /**< Low byte of TSC */ |
---|
75 | u8 kid; /**< Key ID and ExtIV byte */ |
---|
76 | u32 tsc_hi; /**< High 32 bits of TSC, as an ExtIV */ |
---|
77 | } __attribute__ (( packed )); |
---|
78 | |
---|
79 | |
---|
80 | /** TKIP header overhead (IV + KID + ExtIV) */ |
---|
81 | #define TKIP_HEAD_LEN 8 |
---|
82 | |
---|
83 | /** TKIP trailer overhead (MIC + ICV) [assumes unfragmented] */ |
---|
84 | #define TKIP_FOOT_LEN 12 |
---|
85 | |
---|
86 | /** TKIP MIC length */ |
---|
87 | #define TKIP_MIC_LEN 8 |
---|
88 | |
---|
89 | /** TKIP ICV length */ |
---|
90 | #define TKIP_ICV_LEN 4 |
---|
91 | |
---|
92 | |
---|
93 | /** TKIP S-box */ |
---|
94 | static const u16 Sbox[256] = { |
---|
95 | 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, |
---|
96 | 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, |
---|
97 | 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, |
---|
98 | 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, |
---|
99 | 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, |
---|
100 | 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, |
---|
101 | 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, |
---|
102 | 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, |
---|
103 | 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, |
---|
104 | 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, |
---|
105 | 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, |
---|
106 | 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, |
---|
107 | 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, |
---|
108 | 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, |
---|
109 | 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, |
---|
110 | 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, |
---|
111 | 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, |
---|
112 | 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, |
---|
113 | 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, |
---|
114 | 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, |
---|
115 | 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, |
---|
116 | 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, |
---|
117 | 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, |
---|
118 | 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, |
---|
119 | 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, |
---|
120 | 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, |
---|
121 | 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, |
---|
122 | 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, |
---|
123 | 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, |
---|
124 | 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, |
---|
125 | 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, |
---|
126 | 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, |
---|
127 | }; |
---|
128 | |
---|
129 | /** |
---|
130 | * Perform S-box mapping on a 16-bit value |
---|
131 | * |
---|
132 | * @v v Value to perform S-box mapping on |
---|
133 | * @ret Sv S-box mapped value |
---|
134 | */ |
---|
135 | static inline u16 S ( u16 v ) |
---|
136 | { |
---|
137 | return Sbox[v & 0xFF] ^ swap16 ( Sbox[v >> 8] ); |
---|
138 | } |
---|
139 | |
---|
140 | /** |
---|
141 | * Rotate 16-bit value right |
---|
142 | * |
---|
143 | * @v v Value to rotate |
---|
144 | * @v bits Number of bits to rotate by |
---|
145 | * @ret rotv Rotated value |
---|
146 | */ |
---|
147 | static inline u16 ror16 ( u16 v, int bits ) |
---|
148 | { |
---|
149 | return ( v >> bits ) | ( v << ( 16 - bits ) ); |
---|
150 | } |
---|
151 | |
---|
152 | /** |
---|
153 | * Rotate 32-bit value right |
---|
154 | * |
---|
155 | * @v v Value to rotate |
---|
156 | * @v bits Number of bits to rotate by |
---|
157 | * @ret rotv Rotated value |
---|
158 | */ |
---|
159 | static inline u32 ror32 ( u32 v, int bits ) |
---|
160 | { |
---|
161 | return ( v >> bits ) | ( v << ( 32 - bits ) ); |
---|
162 | } |
---|
163 | |
---|
164 | /** |
---|
165 | * Rotate 32-bit value left |
---|
166 | * |
---|
167 | * @v v Value to rotate |
---|
168 | * @v bits Number of bits to rotate by |
---|
169 | * @ret rotv Rotated value |
---|
170 | */ |
---|
171 | static inline u32 rol32 ( u32 v, int bits ) |
---|
172 | { |
---|
173 | return ( v << bits ) | ( v >> ( 32 - bits ) ); |
---|
174 | } |
---|
175 | |
---|
176 | |
---|
177 | /** |
---|
178 | * Initialise TKIP state and install key |
---|
179 | * |
---|
180 | * @v crypto TKIP cryptosystem structure |
---|
181 | * @v key Pointer to tkip_tk to install |
---|
182 | * @v keylen Length of key (32 bytes) |
---|
183 | * @v rsc Initial receive sequence counter |
---|
184 | */ |
---|
185 | static int tkip_init ( struct net80211_crypto *crypto, const void *key, |
---|
186 | int keylen, const void *rsc ) |
---|
187 | { |
---|
188 | struct tkip_ctx *ctx = crypto->priv; |
---|
189 | const u8 *rscb = rsc; |
---|
190 | |
---|
191 | if ( keylen != sizeof ( ctx->tk ) ) |
---|
192 | return -EINVAL; |
---|
193 | |
---|
194 | if ( rscb ) { |
---|
195 | ctx->dec.tsc_lo = ( rscb[1] << 8 ) | rscb[0]; |
---|
196 | ctx->dec.tsc_hi = ( ( rscb[5] << 24 ) | ( rscb[4] << 16 ) | |
---|
197 | ( rscb[3] << 8 ) | rscb[2] ); |
---|
198 | } |
---|
199 | |
---|
200 | memcpy ( &ctx->tk, key, sizeof ( ctx->tk ) ); |
---|
201 | |
---|
202 | return 0; |
---|
203 | } |
---|
204 | |
---|
205 | /** |
---|
206 | * Perform TKIP key mixing, phase 1 |
---|
207 | * |
---|
208 | * @v dctx TKIP directional context |
---|
209 | * @v tk TKIP temporal key |
---|
210 | * @v mac MAC address of transmitter |
---|
211 | * |
---|
212 | * This recomputes the TTAK in @a dctx if necessary, and sets |
---|
213 | * @c dctx->ttak_ok. |
---|
214 | */ |
---|
215 | static void tkip_mix_1 ( struct tkip_dir_ctx *dctx, struct tkip_tk *tk, u8 *mac ) |
---|
216 | { |
---|
217 | int i, j; |
---|
218 | |
---|
219 | if ( dctx->ttak_ok && ! memcmp ( mac, dctx->mac, ETH_ALEN ) ) |
---|
220 | return; |
---|
221 | |
---|
222 | memcpy ( dctx->mac, mac, ETH_ALEN ); |
---|
223 | |
---|
224 | dctx->ttak[0] = dctx->tsc_hi & 0xFFFF; |
---|
225 | dctx->ttak[1] = dctx->tsc_hi >> 16; |
---|
226 | dctx->ttak[2] = ( mac[1] << 8 ) | mac[0]; |
---|
227 | dctx->ttak[3] = ( mac[3] << 8 ) | mac[2]; |
---|
228 | dctx->ttak[4] = ( mac[5] << 8 ) | mac[4]; |
---|
229 | |
---|
230 | for ( i = 0; i < 8; i++ ) { |
---|
231 | j = 2 * ( i & 1 ); |
---|
232 | |
---|
233 | dctx->ttak[0] += S ( dctx->ttak[4] ^ ( ( tk->key[1 + j] << 8 ) | |
---|
234 | tk->key[0 + j] ) ); |
---|
235 | dctx->ttak[1] += S ( dctx->ttak[0] ^ ( ( tk->key[5 + j] << 8 ) | |
---|
236 | tk->key[4 + j] ) ); |
---|
237 | dctx->ttak[2] += S ( dctx->ttak[1] ^ ( ( tk->key[9 + j] << 8 ) | |
---|
238 | tk->key[8 + j] ) ); |
---|
239 | dctx->ttak[3] += S ( dctx->ttak[2] ^ ( ( tk->key[13+ j] << 8 ) | |
---|
240 | tk->key[12+ j] ) ); |
---|
241 | dctx->ttak[4] += S ( dctx->ttak[3] ^ ( ( tk->key[1 + j] << 8 ) | |
---|
242 | tk->key[0 + j] ) ) + i; |
---|
243 | } |
---|
244 | |
---|
245 | dctx->ttak_ok = 1; |
---|
246 | } |
---|
247 | |
---|
248 | /** |
---|
249 | * Perform TKIP key mixing, phase 2 |
---|
250 | * |
---|
251 | * @v dctx TKIP directional context |
---|
252 | * @v tk TKIP temporal key |
---|
253 | * @ret key ARC4 key, 16 bytes long |
---|
254 | */ |
---|
255 | static void tkip_mix_2 ( struct tkip_dir_ctx *dctx, struct tkip_tk *tk, |
---|
256 | void *key ) |
---|
257 | { |
---|
258 | u8 *kb = key; |
---|
259 | u16 ppk[6]; |
---|
260 | int i; |
---|
261 | |
---|
262 | memcpy ( ppk, dctx->ttak, sizeof ( dctx->ttak ) ); |
---|
263 | ppk[5] = dctx->ttak[4] + dctx->tsc_lo; |
---|
264 | |
---|
265 | ppk[0] += S ( ppk[5] ^ ( ( tk->key[1] << 8 ) | tk->key[0] ) ); |
---|
266 | ppk[1] += S ( ppk[0] ^ ( ( tk->key[3] << 8 ) | tk->key[2] ) ); |
---|
267 | ppk[2] += S ( ppk[1] ^ ( ( tk->key[5] << 8 ) | tk->key[4] ) ); |
---|
268 | ppk[3] += S ( ppk[2] ^ ( ( tk->key[7] << 8 ) | tk->key[6] ) ); |
---|
269 | ppk[4] += S ( ppk[3] ^ ( ( tk->key[9] << 8 ) | tk->key[8] ) ); |
---|
270 | ppk[5] += S ( ppk[4] ^ ( ( tk->key[11] << 8 ) | tk->key[10] ) ); |
---|
271 | |
---|
272 | ppk[0] += ror16 ( ppk[5] ^ ( ( tk->key[13] << 8 ) | tk->key[12] ), 1 ); |
---|
273 | ppk[1] += ror16 ( ppk[0] ^ ( ( tk->key[15] << 8 ) | tk->key[14] ), 1 ); |
---|
274 | ppk[2] += ror16 ( ppk[1], 1 ); |
---|
275 | ppk[3] += ror16 ( ppk[2], 1 ); |
---|
276 | ppk[4] += ror16 ( ppk[3], 1 ); |
---|
277 | ppk[5] += ror16 ( ppk[4], 1 ); |
---|
278 | |
---|
279 | kb[0] = dctx->tsc_lo >> 8; |
---|
280 | kb[1] = ( ( dctx->tsc_lo >> 8 ) | 0x20 ) & 0x7F; |
---|
281 | kb[2] = dctx->tsc_lo & 0xFF; |
---|
282 | kb[3] = ( ( ppk[5] ^ ( ( tk->key[1] << 8 ) | tk->key[0] ) ) >> 1 ) |
---|
283 | & 0xFF; |
---|
284 | |
---|
285 | for ( i = 0; i < 6; i++ ) { |
---|
286 | kb[4 + 2*i] = ppk[i] & 0xFF; |
---|
287 | kb[5 + 2*i] = ppk[i] >> 8; |
---|
288 | } |
---|
289 | } |
---|
290 | |
---|
291 | /** |
---|
292 | * Update Michael message integrity code based on next 32-bit word of data |
---|
293 | * |
---|
294 | * @v V Michael code state (two 32-bit words) |
---|
295 | * @v word Next 32-bit word of data |
---|
296 | */ |
---|
297 | static void tkip_feed_michael ( u32 *V, u32 word ) |
---|
298 | { |
---|
299 | V[0] ^= word; |
---|
300 | V[1] ^= rol32 ( V[0], 17 ); |
---|
301 | V[0] += V[1]; |
---|
302 | V[1] ^= ( ( V[0] & 0xFF00FF00 ) >> 8 ) | ( ( V[0] & 0x00FF00FF ) << 8 ); |
---|
303 | V[0] += V[1]; |
---|
304 | V[1] ^= rol32 ( V[0], 3 ); |
---|
305 | V[0] += V[1]; |
---|
306 | V[1] ^= ror32 ( V[0], 2 ); |
---|
307 | V[0] += V[1]; |
---|
308 | } |
---|
309 | |
---|
310 | /** |
---|
311 | * Calculate Michael message integrity code |
---|
312 | * |
---|
313 | * @v key MIC key to use (8 bytes) |
---|
314 | * @v da Destination link-layer address |
---|
315 | * @v sa Source link-layer address |
---|
316 | * @v data Start of data to calculate over |
---|
317 | * @v len Length of header + data |
---|
318 | * @ret mic Calculated Michael MIC (8 bytes) |
---|
319 | */ |
---|
320 | static void tkip_michael ( const void *key, const void *da, const void *sa, |
---|
321 | const void *data, size_t len, void *mic ) |
---|
322 | { |
---|
323 | u32 V[2]; /* V[0] = "l", V[1] = "r" in 802.11 */ |
---|
324 | union { |
---|
325 | u8 byte[12]; |
---|
326 | u32 word[3]; |
---|
327 | } cap; |
---|
328 | const u8 *ptr = data; |
---|
329 | const u8 *end = ptr + len; |
---|
330 | int i; |
---|
331 | |
---|
332 | memcpy ( V, key, sizeof ( V ) ); |
---|
333 | V[0] = le32_to_cpu ( V[0] ); |
---|
334 | V[1] = le32_to_cpu ( V[1] ); |
---|
335 | |
---|
336 | /* Feed in header (we assume non-QoS, so Priority = 0) */ |
---|
337 | memcpy ( &cap.byte[0], da, ETH_ALEN ); |
---|
338 | memcpy ( &cap.byte[6], sa, ETH_ALEN ); |
---|
339 | tkip_feed_michael ( V, le32_to_cpu ( cap.word[0] ) ); |
---|
340 | tkip_feed_michael ( V, le32_to_cpu ( cap.word[1] ) ); |
---|
341 | tkip_feed_michael ( V, le32_to_cpu ( cap.word[2] ) ); |
---|
342 | tkip_feed_michael ( V, 0 ); |
---|
343 | |
---|
344 | /* Feed in data */ |
---|
345 | while ( ptr + 4 <= end ) { |
---|
346 | tkip_feed_michael ( V, le32_to_cpu ( *( u32 * ) ptr ) ); |
---|
347 | ptr += 4; |
---|
348 | } |
---|
349 | |
---|
350 | /* Add unaligned part and padding */ |
---|
351 | for ( i = 0; ptr < end; i++ ) |
---|
352 | cap.byte[i] = *ptr++; |
---|
353 | cap.byte[i++] = 0x5a; |
---|
354 | for ( ; i < 8; i++ ) |
---|
355 | cap.byte[i] = 0; |
---|
356 | |
---|
357 | /* Feed in padding */ |
---|
358 | tkip_feed_michael ( V, le32_to_cpu ( cap.word[0] ) ); |
---|
359 | tkip_feed_michael ( V, le32_to_cpu ( cap.word[1] ) ); |
---|
360 | |
---|
361 | /* Output MIC */ |
---|
362 | V[0] = cpu_to_le32 ( V[0] ); |
---|
363 | V[1] = cpu_to_le32 ( V[1] ); |
---|
364 | memcpy ( mic, V, sizeof ( V ) ); |
---|
365 | } |
---|
366 | |
---|
367 | /** |
---|
368 | * Encrypt a packet using TKIP |
---|
369 | * |
---|
370 | * @v crypto TKIP cryptosystem |
---|
371 | * @v iob I/O buffer containing cleartext packet |
---|
372 | * @ret eiob I/O buffer containing encrypted packet |
---|
373 | */ |
---|
374 | static struct io_buffer * tkip_encrypt ( struct net80211_crypto *crypto, |
---|
375 | struct io_buffer *iob ) |
---|
376 | { |
---|
377 | struct tkip_ctx *ctx = crypto->priv; |
---|
378 | struct ieee80211_frame *hdr = iob->data; |
---|
379 | struct io_buffer *eiob; |
---|
380 | struct arc4_ctx arc4; |
---|
381 | u8 key[16]; |
---|
382 | struct tkip_head head; |
---|
383 | u8 mic[8]; |
---|
384 | u32 icv; |
---|
385 | const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN; |
---|
386 | int datalen = iob_len ( iob ) - hdrlen; |
---|
387 | |
---|
388 | ctx->enc.tsc_lo++; |
---|
389 | if ( ctx->enc.tsc_lo == 0 ) { |
---|
390 | ctx->enc.tsc_hi++; |
---|
391 | ctx->enc.ttak_ok = 0; |
---|
392 | } |
---|
393 | |
---|
394 | tkip_mix_1 ( &ctx->enc, &ctx->tk, hdr->addr2 ); |
---|
395 | tkip_mix_2 ( &ctx->enc, &ctx->tk, key ); |
---|
396 | |
---|
397 | eiob = alloc_iob ( iob_len ( iob ) + TKIP_HEAD_LEN + TKIP_FOOT_LEN ); |
---|
398 | if ( ! eiob ) |
---|
399 | return NULL; |
---|
400 | |
---|
401 | /* Copy frame header */ |
---|
402 | memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen ); |
---|
403 | hdr = eiob->data; |
---|
404 | hdr->fc |= IEEE80211_FC_PROTECTED; |
---|
405 | |
---|
406 | /* Fill in IV and key ID byte, and extended IV */ |
---|
407 | memcpy ( &head, key, 3 ); |
---|
408 | head.kid = 0x20; /* have Extended IV, key ID 0 */ |
---|
409 | head.tsc_hi = cpu_to_le32 ( ctx->enc.tsc_hi ); |
---|
410 | memcpy ( iob_put ( eiob, sizeof ( head ) ), &head, sizeof ( head ) ); |
---|
411 | |
---|
412 | /* Copy and encrypt the data */ |
---|
413 | cipher_setkey ( &arc4_algorithm, &arc4, key, 16 ); |
---|
414 | cipher_encrypt ( &arc4_algorithm, &arc4, iob->data + hdrlen, |
---|
415 | iob_put ( eiob, datalen ), datalen ); |
---|
416 | |
---|
417 | /* Add MIC */ |
---|
418 | hdr = iob->data; |
---|
419 | tkip_michael ( &ctx->tk.mic.tx, hdr->addr3, hdr->addr2, |
---|
420 | iob->data + hdrlen, datalen, mic ); |
---|
421 | cipher_encrypt ( &arc4_algorithm, &arc4, mic, |
---|
422 | iob_put ( eiob, sizeof ( mic ) ), sizeof ( mic ) ); |
---|
423 | |
---|
424 | /* Add ICV */ |
---|
425 | icv = crc32_le ( ~0, iob->data + hdrlen, datalen ); |
---|
426 | icv = crc32_le ( icv, mic, sizeof ( mic ) ); |
---|
427 | icv = cpu_to_le32 ( ~icv ); |
---|
428 | cipher_encrypt ( &arc4_algorithm, &arc4, &icv, |
---|
429 | iob_put ( eiob, TKIP_ICV_LEN ), TKIP_ICV_LEN ); |
---|
430 | |
---|
431 | DBGC2 ( ctx, "WPA-TKIP %p: encrypted packet %p -> %p\n", ctx, |
---|
432 | iob, eiob ); |
---|
433 | |
---|
434 | return eiob; |
---|
435 | } |
---|
436 | |
---|
437 | /** |
---|
438 | * Decrypt a packet using TKIP |
---|
439 | * |
---|
440 | * @v crypto TKIP cryptosystem |
---|
441 | * @v eiob I/O buffer containing encrypted packet |
---|
442 | * @ret iob I/O buffer containing cleartext packet |
---|
443 | */ |
---|
444 | static struct io_buffer * tkip_decrypt ( struct net80211_crypto *crypto, |
---|
445 | struct io_buffer *eiob ) |
---|
446 | { |
---|
447 | struct tkip_ctx *ctx = crypto->priv; |
---|
448 | struct ieee80211_frame *hdr; |
---|
449 | struct io_buffer *iob; |
---|
450 | const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN; |
---|
451 | int datalen = iob_len ( eiob ) - hdrlen - TKIP_HEAD_LEN - TKIP_FOOT_LEN; |
---|
452 | struct tkip_head *head; |
---|
453 | struct arc4_ctx arc4; |
---|
454 | u16 rx_tsc_lo; |
---|
455 | u8 key[16]; |
---|
456 | u8 mic[8]; |
---|
457 | u32 icv, crc; |
---|
458 | |
---|
459 | iob = alloc_iob ( hdrlen + datalen + TKIP_FOOT_LEN ); |
---|
460 | if ( ! iob ) |
---|
461 | return NULL; |
---|
462 | |
---|
463 | /* Copy frame header */ |
---|
464 | memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen ); |
---|
465 | hdr = iob->data; |
---|
466 | hdr->fc &= ~IEEE80211_FC_PROTECTED; |
---|
467 | |
---|
468 | /* Check and update TSC */ |
---|
469 | head = eiob->data + hdrlen; |
---|
470 | rx_tsc_lo = ( head->tsc1 << 8 ) | head->tsc0; |
---|
471 | |
---|
472 | if ( head->tsc_hi < ctx->dec.tsc_hi || |
---|
473 | ( head->tsc_hi == ctx->dec.tsc_hi && |
---|
474 | rx_tsc_lo <= ctx->dec.tsc_lo ) ) { |
---|
475 | DBGC ( ctx, "WPA-TKIP %p: packet received out of order " |
---|
476 | "(%08x:%04x <= %08x:%04x)\n", ctx, head->tsc_hi, |
---|
477 | rx_tsc_lo, ctx->dec.tsc_hi, ctx->dec.tsc_lo ); |
---|
478 | free_iob ( iob ); |
---|
479 | return NULL; |
---|
480 | } |
---|
481 | ctx->dec.tsc_lo = rx_tsc_lo; |
---|
482 | if ( ctx->dec.tsc_hi != head->tsc_hi ) { |
---|
483 | ctx->dec.ttak_ok = 0; |
---|
484 | ctx->dec.tsc_hi = head->tsc_hi; |
---|
485 | } |
---|
486 | |
---|
487 | /* Calculate key */ |
---|
488 | tkip_mix_1 ( &ctx->dec, &ctx->tk, hdr->addr2 ); |
---|
489 | tkip_mix_2 ( &ctx->dec, &ctx->tk, key ); |
---|
490 | |
---|
491 | /* Copy-decrypt data, MIC, ICV */ |
---|
492 | cipher_setkey ( &arc4_algorithm, &arc4, key, 16 ); |
---|
493 | cipher_decrypt ( &arc4_algorithm, &arc4, |
---|
494 | eiob->data + hdrlen + TKIP_HEAD_LEN, |
---|
495 | iob_put ( iob, datalen ), datalen + TKIP_FOOT_LEN ); |
---|
496 | |
---|
497 | /* Check ICV */ |
---|
498 | icv = le32_to_cpu ( *( u32 * ) ( iob->tail + TKIP_MIC_LEN ) ); |
---|
499 | crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen + TKIP_MIC_LEN ); |
---|
500 | if ( crc != icv ) { |
---|
501 | DBGC ( ctx, "WPA-TKIP %p CRC mismatch: expect %08x, get %08x\n", |
---|
502 | ctx, icv, crc ); |
---|
503 | free_iob ( iob ); |
---|
504 | return NULL; |
---|
505 | } |
---|
506 | |
---|
507 | /* Check MIC */ |
---|
508 | tkip_michael ( &ctx->tk.mic.rx, hdr->addr1, hdr->addr3, |
---|
509 | iob->data + hdrlen, datalen, mic ); |
---|
510 | if ( memcmp ( mic, iob->tail, TKIP_MIC_LEN ) != 0 ) { |
---|
511 | DBGC ( ctx, "WPA-TKIP %p ALERT! MIC failure\n", ctx ); |
---|
512 | /* XXX we should do the countermeasures here */ |
---|
513 | free_iob ( iob ); |
---|
514 | return NULL; |
---|
515 | } |
---|
516 | |
---|
517 | DBGC2 ( ctx, "WPA-TKIP %p: decrypted packet %p -> %p\n", ctx, |
---|
518 | eiob, iob ); |
---|
519 | |
---|
520 | return iob; |
---|
521 | } |
---|
522 | |
---|
523 | /** TKIP cryptosystem */ |
---|
524 | struct net80211_crypto tkip_crypto __net80211_crypto = { |
---|
525 | .algorithm = NET80211_CRYPT_TKIP, |
---|
526 | .init = tkip_init, |
---|
527 | .encrypt = tkip_encrypt, |
---|
528 | .decrypt = tkip_decrypt, |
---|
529 | .priv_len = sizeof ( struct tkip_ctx ), |
---|
530 | }; |
---|
531 | |
---|
532 | |
---|
533 | |
---|
534 | |
---|
535 | /** |
---|
536 | * Calculate HMAC-MD5 MIC for EAPOL-Key frame |
---|
537 | * |
---|
538 | * @v kck Key Confirmation Key, 16 bytes |
---|
539 | * @v msg Message to calculate MIC over |
---|
540 | * @v len Number of bytes to calculate MIC over |
---|
541 | * @ret mic Calculated MIC, 16 bytes long |
---|
542 | */ |
---|
543 | static void tkip_kie_mic ( const void *kck, const void *msg, size_t len, |
---|
544 | void *mic ) |
---|
545 | { |
---|
546 | struct md5_ctx md5; |
---|
547 | u8 kckb[16]; |
---|
548 | size_t kck_len = 16; |
---|
549 | |
---|
550 | memcpy ( kckb, kck, kck_len ); |
---|
551 | |
---|
552 | hmac_init ( &md5_algorithm, &md5, kckb, &kck_len ); |
---|
553 | hmac_update ( &md5_algorithm, &md5, msg, len ); |
---|
554 | hmac_final ( &md5_algorithm, &md5, kckb, &kck_len, mic ); |
---|
555 | } |
---|
556 | |
---|
557 | /** |
---|
558 | * Decrypt key data in EAPOL-Key frame |
---|
559 | * |
---|
560 | * @v kek Key Encryption Key, 16 bytes |
---|
561 | * @v iv Initialisation vector, 16 bytes |
---|
562 | * @v msg Message to decrypt |
---|
563 | * @v len Length of message |
---|
564 | * @ret msg Decrypted message in place of original |
---|
565 | * @ret len Unchanged |
---|
566 | * @ret rc Always 0 for success |
---|
567 | */ |
---|
568 | static int tkip_kie_decrypt ( const void *kek, const void *iv, |
---|
569 | void *msg, u16 *len ) |
---|
570 | { |
---|
571 | u8 key[32]; |
---|
572 | memcpy ( key, iv, 16 ); |
---|
573 | memcpy ( key + 16, kek, 16 ); |
---|
574 | |
---|
575 | arc4_skip ( key, 32, 256, msg, msg, *len ); |
---|
576 | |
---|
577 | return 0; |
---|
578 | } |
---|
579 | |
---|
580 | |
---|
581 | /** TKIP-style key integrity and encryption handler */ |
---|
582 | struct wpa_kie tkip_kie __wpa_kie = { |
---|
583 | .version = EAPOL_KEY_VERSION_WPA, |
---|
584 | .mic = tkip_kie_mic, |
---|
585 | .decrypt = tkip_kie_decrypt, |
---|
586 | }; |
---|