[contrib] Allow Network Protocol header to display in rom-o-matic
[gpxe.git] / src / net / 80211 / wpa_tkip.c
blob0cb697fa5401d2355206efe2980e9d7592295401
1 /*
2 * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER );
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>
32 /** @file
34 * Backend for WPA using the TKIP encryption standard.
37 /** Context for one direction of TKIP, either encryption or decryption */
38 struct tkip_dir_ctx
40 /** High 32 bits of last sequence counter value used */
41 u32 tsc_hi;
43 /** Low 32 bits of last sequence counter value used */
44 u16 tsc_lo;
46 /** MAC address used to derive TTAK */
47 u8 mac[ETH_ALEN];
49 /** If TRUE, TTAK is valid */
50 u16 ttak_ok;
52 /** TKIP-mixed transmit address and key, depends on tsc_hi and MAC */
53 u16 ttak[5];
56 /** Context for TKIP encryption and decryption */
57 struct tkip_ctx
59 /** Temporal key to use */
60 struct tkip_tk tk;
62 /** State for encryption */
63 struct tkip_dir_ctx enc;
65 /** State for decryption */
66 struct tkip_dir_ctx dec;
69 /** Header structure at the beginning of TKIP frame data */
70 struct tkip_head
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 ));
80 /** TKIP header overhead (IV + KID + ExtIV) */
81 #define TKIP_HEAD_LEN 8
83 /** TKIP trailer overhead (MIC + ICV) [assumes unfragmented] */
84 #define TKIP_FOOT_LEN 12
86 /** TKIP MIC length */
87 #define TKIP_MIC_LEN 8
89 /** TKIP ICV length */
90 #define TKIP_ICV_LEN 4
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,
130 * Perform S-box mapping on a 16-bit value
132 * @v v Value to perform S-box mapping on
133 * @ret Sv S-box mapped value
135 static inline u16 S ( u16 v )
137 return Sbox[v & 0xFF] ^ swap16 ( Sbox[v >> 8] );
141 * Rotate 16-bit value right
143 * @v v Value to rotate
144 * @v bits Number of bits to rotate by
145 * @ret rotv Rotated value
147 static inline u16 ror16 ( u16 v, int bits )
149 return ( v >> bits ) | ( v << ( 16 - bits ) );
153 * Rotate 32-bit value right
155 * @v v Value to rotate
156 * @v bits Number of bits to rotate by
157 * @ret rotv Rotated value
159 static inline u32 ror32 ( u32 v, int bits )
161 return ( v >> bits ) | ( v << ( 32 - bits ) );
165 * Rotate 32-bit value left
167 * @v v Value to rotate
168 * @v bits Number of bits to rotate by
169 * @ret rotv Rotated value
171 static inline u32 rol32 ( u32 v, int bits )
173 return ( v << bits ) | ( v >> ( 32 - bits ) );
178 * Initialise TKIP state and install key
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
185 static int tkip_init ( struct net80211_crypto *crypto, const void *key,
186 int keylen, const void *rsc )
188 struct tkip_ctx *ctx = crypto->priv;
189 const u8 *rscb = rsc;
191 if ( keylen != sizeof ( ctx->tk ) )
192 return -EINVAL;
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] );
200 memcpy ( &ctx->tk, key, sizeof ( ctx->tk ) );
202 return 0;
206 * Perform TKIP key mixing, phase 1
208 * @v dctx TKIP directional context
209 * @v tk TKIP temporal key
210 * @v mac MAC address of transmitter
212 * This recomputes the TTAK in @a dctx if necessary, and sets
213 * @c dctx->ttak_ok.
215 static void tkip_mix_1 ( struct tkip_dir_ctx *dctx, struct tkip_tk *tk, u8 *mac )
217 int i, j;
219 if ( dctx->ttak_ok && ! memcmp ( mac, dctx->mac, ETH_ALEN ) )
220 return;
222 memcpy ( dctx->mac, mac, ETH_ALEN );
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];
230 for ( i = 0; i < 8; i++ ) {
231 j = 2 * ( i & 1 );
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;
245 dctx->ttak_ok = 1;
249 * Perform TKIP key mixing, phase 2
251 * @v dctx TKIP directional context
252 * @v tk TKIP temporal key
253 * @ret key ARC4 key, 16 bytes long
255 static void tkip_mix_2 ( struct tkip_dir_ctx *dctx, struct tkip_tk *tk,
256 void *key )
258 u8 *kb = key;
259 u16 ppk[6];
260 int i;
262 memcpy ( ppk, dctx->ttak, sizeof ( dctx->ttak ) );
263 ppk[5] = dctx->ttak[4] + dctx->tsc_lo;
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] ) );
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 );
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;
285 for ( i = 0; i < 6; i++ ) {
286 kb[4 + 2*i] = ppk[i] & 0xFF;
287 kb[5 + 2*i] = ppk[i] >> 8;
292 * Update Michael message integrity code based on next 32-bit word of data
294 * @v V Michael code state (two 32-bit words)
295 * @v word Next 32-bit word of data
297 static void tkip_feed_michael ( u32 *V, u32 word )
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];
311 * Calculate Michael message integrity code
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)
320 static void tkip_michael ( const void *key, const void *da, const void *sa,
321 const void *data, size_t len, void *mic )
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;
332 memcpy ( V, key, sizeof ( V ) );
333 V[0] = le32_to_cpu ( V[0] );
334 V[1] = le32_to_cpu ( V[1] );
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 );
344 /* Feed in data */
345 while ( ptr + 4 <= end ) {
346 tkip_feed_michael ( V, le32_to_cpu ( *( u32 * ) ptr ) );
347 ptr += 4;
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;
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] ) );
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 ) );
368 * Encrypt a packet using TKIP
370 * @v crypto TKIP cryptosystem
371 * @v iob I/O buffer containing cleartext packet
372 * @ret eiob I/O buffer containing encrypted packet
374 static struct io_buffer * tkip_encrypt ( struct net80211_crypto *crypto,
375 struct io_buffer *iob )
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;
388 ctx->enc.tsc_lo++;
389 if ( ctx->enc.tsc_lo == 0 ) {
390 ctx->enc.tsc_hi++;
391 ctx->enc.ttak_ok = 0;
394 tkip_mix_1 ( &ctx->enc, &ctx->tk, hdr->addr2 );
395 tkip_mix_2 ( &ctx->enc, &ctx->tk, key );
397 eiob = alloc_iob ( iob_len ( iob ) + TKIP_HEAD_LEN + TKIP_FOOT_LEN );
398 if ( ! eiob )
399 return NULL;
401 /* Copy frame header */
402 memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
403 hdr = eiob->data;
404 hdr->fc |= IEEE80211_FC_PROTECTED;
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 ) );
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 );
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 ) );
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 );
431 DBGC2 ( ctx, "WPA-TKIP %p: encrypted packet %p -> %p\n", ctx,
432 iob, eiob );
434 return eiob;
438 * Decrypt a packet using TKIP
440 * @v crypto TKIP cryptosystem
441 * @v eiob I/O buffer containing encrypted packet
442 * @ret iob I/O buffer containing cleartext packet
444 static struct io_buffer * tkip_decrypt ( struct net80211_crypto *crypto,
445 struct io_buffer *eiob )
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;
459 iob = alloc_iob ( hdrlen + datalen + TKIP_FOOT_LEN );
460 if ( ! iob )
461 return NULL;
463 /* Copy frame header */
464 memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
465 hdr = iob->data;
466 hdr->fc &= ~IEEE80211_FC_PROTECTED;
468 /* Check and update TSC */
469 head = eiob->data + hdrlen;
470 rx_tsc_lo = ( head->tsc1 << 8 ) | head->tsc0;
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;
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;
487 /* Calculate key */
488 tkip_mix_1 ( &ctx->dec, &ctx->tk, hdr->addr2 );
489 tkip_mix_2 ( &ctx->dec, &ctx->tk, key );
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 );
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;
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;
517 DBGC2 ( ctx, "WPA-TKIP %p: decrypted packet %p -> %p\n", ctx,
518 eiob, iob );
520 return iob;
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 ),
536 * Calculate HMAC-MD5 MIC for EAPOL-Key frame
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
543 static void tkip_kie_mic ( const void *kck, const void *msg, size_t len,
544 void *mic )
546 struct md5_ctx md5;
547 u8 kckb[16];
548 size_t kck_len = 16;
550 memcpy ( kckb, kck, kck_len );
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 );
558 * Decrypt key data in EAPOL-Key frame
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
568 static int tkip_kie_decrypt ( const void *kek, const void *iv,
569 void *msg, u16 *len )
571 u8 key[32];
572 memcpy ( key, iv, 16 );
573 memcpy ( key + 16, kek, 16 );
575 arc4_skip ( key, 32, 256, msg, msg, *len );
577 return 0;
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,