blob: f0d1860e5b1b65570852361dec1f446c1f0f4d23 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -08002 * Copyright (c) 2012-2013 Qualcomm Atheros, Inc.
3 * All Rights Reserved.
4 * Qualcomm Atheros Confidential and Proprietary.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08005 */
6/*
Jeff Johnson295189b2012-06-20 16:38:30 -07007 * Woodside Networks, Inc proprietary. All rights reserved.
8 * File: $Header: //depot/software/projects/feature_branches/gen5_phase1/os/linux/classic/ap/apps/ssm/lib/aniSsmEapol.c#2 $
9 *
10 * Contains definitions of various utilities for EAPoL frame
11 * parsing and creation.
12 *
13 * Author: Mayank D. Upadhyay
14 * Date: 19-June-2002
15 * History:-
16 * Date Modified by Modification Information
17 * ------------------------------------------------------
18 *
19 */
20#include "vos_utils.h"
21#include <bapRsnAsfPacket.h>
22#include <bapRsnErrors.h>
23#include <bapRsnSsmEapol.h>
24#include "bapRsn8021xFsm.h"
25#include "vos_memory.h"
26
27//#include "aniSsmUtils.h"
28
Jeff Johnson295189b2012-06-20 16:38:30 -070029
30//TODO: Put these in an array after EAPOL_TYPE is made an enum
31#define ANI_EAPOL_TYPE_PACKET_STR "EAP"
32#define ANI_EAPOL_TYPE_START_STR "START"
33#define ANI_EAPOL_TYPE_LOGOFF_STR "LOGOFF"
34#define ANI_EAPOL_TYPE_KEY_STR "KEY"
35#define ANI_EAPOL_TYPE_ASF_ALERT_STR "ALERT"
36#define ANI_EAPOL_TYPE_UNKNOWN_STR "UNKNOWN"
37
38/**
39 * The EAPOL packet is structured as follows:
40 */
41#define DST_MAC_POS 0
42#define SRC_MAC_POS 6
43#define ETHER_PROTO_POS 12
44#define EAPOL_VERSION_POS 14
45#define ANI_EAPOL_TYPE_POS 15
46#define EAPOL_BODY_LEN_POS 16
47#define EAPOL_BODY_POS EAPOL_RX_HEADER_SIZE
48
49#define EAPOL_BODY_LEN_SIZE 2
50
Madan Mohan Koyyalamudia53c4dc2012-11-13 10:35:42 -080051#define ANI_SSM_LEGACY_RC4_KEY_SIGN_OFFSET (EAPOL_BODY_POS + 28)
Jeff Johnson295189b2012-06-20 16:38:30 -070052
53/**
54 * Bitmasks for the RSN Key Information field
55 */
56#define ANI_SSM_RSN_KEY_DESC_VERS_MASK 0x0007
57#define ANI_SSM_RSN_UNICAST_MASK 0x0008
58#define ANI_SSM_RSN_KEY_INDEX_MASK 0x0030
59#define ANI_SSM_RSN_INSTALL_MASK 0x0040
60#define ANI_SSM_RSN_ACK_MASK 0x0080
61#define ANI_SSM_RSN_MIC_MASK 0x0100
62#define ANI_SSM_RSN_SECURE_MASK 0x0200
63#define ANI_SSM_RSN_ERROR_MASK 0x0400
64#define ANI_SSM_RSN_REQUEST_MASK 0x0800
65#define ANI_SSM_RSN_ENC_KEY_DATA_MASK 0x1000
66
67#define ANI_SSM_RSN_KEY_DESC_VERS_OFFSET 0
68#define ANI_SSM_RSN_KEY_INDEX_OFFSET 4
69
Madan Mohan Koyyalamudia53c4dc2012-11-13 10:35:42 -080070#define ANI_SSM_RSN_KEY_MIC_OFFSET (EAPOL_BODY_POS + 77)
Jeff Johnson295189b2012-06-20 16:38:30 -070071
72/**
73 * Other hard coded values for convenience:
74 */
75static const v_U8_t
76ANI_ETH_P_EAPOL_BYTES[2] = {0x00, 0x03};//BT-AMP security type{0x88, 0x8e};
77static const v_U8_t
78EAPOL_VERSION_BYTES[1] = {EAPOL_VERSION_1};
79static const v_U8_t
80ANI_EAPOL_TYPE_PACKET_BYTES[1] = {ANI_EAPOL_TYPE_PACKET};
81static const v_U8_t
82ANI_EAPOL_TYPE_START_BYTES[1] = {ANI_EAPOL_TYPE_START};
83static const v_U8_t
84ANI_EAPOL_TYPE_LOGOFF_BYTES[1] = {ANI_EAPOL_TYPE_LOGOFF};
85static const v_U8_t
86ANI_EAPOL_TYPE_KEY_BYTES[1] = {ANI_EAPOL_TYPE_KEY};
87static const v_U8_t
88ANI_EAPOL_TYPE_ASF_ALERT_BYTES[1] = {ANI_EAPOL_TYPE_ASF_ALERT};
89static const v_U8_t
90ZERO_BYTES[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
91static v_U8_t BAP_RSN_LLC_HEADER[] = {0xAA, 0xAA, 0x03, 0x00, 0x19, 0x58 };
92
93
94
95static int
96parseRsnKeyDesc(tAniPacket *packet,
97 tAniEapolRsnKeyDesc **rsnDescPtr);
98
99static int
100parseRsnKeyInfo(tAniPacket *packet,
101 tAniRsnKeyInfo *info);
102
103static int
104writeRsnKeyDesc(tAniPacket *packet,
105 tAniEapolRsnKeyDesc *rsnDesc,
106 v_U8_t keyDescType);
107
108static int
109writeRsnKeyInfo(tAniPacket *packet, tAniRsnKeyInfo *info);
110
111static int
112writeRsnKeyMic(v_U32_t cryptHandle,
113 tAniPacket *eapolFrame,
114 tAniEapolRsnKeyDesc *rsnDesc,
115 v_U8_t *micKey,
116 v_U32_t micKeyLen);
117
118static int
119checkRsnKeyMic(v_U32_t cryptHandle,
120 tAniPacket *eapolFrame,
121 tAniEapolRsnKeyDesc *rsnDesc,
122 v_U8_t *micKey,
123 v_U32_t micKeyLen);
124
125extern void authEapolHandler( tAuthRsnFsm *fsm, tAniPacket *eapolFrame,
126 tAniMacAddr dstMac,
127 tAniMacAddr srcMac,
128 v_U8_t *type);
129extern void suppEapolHandler( tSuppRsnFsm *fsm, tAniPacket *eapolFrame,
130 tAniMacAddr dstMac,
131 tAniMacAddr srcMac,
132 v_U8_t *type);
133
134/**
135 * addEapolHeaders
136 *
137 * FUNCTION:
138 * Prepends the EAPOL header to a packet.
139 *
140 * ASSUMPTIONS:
141 * The packet has enough space available for prepending the EAPOL
142 * header.
143 *
144 * @param packet the packet to prepend to
145 * @param dstMac the MAC address of the destination (authenticator)
146 * @param srcMac the MAC address of the source (supplicant)
147 * @param eapolType the EAPOL-Type field
148 *
149 * @return ANI_OK if the operation succeeds
150 */
151static int
152addEapolHeaders(tAniPacket *packet,
153 tAniMacAddr dstMac,
154 tAniMacAddr srcMac,
155 v_U8_t eapolType)
156{
157 int retVal;
158 v_U16_t len;
159
160 do
161 {
162 retVal = aniAsfPacketGetLen(packet);
163 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
164
165 len = retVal;
166 retVal = aniAsfPacketPrepend16(packet, len);
167
168 retVal = aniAsfPacketPrepend8(packet, eapolType);
169 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
170
171 retVal = aniAsfPacketPrependBuffer(packet, EAPOL_VERSION_BYTES, 1);
172 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
173
174 retVal = aniAsfPacketPrependBuffer(packet, ANI_ETH_P_EAPOL_BYTES, 2);
175 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
176
177 //Since TL expects SNAP header in all packets we send, put it in
178 retVal = aniAsfPacketPrependBuffer(packet, BAP_RSN_LLC_HEADER, sizeof(BAP_RSN_LLC_HEADER));
179 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
180
181 //packet length
182 len += 6/*length + eapolType+version + eth_type*/ + sizeof(BAP_RSN_LLC_HEADER);
183 retVal = aniAsfPacketPrepend16(packet, len);
184 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
185
186 retVal = aniAsfPacketPrependBuffer(packet, srcMac, sizeof(tAniMacAddr));
187 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
188
189 retVal = aniAsfPacketPrependBuffer(packet, dstMac, sizeof(tAniMacAddr));
190 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
191 }while( 0 );
192
193 return retVal;
194}
195
196/**
197 * aniEapolWriteStart
198 *
199 * FUNCTION:
200 * Writes an EAPOL-Start frame to the packet. It is only used by the
201 * supplicant.
202 *
203 * LOGIC:
204 * Prepend the appropriate EAPOL header to the packet. There is no
205 * EAPOL payload for this kind of frame.
206 *
207 * ASSUMPTIONS:
208 * The packet has enough space available for prepending the header.
209 *
210 * @param packet the packet to which the frame should be written
211 * @param dstMac the MAC address of the destination (authenticator)
212 * @param srcMac the MAC address of the source (supplicant)
213 *
214 * @return ANI_OK if the operation succeeds
215 */
216int
217aniEapolWriteStart(tAniPacket *packet,
218 tAniMacAddr dstMac,
219 tAniMacAddr srcMac)
220{
221 return ( addEapolHeaders(packet, dstMac, srcMac, ANI_EAPOL_TYPE_START) );
222}
223
224/**
225 * aniEapolWriteEapPacket
226 *
227 * FUNCTION:
228 * Writes the EAPOL/EAP-Packet frame headers. It is used
229 * by both the authenticator and the supplicant. This creates an EAPOL
230 * frame that is carrying an EAP message as its payload.
231 *
232 * LOGIC:
233 * Prepend the appropriate EAPOL header to the packet.
234 *
235 * ASSUMPTIONS:
236 * The EAP message (ie., the payload) is already available in the
237 * packet and that the packet has enough space available for
238 * prepending the EAPOL header.
239 *
240 * @param packet the packet containing the EAP message
241 * @param dstMac the MAC address of the destination (authenticator)
242 * @param srcMac the MAC address of the source (supplicant)
243 *
244 * @return ANI_OK if the operation succeeds
245 */
246int
247aniEapolWriteEapPacket(tAniPacket *eapPacket,
248 tAniMacAddr dstMac,
249 tAniMacAddr srcMac)
250{
251 return( addEapolHeaders(eapPacket, dstMac, srcMac, ANI_EAPOL_TYPE_PACKET) );
252}
253
254/**
255 * aniEapolParse
256 *
257 * FUNCTION:
258 * Parses an EAPoL frame to the first level of headers (no EAP
259 * headers are parsed).
260 *
261 * NOTE: This is a non-destructive read, that is the
262 * headers are not stripped off the packet. However, any additional
263 * data at the end of the packet, beyond what the EAPoL headers encode
264 * will be stripped off.
265 *
266 * @param packet the packet containing the EAPoL frame to parse
267 * @param dstMac a pointer to set to the location of the destination
268 * MAC address
269 * @param srcMac a pointer to set to the location of the source
270 * MAC address
271 * @param type a pointer to set to the location of the EAPOL type
272 * field.
273 *
274 * @return the non-negative length of the EAPOL payload if the operation
275 * succeeds
276 */
277int
278aniEapolParse(tAniPacket *packet,
279 v_U8_t **dstMac,
280 v_U8_t **srcMac,
281 v_U8_t **type)
282{
283 v_U16_t frameType;
284 v_U8_t *ptr;
285 int retVal;
286 int tmp;
287
288 if (aniAsfPacketGetLen(packet) < EAPOL_BODY_POS)
289 return ANI_E_ILLEGAL_ARG;
290
291 retVal = aniAsfPacketGetBytes(packet, &ptr);
292 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
293 {
294 return retVal;
295 }
296
297 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO,
298 "Supp parsing EAPOL packet of len %d: \n",
299 retVal);
300
301 frameType = (ptr[ETHER_PROTO_POS] << 8) + ptr[ETHER_PROTO_POS+1];
302
303 /*
304 * Validate the EAPOL-FRAME
305 */
306
307 if (frameType != ANI_ETH_P_EAPOL)
308 return ANI_E_ILLEGAL_ARG;
309
310 *dstMac = ptr + DST_MAC_POS;
311 *srcMac = ptr + SRC_MAC_POS;
312
313 // if (ptr[EAPOL_VERSION_POS] != EAPOL_VERSION_1)
314 // return ANI_E_ILLEGAL_ARG;
315
316 *type = ptr + ANI_EAPOL_TYPE_POS;
317 retVal = (ptr[EAPOL_BODY_LEN_POS] << 8) + ptr[EAPOL_BODY_LEN_POS + 1];
318
319 /*
320 * Validate the length of the body. Allow for longer
321 * packets than encoded, but encoding should not be larger than
322 * packet.
323 * Note: EAPOL body len does not include headers
324 */
325 tmp = aniAsfPacketGetLen(packet) - EAPOL_RX_HEADER_SIZE;
326 if (retVal > tmp)
327 {
328 retVal = ANI_E_ILLEGAL_ARG;
329 }
330 else {
331 if (retVal < tmp)
332 {
333 retVal = aniAsfPacketTruncateFromRear(packet, tmp - retVal);
334 }
335 }
336
337 return retVal;
338}
339
340/**
341 * aniEapolWriteKey
342 *
343 * Writes out a complete EAPOL-Key frame. The key descriptor is
344 * appended to the packet and the EAPOL header is prepended to it. If
345 * a micKey is passed in, then a MIC is calculated and inserted into
346 * the frame.
347 *
348 * @param packet the packet to write to
349 * @param dstMac the destination MAC address
350 * @param srcMac the source MAC address
351 * @param descType the key descriptor type
352 * (ANI_EAPOL_KEY_DESC_TYPE_LEGACY_RC4 or
353 * ANI_EAPOL_KEY_DESC_TYPE_RSN).
354 * @param keyDescData the key descriptor data corresponding to the
355 * above descType. The signature field is ignored and will be
356 * generated in the packet. The key bytes are expected to be encrypted
357 * if they need to be encrypted.
358 * @param micKey the MIC key
359 * @param micKeyLen the number of bytes in the MIC key
360 *
361 * @return ANI_OK if the operation succeeds
362 *
363 */
364int
365aniEapolWriteKey(v_U32_t cryptHandle,
366 tAniPacket *packet,
367 tAniMacAddr dstMac,
368 tAniMacAddr srcMac,
369 int descType,
370 void *keyDescData,
371 v_U8_t *micKey,
372 v_U32_t micKeyLen)
373{
374 int retVal;
375
376 if (packet == NULL)
377 return ANI_E_NULL_VALUE;
378
379 do
380 {
381 if ((descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW)
382 || (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN))
383 {
384
385 retVal = writeRsnKeyDesc(packet,
386 (tAniEapolRsnKeyDesc *) keyDescData,
387 // Indicate
388 // ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW
389 // or ANI_EAPOL_KEY_DESC_TYPE_RSN
390 descType);
391 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
392 {
393 break;
394 }
395
396 retVal = addEapolHeaders(packet, dstMac, srcMac, ANI_EAPOL_TYPE_KEY);
397 if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
398
399 retVal = writeRsnKeyMic(cryptHandle,
400 packet,
401 (tAniEapolRsnKeyDesc *) keyDescData,
402 micKey, micKeyLen);
403 if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
404
405 }
406 else {
407 VOS_ASSERT( 0 );
408 return ANI_E_ILLEGAL_ARG;
409 }
410 }while( 0 );
411
412 return retVal;
413}
414
415
416/**
417 * aniEapolParseKey
418 *
419 * Parses and verifies a complete EAPOL-Key frame. The key descriptor
420 * type is returned and so is a newly allocated key descriptor structure
421 * that is appropriate for the type.
422 *
423 * NOTE: This is a non-destructive read. That is, the packet headers
424 * will be unchanged at the end of this read operation. This is so
425 * that a followup MIC check may be done on the complete packet. If
426 * the packet parsing fails, the packet headers are not guaranteed to
427 * be unchanged.
428 *
429 * @param packet the packet to read from. Note that the frame is not
430 * expected to contain any additional padding at the end other than
431 * the exact number of key bytes. (The aniEapolParse function will
432 * ensure this.)
433 * @param descType is set to the key descriptor type
434 * (ANI_EAPOL_KEY_DESC_TYPE_LEGACY_RC4 or
435 * ANI_EAPOL_KEY_DESC_TYPE_RSN).
436 * @param keyDescData is set to a newly allocated key descriptor
437 * corresponding to the above descType. The signature field is
438 * verified. The key bytes will be returned encrypted. It is the
439 * responsibility of the caller to free this structure and the data
440 * contained therein.
441 *
442 * @return ANI_OK if the operation succeeds
443 */
444int
445aniEapolParseKey(tAniPacket *packet,
446 int *descType,
447 void **keyDescData)
448{
449 int retVal;
450 v_U8_t *bytes;
451 v_U32_t eapolFrameLen;
452
453 if (packet == NULL)
454 return ANI_E_NULL_VALUE;
455
456 do
457 {
458 eapolFrameLen = aniAsfPacketGetLen(packet);
459
460 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "Supp parsing EAPOL-Key frame of len %d\n",
461 eapolFrameLen);
462
463 retVal = aniAsfPacketTruncateFromFront(packet, EAPOL_RX_HEADER_SIZE);
464 if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
465
466 retVal = aniAsfPacketGetBytes(packet, &bytes);
467 if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
468
469 if (*bytes == ANI_EAPOL_KEY_DESC_TYPE_RSN ||
470 *bytes == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW)
471 {
472 tAniEapolRsnKeyDesc *rsnDesc = NULL;
473
474 //*descType = ANI_EAPOL_KEY_DESC_TYPE_RSN;
475 *descType = (*bytes == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW ?
476 ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW : ANI_EAPOL_KEY_DESC_TYPE_RSN) ;
477 retVal = parseRsnKeyDesc(packet, &rsnDesc);
478 if( !ANI_IS_STATUS_SUCCESS(retVal) ) break;
479 *keyDescData = rsnDesc;
480 }
481 else
482 {
483 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
484 "Supp received unknown EAPOL-Key descriptor: %d\n",
485 *bytes);
486 retVal = ANI_E_ILLEGAL_ARG;
487 break;
488 }
489
490 aniAsfPacketMoveLeft(packet, eapolFrameLen);
491 }while( 0 );
492
493 return retVal;
494}
495
496
497
498static int
499parseRsnKeyDesc(tAniPacket *packet,
500 tAniEapolRsnKeyDesc **rsnDescPtr)
501{
502 int retVal = ANI_OK;
503 int len;
504 v_U8_t *bytes;
505 tAniEapolRsnKeyDesc *rsnDesc = NULL;
506
507 do
508 {
509 aniAsfPacketTruncateFromFront(packet, 1); // Desc-Type
510
511 rsnDesc = (tAniEapolRsnKeyDesc *)
512 vos_mem_malloc( sizeof(tAniEapolRsnKeyDesc) );
513
514 if (rsnDesc == NULL)
515 {
516 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
517 "Supp could not malloc EAPOL-Key Descriptor for RSN\n");
518 retVal = ANI_E_MALLOC_FAILED;
519 break;
520 }
521
522 retVal = parseRsnKeyInfo(packet, &rsnDesc->info);
523 if (retVal != ANI_OK) break;
524
525 retVal = aniAsfPacketGet16(packet, &rsnDesc->keyLen);
526 if (retVal != ANI_OK)
527 {
528 break;
529 }
530
531 len = sizeof(rsnDesc->replayCounter);
532 retVal = aniAsfPacketGetN(packet, len, &bytes);
533 if (retVal != ANI_OK)
534 {
535 break;
536 }
537 vos_mem_copy(rsnDesc->replayCounter, bytes, len);
538
539 len = sizeof(rsnDesc->keyNonce);
540 retVal = aniAsfPacketGetN(packet, len, &bytes);
541 if (retVal != ANI_OK)
542 {
543 break;
544 }
545 vos_mem_copy(rsnDesc->keyNonce, bytes, len);
546
547 len = sizeof(rsnDesc->keyIv);
548 retVal = aniAsfPacketGetN(packet, len, &bytes);
549 if (retVal != ANI_OK)
550 {
551 break;
552 }
553 vos_mem_copy(rsnDesc->keyIv, bytes, len);
554
555 len = sizeof(rsnDesc->keyRecvSeqCounter);
556 retVal = aniAsfPacketGetN(packet, len, &bytes);
557 if (retVal != ANI_OK)
558 {
559 break;
560 }
561 vos_mem_copy(rsnDesc->keyRecvSeqCounter, bytes, len);
562
563 len = sizeof(rsnDesc->keyId);
564 retVal = aniAsfPacketGetN(packet, len, &bytes);
565 if (retVal != ANI_OK)
566 {
567 break;
568 }
569 vos_mem_copy(rsnDesc->keyId, bytes, len);
570
571 len = sizeof(rsnDesc->keyMic);
572 retVal = aniAsfPacketGetN(packet, len, &bytes);
573 if (retVal != ANI_OK)
574 {
575 break;
576 }
577 vos_mem_copy(rsnDesc->keyMic, bytes, len);
578
579 retVal = aniAsfPacketGet16(packet, &rsnDesc->keyDataLen);
580 if (retVal != ANI_OK)
581 {
582 break;
583 }
584
585 len = rsnDesc->keyDataLen;
586 if (len > 0) {
587 // We have a key
588 retVal = aniAsfPacketGetN(packet, len, &bytes);
589 if (retVal != ANI_OK)
590 {
591 break;
592 }
593 rsnDesc->keyData = (v_U8_t*)vos_mem_malloc(len);
594 if (rsnDesc->keyData == NULL)
595 {
596 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Could not allocate RSN key bytes!\n");
597 VOS_ASSERT( 0 );
598 retVal = ANI_E_MALLOC_FAILED;
599 break;
600 }
601 vos_mem_copy(rsnDesc->keyData, bytes, len);
602 }
603 else {
604 rsnDesc->keyData = NULL;
605 }
606
607 *rsnDescPtr = rsnDesc;
608
609 }while( 0 );
610
611 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
612 {
613 vos_mem_free(rsnDesc);
614 }
615
616 return retVal;
617}
618
619static int
620parseRsnKeyInfo(tAniPacket *packet,
621 tAniRsnKeyInfo *info)
622{
623 v_U16_t tmp;
624 int retVal;
625
626 retVal = aniAsfPacketGet16(packet, &tmp);
627 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
628 {
629 return retVal;
630 }
631
632 info->keyDescVers = (tmp & ANI_SSM_RSN_KEY_DESC_VERS_MASK)
633 >> ANI_SSM_RSN_KEY_DESC_VERS_OFFSET;
634 if (info->keyDescVers != ANI_EAPOL_KEY_DESC_VERS_RC4 &&
635 info->keyDescVers != ANI_EAPOL_KEY_DESC_VERS_AES)
636 return ANI_E_ILLEGAL_ARG;
637
638 info->unicastFlag = (tmp & ANI_SSM_RSN_UNICAST_MASK) ?
639 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
640 info->keyId = (tmp & ANI_SSM_RSN_KEY_INDEX_MASK)
641 >> ANI_SSM_RSN_KEY_INDEX_OFFSET;
642 info->installFlag = (tmp & ANI_SSM_RSN_INSTALL_MASK) ?
643 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
644 info->ackFlag = (tmp & ANI_SSM_RSN_ACK_MASK) ?
645 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
646 info->micFlag = (tmp & ANI_SSM_RSN_MIC_MASK) ?
647 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
648 info->secureFlag = (tmp & ANI_SSM_RSN_SECURE_MASK) ?
649 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
650 info->errorFlag = (tmp & ANI_SSM_RSN_ERROR_MASK) ?
651 eANI_BOOLEAN_TRUE: eANI_BOOLEAN_FALSE;
652 info->requestFlag = (tmp & ANI_SSM_RSN_REQUEST_MASK) ?
653 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
654 info->encKeyDataFlag = (tmp & ANI_SSM_RSN_ENC_KEY_DATA_MASK) ?
655 eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE;
656
657 return ANI_OK;
658}
659
660
661static int
662writeRsnKeyDesc(tAniPacket *packet,
663 tAniEapolRsnKeyDesc *rsnDesc,
664 v_U8_t keyDescType)
665{
666 int retVal;
667
668 do
669 {
670 // This can be either ANI_EAPOL_KEY_DESC_TYPE_RSN
671 // or ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW
672 retVal = aniAsfPacketAppend8(packet, keyDescType);
673 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
674
675 retVal = writeRsnKeyInfo(packet, &rsnDesc->info);
676 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
677
678 retVal = aniAsfPacketAppend16(packet, rsnDesc->keyLen);
679 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
680
681 retVal = aniAsfPacketAppendBuffer(packet,
682 rsnDesc->replayCounter,
683 sizeof(rsnDesc->replayCounter));
684 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
685
686 retVal = aniAsfPacketAppendBuffer(packet,
687 rsnDesc->keyNonce,
688 sizeof(rsnDesc->keyNonce));
689 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
690
691 retVal = aniAsfPacketAppendBuffer(packet,
692 rsnDesc->keyIv,
693 sizeof(rsnDesc->keyIv));
694 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
695
696 retVal = aniAsfPacketAppendBuffer(packet,
697 rsnDesc->keyRecvSeqCounter,
698 sizeof(rsnDesc->keyRecvSeqCounter));
699 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
700
701 retVal = aniAsfPacketAppendBuffer(packet,
702 rsnDesc->keyId,
703 sizeof(rsnDesc->keyId));
704 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
705
706 // Zero out the key MIC
707 retVal = aniAsfPacketAppendBuffer(packet,
708 ZERO_BYTES,
709 sizeof(rsnDesc->keyMic));
710 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
711
712 retVal = aniAsfPacketAppend16(packet, rsnDesc->keyDataLen);
713 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
714
715 if (rsnDesc->keyDataLen != 0)
716 {
717 retVal = aniAsfPacketAppendBuffer(packet,
718 rsnDesc->keyData,
719 rsnDesc->keyDataLen);
720 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
721 }
722 }while( 0 );
723
724 return retVal;
725}
726
727static int
728writeRsnKeyInfo(tAniPacket *packet, tAniRsnKeyInfo *info)
729{
730 int retVal;
731 v_U16_t tmp;
732 v_U16_t infoValue;
733
734 infoValue = 0;
735
736 tmp = (v_U16_t)info->keyDescVers;
737 tmp = tmp << ANI_SSM_RSN_KEY_DESC_VERS_OFFSET;
738 infoValue |= (tmp & ANI_SSM_RSN_KEY_DESC_VERS_MASK);
739
740 if (info->unicastFlag)
741 infoValue |= ANI_SSM_RSN_UNICAST_MASK;
742
743 tmp = info->keyId;
744 tmp = tmp << ANI_SSM_RSN_KEY_INDEX_OFFSET;
745 infoValue |= (tmp & ANI_SSM_RSN_KEY_INDEX_MASK);
746
747 if (info->installFlag)
748 infoValue |= ANI_SSM_RSN_INSTALL_MASK;
749
750 if (info->ackFlag)
751 infoValue |= ANI_SSM_RSN_ACK_MASK;
752
753 if (info->micFlag)
754 infoValue |= ANI_SSM_RSN_MIC_MASK;
755
756 if (info->secureFlag)
757 infoValue |= ANI_SSM_RSN_SECURE_MASK;
758
759 if (info->errorFlag)
760 infoValue |= ANI_SSM_RSN_ERROR_MASK;
761
762 if (info->requestFlag)
763 infoValue |= ANI_SSM_RSN_REQUEST_MASK;
764
765 if (info->encKeyDataFlag)
766 infoValue |= ANI_SSM_RSN_ENC_KEY_DATA_MASK;
767
768 retVal = aniAsfPacketAppend16(packet, infoValue);
769
770 return retVal;
771}
772
773
774static int
775writeRsnKeyMic(v_U32_t cryptHandle,
776 tAniPacket *eapolFrame,
777 tAniEapolRsnKeyDesc *rsnDesc,
778 v_U8_t *micKey,
779 v_U32_t micKeyLen)
780{
781 int retVal = ANI_OK;
782 int len;
783
784 v_U8_t *ptr = NULL;
785 v_U8_t *micPos = NULL;
786 v_U8_t result[VOS_DIGEST_SHA1_SIZE]; // Larger of the two
787
788 // Sanity check the arguments and return if no MIC generation is
789 // needed
790 if (micKey != NULL)
791 {
792 if (micKeyLen == 0 || !rsnDesc->info.micFlag)
793 {
794 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
795 "Supp MIC key provided but micKeyLen or micFlag is not set!\n");
796 VOS_ASSERT( 0 );
797 return ANI_E_ILLEGAL_ARG;
798 }
799 }
800 else {
801 if (rsnDesc->info.micFlag)
802 {
803 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
804 "Supp micFlag is set but MIC key not provided!\n");
805 VOS_ASSERT( 0 );
806 return ANI_E_ILLEGAL_ARG;
807 }
808 // Normal condition where MIC is not desired by the caller
809 return ANI_OK;
810 }
811
812 len = aniAsfPacketGetBytes(eapolFrame, &ptr);
813 if( !ANI_IS_STATUS_SUCCESS( len ) )
814 {
815 return len;
816 }
817
818 micPos = ptr + ANI_SSM_RSN_KEY_MIC_OFFSET + SNAP_HEADER_SIZE;
819
820 // Clear the MIC field in the packet before the MIC computation
821 vos_mem_zero( micPos, VOS_DIGEST_MD5_SIZE);
822
823 // Skip to the EAPOL version field for MIC computation
824 ptr += EAPOL_VERSION_POS + SNAP_HEADER_SIZE;
825 len -= (EAPOL_VERSION_POS + SNAP_HEADER_SIZE);
826
827 if (rsnDesc->info.keyDescVers == ANI_EAPOL_KEY_DESC_VERS_AES)
828 {
829 if( VOS_IS_STATUS_SUCCESS( vos_sha1_hmac_str(cryptHandle, ptr, len, micKey, micKeyLen, result) ) )
830 {
831 retVal = ANI_OK;
832 }
833 else
834 {
835 retVal = ANI_ERROR;
836 }
837 }
838 else {
839 VOS_ASSERT( 0 );
840 retVal = ANI_E_ILLEGAL_ARG;
841 }
842
843 if (retVal == ANI_OK)
844 {
845 // Copy only 16B which is the smaller of the two and the same as
846 // ANI_EAPOL_KEY_RSN_MIC_SIZE
847 vos_mem_copy(micPos, result, VOS_DIGEST_MD5_SIZE);
848 }
849
850 return retVal;
851}
852
853/**
854 * aniEapolKeyCheckMic
855 *
856 * @param eapolFrame the complete EAPOL-Key packet
857 * @param descType the key descriptor type
858 * @param keyDescData the key descriptor
859 * @param micKey the MIC key
860 * @param micKeyLen the number of bytes in the MIC key
861 *
862 * @return ANI_OK if the operation succeeds; ANI_E_MIC_FAILED if the
863 * MIC check fails.
864 */
865int
866aniEapolKeyCheckMic(v_U32_t cryptHandle,
867 tAniPacket *eapolFrame,
868 int descType,
869 void *keyDescData,
870 v_U8_t *micKey,
871 v_U32_t micKeyLen)
872{
873 if (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW)
874 {
875 return checkRsnKeyMic(cryptHandle, eapolFrame, keyDescData, micKey, micKeyLen);
876 }
877 else {
878 VOS_ASSERT( 0 );
879 return ANI_E_ILLEGAL_ARG;
880 }
881}
882
883
884static int
885checkRsnKeyMic(v_U32_t cryptHandle,
886 tAniPacket *eapolFrame,
887 tAniEapolRsnKeyDesc *rsnDesc,
888 v_U8_t *micKey,
889 v_U32_t micKeyLen)
890{
891 int retVal = ANI_ERROR;
892 int len;
893
894 v_U8_t *ptr = NULL;
895 v_U8_t *micPos = NULL;
896
897 v_U8_t result[VOS_DIGEST_SHA1_SIZE]; // Larger of the two
898 v_U8_t incomingMic[ANI_EAPOL_KEY_RSN_MIC_SIZE];
899
900 if (!rsnDesc->info.micFlag)
901 {
902 VOS_ASSERT( 0 );
903 return ANI_E_ILLEGAL_ARG;
904 }
905
906 len = aniAsfPacketGetBytes(eapolFrame, &ptr);
907 if( ANI_IS_STATUS_SUCCESS( len ) )
908 {
909 micPos = ptr + ANI_SSM_RSN_KEY_MIC_OFFSET;
910
911 // Skip to the EAPOL version field for MIC computation
912 ptr += EAPOL_VERSION_POS;
913 len -= EAPOL_VERSION_POS;
914
915 // Copy existing MIC to temporary location and zero it out
916 vos_mem_copy( incomingMic, micPos, ANI_EAPOL_KEY_RSN_MIC_SIZE );
917 vos_mem_zero( micPos, ANI_EAPOL_KEY_RSN_MIC_SIZE );
918
919 if (rsnDesc->info.keyDescVers == ANI_EAPOL_KEY_DESC_VERS_AES)
920 {
921 if( VOS_IS_STATUS_SUCCESS( vos_sha1_hmac_str(cryptHandle, ptr, len, micKey, micKeyLen, result) ) )
922 {
923 retVal = ANI_OK;
924 }
925 }
926 else {
927 VOS_ASSERT( 0 );
928 retVal = ANI_E_ILLEGAL_ARG;
929 }
930
931 if (retVal == ANI_OK)
932 {
933 if ( !vos_mem_compare(incomingMic, result, ANI_EAPOL_KEY_RSN_MIC_SIZE))
934 {
935 retVal = ANI_E_MIC_FAILED;
936 }
937 }
938 }
939
940 return retVal;
941}
942
943/**
944 * aniEapolKeyFreeDesc
945 *
946 * Frees the EAPOL key descriptor and the key bytes contained within it.
947 *
948 * @param descType the key descriptor type
949 * @param keyDescData the key descriptor
950 *
951 * @return ANI_OK if the operation succeeds
952 */
953int
954aniEapolKeyFreeDesc(int descType, void *keyDescData)
955{
956 tAniEapolRsnKeyDesc *rsnDesc;
957
958 if( keyDescData )
959 {
960 if ((descType == ANI_EAPOL_KEY_DESC_TYPE_RSN_NEW)
961 || (descType == ANI_EAPOL_KEY_DESC_TYPE_RSN))
962 {
963
964 rsnDesc = (tAniEapolRsnKeyDesc *) keyDescData;
965 if (rsnDesc->keyData != NULL)
966 vos_mem_free(rsnDesc->keyData);
967
968 }
969 else {
970
971 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
972 "Supp asked to free illegal type: %d\n", descType);
973
974 }
975
976 vos_mem_free(keyDescData);
977 }
978
979 return ANI_OK;
980}
981
982v_U8_t *
983aniEapolType2Str(v_U8_t type)
984{
985 switch (type)
986 {
987 case ANI_EAPOL_TYPE_PACKET:
988 return (v_U8_t *)ANI_EAPOL_TYPE_PACKET_STR;
989 break;
990 case ANI_EAPOL_TYPE_START:
991 return (v_U8_t *)ANI_EAPOL_TYPE_START_STR;
992 break;
993 case ANI_EAPOL_TYPE_LOGOFF:
994 return (v_U8_t *)ANI_EAPOL_TYPE_LOGOFF_STR;
995 break;
996 case ANI_EAPOL_TYPE_KEY:
997 return (v_U8_t *)ANI_EAPOL_TYPE_KEY_STR;
998 break;
999 case ANI_EAPOL_TYPE_ASF_ALERT:
1000 return (v_U8_t *)ANI_EAPOL_TYPE_ASF_ALERT_STR;
1001 break;
1002 default:
1003 return (v_U8_t *)ANI_EAPOL_TYPE_UNKNOWN_STR;
1004 break;
1005 }
1006}
1007
1008
1009void bapRsnEapolHandler( v_PVOID_t pvFsm, tAniPacket *packet, v_BOOL_t fIsAuth )
1010{
1011 int retVal;
1012 v_U8_t *dstMac = NULL;
1013 v_U8_t *srcMac = NULL;
1014 v_U8_t *type = NULL;
1015
1016 retVal = aniEapolParse(packet, &dstMac, &srcMac, &type);
1017 if ( retVal >= 0 )
1018 {
1019 retVal = ANI_OK;
1020
1021 // Sanity check that a PAE role has been assigned to it,
1022 // and then dispatch to the appropriate handler
1023
1024 if( fIsAuth )
1025 {
1026 tAuthRsnFsm *fsm = (tAuthRsnFsm *)pvFsm;
1027 authEapolHandler( fsm, packet, dstMac, srcMac, type );
1028 }
1029 else
1030 {
1031 tSuppRsnFsm *fsm = (tSuppRsnFsm *)pvFsm;
1032 suppEapolHandler(fsm, packet, dstMac, srcMac, type);
1033 } // switch statement
1034 } // Successfully parsed EAPOL
1035 else
1036 {
1037 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1038 "eapolHandler Received bad EAPOL message of len %d (status=%d)\n",
1039 aniAsfPacketGetLen(packet), retVal );
1040 }
1041 aniAsfPacketFree( packet );
1042}
1043
1044
1045int bapRsnFormPktFromVosPkt( tAniPacket **ppPacket, vos_pkt_t *pVosPacket )
1046{
1047 int retVal = ANI_ERROR;
1048 VOS_STATUS status;
1049 v_U16_t uPktLen;
1050#define BAP_RSN_SNAP_TYPE_OFFSET 20
1051#define BAP_RSN_ETHERNET_3_HEADER_LEN 22
1052 v_U8_t *pFrame;
1053 tAniPacket *pAniPacket = NULL;
1054
1055 do
1056 {
1057 status = vos_pkt_get_packet_length( pVosPacket, &uPktLen );
1058 if( !VOS_IS_STATUS_SUCCESS(status) ) break;
1059 if( (uPktLen < BAP_RSN_ETHERNET_3_HEADER_LEN) )
1060 {
1061 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1062 " authRsnRxFrameHandler receive eapol packet size (%d) too small (%d)\n",
1063 uPktLen, BAP_RSN_ETHERNET_3_HEADER_LEN );
1064 break;
1065 }
1066 status = vos_pkt_peek_data( pVosPacket, 0, (v_VOID_t *)&pFrame, uPktLen );
1067 if( !VOS_IS_STATUS_SUCCESS(status) ) break;
1068 retVal = aniAsfPacketAllocateExplicit(&pAniPacket, uPktLen, 0 );
1069 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
1070 {
1071 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1072 " authRsnRxFrameHandler failed to get buffer size (%d) \n",
1073 uPktLen );
1074 break;
1075 }
1076 aniAsfPacketEmptyExplicit( pAniPacket, 0 );
1077 pFrame[ETHER_PROTO_POS] = pFrame[BAP_RSN_SNAP_TYPE_OFFSET];
1078 pFrame[ETHER_PROTO_POS + 1] = pFrame[BAP_RSN_SNAP_TYPE_OFFSET + 1];
1079 //push ethernet II header in
1080 retVal = aniAsfPacketAppendBuffer( pAniPacket, pFrame, ETHER_PROTO_POS + 2 );
1081 if( !ANI_IS_STATUS_SUCCESS( retVal ) ) break;
1082 //Get the rest of the data in
1083 uPktLen -= BAP_RSN_ETHERNET_3_HEADER_LEN;
1084 VOS_ASSERT( uPktLen > 0 );
1085 retVal = aniAsfPacketAppendBuffer( pAniPacket, pFrame + BAP_RSN_ETHERNET_3_HEADER_LEN,
1086 uPktLen );
1087 if( !ANI_IS_STATUS_SUCCESS( retVal ) )
1088 {
1089 VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR,
1090 " authRsnRxFrameHandler cannot retrieve eapol payload size (%d)\n",
1091 uPktLen );
1092 break;
1093 }
1094 }while( 0 );
1095
1096 if( ANI_IS_STATUS_SUCCESS( retVal ) )
1097 {
1098 *ppPacket = pAniPacket;
1099 }
1100 else if( pAniPacket )
1101 {
1102 aniAsfPacketFree( pAniPacket );
1103 }
1104
1105 return retVal;
1106}
1107
1108