$search
00001 /* 00002 * Wi-Fi Protected Setup - attribute processing 00003 * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/sha256.h" 00019 #include "wps_i.h" 00020 00021 00022 int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, 00023 const struct wpabuf *msg) 00024 { 00025 u8 hash[SHA256_MAC_LEN]; 00026 const u8 *addr[2]; 00027 size_t len[2]; 00028 00029 if (authenticator == NULL) { 00030 wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " 00031 "included"); 00032 return -1; 00033 } 00034 00035 if (wps->last_msg == NULL) { 00036 wpa_printf(MSG_DEBUG, "WPS: Last message not available for " 00037 "validating authenticator"); 00038 return -1; 00039 } 00040 00041 /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) 00042 * (M_curr* is M_curr without the Authenticator attribute) 00043 */ 00044 addr[0] = wpabuf_head(wps->last_msg); 00045 len[0] = wpabuf_len(wps->last_msg); 00046 addr[1] = wpabuf_head(msg); 00047 len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN; 00048 hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); 00049 00050 if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { 00051 wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); 00052 return -1; 00053 } 00054 00055 return 0; 00056 } 00057 00058 00059 int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, 00060 const u8 *key_wrap_auth) 00061 { 00062 u8 hash[SHA256_MAC_LEN]; 00063 const u8 *head; 00064 size_t len; 00065 00066 if (key_wrap_auth == NULL) { 00067 wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); 00068 return -1; 00069 } 00070 00071 head = wpabuf_head(msg); 00072 len = wpabuf_len(msg) - 4 - WPS_KWA_LEN; 00073 if (head + len != key_wrap_auth - 4) { 00074 wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " 00075 "decrypted attribute"); 00076 return -1; 00077 } 00078 00079 hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash); 00080 if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { 00081 wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); 00082 return -1; 00083 } 00084 00085 return 0; 00086 } 00087 00088 00089 static int wps_process_cred_network_idx(struct wps_credential *cred, 00090 const u8 *idx) 00091 { 00092 if (idx == NULL) { 00093 wpa_printf(MSG_DEBUG, "WPS: Credential did not include " 00094 "Network Index"); 00095 return -1; 00096 } 00097 00098 wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); 00099 00100 return 0; 00101 } 00102 00103 00104 static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid, 00105 size_t ssid_len) 00106 { 00107 if (ssid == NULL) { 00108 wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); 00109 return -1; 00110 } 00111 00112 /* Remove zero-padding since some Registrar implementations seem to use 00113 * hardcoded 32-octet length for this attribute */ 00114 while (ssid_len > 0 && ssid[ssid_len - 1] == 0) 00115 ssid_len--; 00116 00117 wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len); 00118 if (ssid_len <= sizeof(cred->ssid)) { 00119 os_memcpy(cred->ssid, ssid, ssid_len); 00120 cred->ssid_len = ssid_len; 00121 } 00122 00123 return 0; 00124 } 00125 00126 00127 static int wps_process_cred_auth_type(struct wps_credential *cred, 00128 const u8 *auth_type) 00129 { 00130 if (auth_type == NULL) { 00131 wpa_printf(MSG_DEBUG, "WPS: Credential did not include " 00132 "Authentication Type"); 00133 return -1; 00134 } 00135 00136 cred->auth_type = WPA_GET_BE16(auth_type); 00137 wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", 00138 cred->auth_type); 00139 00140 return 0; 00141 } 00142 00143 00144 static int wps_process_cred_encr_type(struct wps_credential *cred, 00145 const u8 *encr_type) 00146 { 00147 if (encr_type == NULL) { 00148 wpa_printf(MSG_DEBUG, "WPS: Credential did not include " 00149 "Encryption Type"); 00150 return -1; 00151 } 00152 00153 cred->encr_type = WPA_GET_BE16(encr_type); 00154 wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", 00155 cred->encr_type); 00156 00157 return 0; 00158 } 00159 00160 00161 static int wps_process_cred_network_key_idx(struct wps_credential *cred, 00162 const u8 *key_idx) 00163 { 00164 if (key_idx == NULL) 00165 return 0; /* optional attribute */ 00166 00167 wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); 00168 cred->key_idx = *key_idx; 00169 00170 return 0; 00171 } 00172 00173 00174 static int wps_process_cred_network_key(struct wps_credential *cred, 00175 const u8 *key, size_t key_len) 00176 { 00177 if (key == NULL) { 00178 wpa_printf(MSG_DEBUG, "WPS: Credential did not include " 00179 "Network Key"); 00180 return -1; 00181 } 00182 00183 wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len); 00184 if (key_len <= sizeof(cred->key)) { 00185 os_memcpy(cred->key, key, key_len); 00186 cred->key_len = key_len; 00187 } 00188 00189 return 0; 00190 } 00191 00192 00193 static int wps_process_cred_mac_addr(struct wps_credential *cred, 00194 const u8 *mac_addr) 00195 { 00196 if (mac_addr == NULL) { 00197 wpa_printf(MSG_DEBUG, "WPS: Credential did not include " 00198 "MAC Address"); 00199 return -1; 00200 } 00201 00202 wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); 00203 os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN); 00204 00205 return 0; 00206 } 00207 00208 00209 static int wps_process_cred_eap_type(struct wps_credential *cred, 00210 const u8 *eap_type, size_t eap_type_len) 00211 { 00212 if (eap_type == NULL) 00213 return 0; /* optional attribute */ 00214 00215 wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len); 00216 00217 return 0; 00218 } 00219 00220 00221 static int wps_process_cred_eap_identity(struct wps_credential *cred, 00222 const u8 *identity, 00223 size_t identity_len) 00224 { 00225 if (identity == NULL) 00226 return 0; /* optional attribute */ 00227 00228 wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity", 00229 identity, identity_len); 00230 00231 return 0; 00232 } 00233 00234 00235 static int wps_process_cred_key_prov_auto(struct wps_credential *cred, 00236 const u8 *key_prov_auto) 00237 { 00238 if (key_prov_auto == NULL) 00239 return 0; /* optional attribute */ 00240 00241 wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d", 00242 *key_prov_auto); 00243 00244 return 0; 00245 } 00246 00247 00248 static int wps_process_cred_802_1x_enabled(struct wps_credential *cred, 00249 const u8 *dot1x_enabled) 00250 { 00251 if (dot1x_enabled == NULL) 00252 return 0; /* optional attribute */ 00253 00254 wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled); 00255 00256 return 0; 00257 } 00258 00259 00260 static void wps_workaround_cred_key(struct wps_credential *cred) 00261 { 00262 if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && 00263 cred->key_len > 8 && cred->key_len < 64 && 00264 cred->key[cred->key_len - 1] == 0) { 00265 /* 00266 * A deployed external registrar is known to encode ASCII 00267 * passphrases incorrectly. Remove the extra NULL termination 00268 * to fix the encoding. 00269 */ 00270 wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " 00271 "termination from ASCII passphrase"); 00272 cred->key_len--; 00273 } 00274 } 00275 00276 00277 int wps_process_cred(struct wps_parse_attr *attr, 00278 struct wps_credential *cred) 00279 { 00280 wpa_printf(MSG_DEBUG, "WPS: Process Credential"); 00281 00282 /* TODO: support multiple Network Keys */ 00283 if (wps_process_cred_network_idx(cred, attr->network_idx) || 00284 wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || 00285 wps_process_cred_auth_type(cred, attr->auth_type) || 00286 wps_process_cred_encr_type(cred, attr->encr_type) || 00287 wps_process_cred_network_key_idx(cred, attr->network_key_idx) || 00288 wps_process_cred_network_key(cred, attr->network_key, 00289 attr->network_key_len) || 00290 wps_process_cred_mac_addr(cred, attr->mac_addr) || 00291 wps_process_cred_eap_type(cred, attr->eap_type, 00292 attr->eap_type_len) || 00293 wps_process_cred_eap_identity(cred, attr->eap_identity, 00294 attr->eap_identity_len) || 00295 wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || 00296 wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled)) 00297 return -1; 00298 00299 wps_workaround_cred_key(cred); 00300 00301 return 0; 00302 } 00303 00304 00305 int wps_process_ap_settings(struct wps_parse_attr *attr, 00306 struct wps_credential *cred) 00307 { 00308 wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); 00309 os_memset(cred, 0, sizeof(*cred)); 00310 /* TODO: optional attributes New Password and Device Password ID */ 00311 if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || 00312 wps_process_cred_auth_type(cred, attr->auth_type) || 00313 wps_process_cred_encr_type(cred, attr->encr_type) || 00314 wps_process_cred_network_key_idx(cred, attr->network_key_idx) || 00315 wps_process_cred_network_key(cred, attr->network_key, 00316 attr->network_key_len) || 00317 wps_process_cred_mac_addr(cred, attr->mac_addr)) 00318 return -1; 00319 00320 wps_workaround_cred_key(cred); 00321 00322 return 0; 00323 }