]>
Commit | Line | Data |
---|---|---|
a9eae7ef JM |
1 | /* |
2 | * BIP | |
3 | * Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi> | |
4 | * | |
5 | * This software may be distributed under the terms of the BSD license. | |
6 | * See README for more details. | |
7 | */ | |
8 | ||
9 | #include "utils/includes.h" | |
10 | ||
11 | #include "utils/common.h" | |
12 | #include "common/ieee802_11_defs.h" | |
13 | #include "crypto/aes_wrap.h" | |
14 | #include "wlantest.h" | |
15 | ||
16 | ||
17 | u8 * bip_protect(const u8 *igtk, u8 *frame, size_t len, u8 *ipn, int keyid, | |
18 | size_t *prot_len) | |
19 | { | |
20 | u8 *prot, *pos, *buf; | |
21 | u8 mic[16]; | |
22 | u16 fc; | |
23 | struct ieee80211_hdr *hdr; | |
24 | size_t plen; | |
25 | ||
26 | plen = len + 18; | |
27 | prot = os_malloc(plen); | |
28 | if (prot == NULL) | |
29 | return NULL; | |
30 | os_memcpy(prot, frame, len); | |
31 | pos = prot + len; | |
32 | *pos++ = WLAN_EID_MMIE; | |
33 | *pos++ = 16; | |
34 | WPA_PUT_LE16(pos, keyid); | |
35 | pos += 2; | |
36 | os_memcpy(pos, ipn, 6); | |
37 | pos += 6; | |
38 | os_memset(pos, 0, 8); /* MIC */ | |
39 | ||
40 | buf = os_malloc(plen + 20 - 24); | |
41 | if (buf == NULL) { | |
42 | os_free(prot); | |
43 | return NULL; | |
44 | } | |
45 | ||
46 | /* BIP AAD: FC(masked) A1 A2 A3 */ | |
47 | hdr = (struct ieee80211_hdr *) frame; | |
48 | fc = le_to_host16(hdr->frame_control); | |
49 | fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); | |
50 | WPA_PUT_LE16(buf, fc); | |
51 | os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN); | |
52 | os_memcpy(buf + 20, prot + 24, plen - 24); | |
53 | wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, plen + 20 - 24); | |
54 | /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */ | |
55 | if (omac1_aes_128(igtk, buf, plen + 20 - 24, mic) < 0) { | |
56 | os_free(prot); | |
57 | os_free(buf); | |
58 | return NULL; | |
59 | } | |
60 | os_free(buf); | |
61 | ||
62 | os_memcpy(pos, mic, 8); | |
63 | wpa_hexdump(MSG_DEBUG, "BIP MMIE MIC", pos, 8); | |
64 | ||
65 | *prot_len = plen; | |
66 | return prot; | |
67 | } | |
e88f0901 JM |
68 | |
69 | ||
70 | u8 * bip_gmac_protect(const u8 *igtk, size_t igtk_len, u8 *frame, size_t len, | |
71 | u8 *ipn, int keyid, size_t *prot_len) | |
72 | { | |
73 | u8 *prot, *pos, *buf; | |
74 | u16 fc; | |
75 | struct ieee80211_hdr *hdr; | |
76 | size_t plen; | |
77 | u8 nonce[12], *npos; | |
78 | ||
79 | plen = len + 26; | |
80 | prot = os_malloc(plen); | |
81 | if (prot == NULL) | |
82 | return NULL; | |
83 | os_memcpy(prot, frame, len); | |
84 | pos = prot + len; | |
85 | *pos++ = WLAN_EID_MMIE; | |
86 | *pos++ = 24; | |
87 | WPA_PUT_LE16(pos, keyid); | |
88 | pos += 2; | |
89 | os_memcpy(pos, ipn, 6); | |
90 | pos += 6; | |
91 | os_memset(pos, 0, 16); /* MIC */ | |
92 | ||
93 | buf = os_malloc(plen + 20 - 24); | |
94 | if (buf == NULL) { | |
95 | os_free(prot); | |
96 | return NULL; | |
97 | } | |
98 | ||
99 | /* BIP AAD: FC(masked) A1 A2 A3 */ | |
100 | hdr = (struct ieee80211_hdr *) frame; | |
101 | fc = le_to_host16(hdr->frame_control); | |
102 | fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA); | |
103 | WPA_PUT_LE16(buf, fc); | |
104 | os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN); | |
105 | os_memcpy(buf + 20, prot + 24, plen - 24); | |
106 | wpa_hexdump(MSG_MSGDUMP, "BIP-GMAC: AAD|Body(masked)", | |
107 | buf, plen + 20 - 24); | |
108 | ||
109 | /* Nonce: A2 | IPN */ | |
110 | os_memcpy(nonce, hdr->addr2, ETH_ALEN); | |
111 | npos = nonce + ETH_ALEN; | |
112 | *npos++ = ipn[5]; | |
113 | *npos++ = ipn[4]; | |
114 | *npos++ = ipn[3]; | |
115 | *npos++ = ipn[2]; | |
116 | *npos++ = ipn[1]; | |
117 | *npos++ = ipn[0]; | |
118 | wpa_hexdump(MSG_EXCESSIVE, "BIP-GMAC: Nonce", nonce, sizeof(nonce)); | |
119 | ||
120 | /* MIC = AES-GMAC(AAD || Frame Body(masked)) */ | |
121 | if (aes_gmac(igtk, igtk_len, nonce, sizeof(nonce), | |
122 | buf, plen + 20 - 24, pos) < 0) { | |
123 | os_free(prot); | |
124 | os_free(buf); | |
125 | return NULL; | |
126 | } | |
127 | os_free(buf); | |
128 | ||
129 | wpa_hexdump(MSG_DEBUG, "BIP-GMAC MMIE MIC", pos, 16); | |
130 | ||
131 | *prot_len = plen; | |
132 | return prot; | |
133 | } |