Go to the documentation of this file.00001
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <stdint.h>
00027 #include <string.h>
00028 #include <sys/ioctl.h>
00029 #include <glib.h>
00030 #include <glib-object.h>
00031 #include <unistd.h>
00032 #include <sys/types.h>
00033 #include <sys/socket.h>
00034 #include <linux/types.h>
00035 #include <linux/netlink.h>
00036 #include <linux/rtnetlink.h>
00037 #include <linux/if_ether.h>
00038
00039 #define DBUS_API_SUBJECT_TO_CHANGE
00040
00041 #include <dbus/dbus.h>
00042 #include <eap-dbus.h>
00043 #include <wlancond.h>
00044 #include "wpa.h"
00045 #include "wapi.h"
00046 #include "common.h"
00047 #include "dbus-handler.h"
00048 #include "log.h"
00049
00050 #define COUNT_LE(p,s) *p++ = (unsigned char)(s & 0x00ff); *p++ = (unsigned char)((s & 0xff00) >> 8);
00051
00057 static guint parse_wapi_key_mgmt_suite(guint8 *suite)
00058 {
00059 if (memcmp(suite, WAPI_KEY_MGMT_CERT, CIPHER_SUITE_LEN) == 0)
00060 return WLANCOND_WAPI_CERT;
00061 if (memcmp(suite, WAPI_KEY_MGMT_PSK, CIPHER_SUITE_LEN) == 0)
00062 return WLANCOND_WAPI_PSK;
00063
00064 return 0;
00065 }
00066
00073 static guint parse_wapi_cipher_suite(guint8 *suite)
00074 {
00075 if (memcmp(suite, CIPHER_SUITE_WAPI, CIPHER_SUITE_LEN) == 0)
00076 return CIPHER_SUITE_SMS4;
00077
00078 return 0;
00079 }
00080
00087 int generate_wapi_ie(guint32 encryption, struct wlan_status_t *wlan_status)
00088 {
00089 guint8 *wapi_ie;
00090 struct wapi_ie_t *wapi_hdr;
00091 guint8* hdr_p;
00092
00093
00094 wapi_ie = g_malloc(sizeof(struct wapi_ie_t)+8+CIPHER_SUITE_LEN*3+WLANCOND_PMKID_LEN);
00095
00096 wapi_hdr = (struct wapi_ie_t*) wapi_ie;
00097 wapi_hdr->element_id = WAPI_ELEMENT;
00098
00099 wapi_hdr->version = WAPI_VERSION;
00100 hdr_p = (guint8*)(wapi_hdr + 1);
00101
00102
00103 COUNT_LE(hdr_p, 1);
00104
00105
00106 if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_PSK) {
00107 memcpy(hdr_p, WAPI_KEY_MGMT_PSK, CIPHER_SUITE_LEN);
00108 } else if ((encryption & WLANCOND_ENCRYPT_METHOD_MASK) == WLANCOND_WAPI_CERT){
00109 memcpy(hdr_p, WAPI_KEY_MGMT_CERT, CIPHER_SUITE_LEN);
00110 } else {
00111 DLOG_ERR("Unknown key management suite");
00112 g_free(wapi_ie);
00113 return -1;
00114 }
00115
00116 hdr_p += CIPHER_SUITE_LEN;
00117
00118
00119 COUNT_LE(hdr_p, 1);
00120
00121
00122 if (wlan_status->pairwise_cipher == CIPHER_SUITE_SMS4) {
00123 memcpy(hdr_p, CIPHER_SUITE_WAPI, CIPHER_SUITE_LEN);
00124 } else {
00125 DLOG_ERR("Unsupported pairwise cipher suite");
00126 g_free(wapi_ie);
00127 return -1;
00128 }
00129
00130 hdr_p += CIPHER_SUITE_LEN;
00131
00132
00133 if (wlan_status->group_cipher == CIPHER_SUITE_SMS4) {
00134 memcpy(hdr_p, CIPHER_SUITE_WAPI, CIPHER_SUITE_LEN);
00135 } else {
00136 DLOG_ERR("Unsupported group cipher suite");
00137 g_free(wapi_ie);
00138 return -1;
00139 }
00140
00141 hdr_p += CIPHER_SUITE_LEN;
00142
00143
00144
00145 COUNT_LE(hdr_p, 0);
00146
00147
00148
00149 unsigned char *bkid;
00150
00151
00152
00153
00154 if (find_pmkid_from_pmk_cache(wlan_status->conn.bssid, &bkid)) {
00155 DLOG_ERR("Error trying to retrieve the bkid.");
00156 return -1;
00157 }
00158
00159 if (bkid != NULL) {
00160 COUNT_LE(hdr_p, 1);
00161 memcpy(hdr_p, bkid, WLANCOND_PMKID_LEN);
00162 hdr_p += WLANCOND_PMKID_LEN;
00163 }
00164
00165
00166
00167 wapi_hdr->length = (hdr_p - wapi_ie) - 2;
00168
00169 #ifdef DEBUG_IE
00170 int i;
00171 printf("Own WPA IE:\n");
00172 for (i=0;i<wapi_hdr->length;i++) {
00173 printf("0x%02x ", i,wapi_ie[i]);
00174 }
00175 printf("\n");
00176 #endif
00177
00178 update_own_ie(wapi_ie, wapi_hdr->length + 2);
00179
00180 return 0;
00181 }
00182
00190 int parse_wapi_ie(unsigned char* wapi_ie, unsigned int wapi_ie_len,
00191 struct ap_info_t* ap_info)
00192 {
00193 struct wapi_ie_t *wapi_hdr;
00194 guint8 *hdr_p;
00195 guint ind;
00196 guint i;
00197 guint cipher_count = 0;
00198
00199
00200
00201
00202
00203
00204 wapi_hdr = (struct wapi_ie_t*) wapi_ie;
00205
00206 if (wapi_ie_len < sizeof(struct wapi_ie_t)) {
00207 DLOG_ERR("WAPI IE too short");
00208 return -1;
00209 }
00210
00211 if (wapi_hdr->element_id != WAPI_ELEMENT) {
00212 DLOG_ERR("Unknown WAPI IE received");
00213 return -1;
00214 }
00215
00216 ind = wapi_ie_len - sizeof(*wapi_hdr);
00217 hdr_p = (guint8*)(wapi_hdr + 1);
00218
00219
00220 if (ind >= 2) {
00221 ap_info->key_mgmt = 0;
00222 cipher_count = *(guint16*)hdr_p;
00223 hdr_p += 2;
00224 ind -= 2;
00225
00226 if (cipher_count == 0 || ind < cipher_count *
00227 CIPHER_SUITE_LEN) {
00228 DLOG_ERR("Invalid key mgmt cipher count or length");
00229 return -1;
00230 }
00231
00232
00233 for (i = 0; i < cipher_count; i++) {
00234 ap_info->key_mgmt |= parse_wapi_key_mgmt_suite(hdr_p);
00235 ind -= CIPHER_SUITE_LEN;
00236 hdr_p += CIPHER_SUITE_LEN;
00237 }
00238
00239 } else if (ind == 1) {
00240 DLOG_ERR("Remaining data too short");
00241 return -1;
00242 }
00243
00244
00245 if (ind >= 2) {
00246 ap_info->pairwise_cipher = 0;
00247 cipher_count = *(guint16*)hdr_p;
00248 ind -= 2;
00249
00250 if (cipher_count == 0) {
00251 DLOG_ERR("No pairwise ciphers");
00252
00253 return 0;
00254 }
00255
00256 if (ind < cipher_count * CIPHER_SUITE_LEN) {
00257 DLOG_ERR("Invalid pairwise cipher length");
00258 return -1;
00259 }
00260
00261 hdr_p += 2;
00262
00263 for (i = 0; i < cipher_count; i++) {
00264 ap_info->pairwise_cipher |= parse_wapi_cipher_suite(hdr_p);
00265 ind -= CIPHER_SUITE_LEN;
00266 hdr_p += CIPHER_SUITE_LEN;
00267 }
00268 } else if (ind == 1) {
00269 DLOG_ERR("Remaining data too short");
00270 return -1;
00271 }
00272
00273
00274
00275 if (ind >= CIPHER_SUITE_LEN) {
00276 ap_info->group_cipher = parse_wapi_cipher_suite(hdr_p);
00277 hdr_p += CIPHER_SUITE_LEN;
00278 ind -= CIPHER_SUITE_LEN;
00279 } else {
00280 DLOG_ERR("Strange length in WAPI IE");
00281 return -1;
00282 }
00283
00284
00285 if (ind >= 2) {
00286 hdr_p += 2;
00287 ind -= 2;
00288 }
00289
00290 if (ind > 0) {
00291 DLOG_DEBUG("IE includes BKID data");
00292 }
00293
00294 return 0;
00295 }