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