📄 wps_enrollee.c
字号:
/* * Wi-Fi Protected Setup - Enrollee * Copyright (c) 2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include "common.h"#include "sha256.h"#include "wps_i.h"#include "wps_dev_attr.h"static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); return 0;}static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg){ u8 state; if (wps->wps->ap) state = wps->wps->wps_state; else state = WPS_STATE_NOT_CONFIGURED; wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, state); return 0;}static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg){ u8 *hash; const u8 *addr[4]; size_t len[4]; if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) return -1; wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-S2", wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "E-Hash derivation"); return -1; } wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); wpabuf_put_be16(msg, ATTR_E_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ addr[0] = wps->snonce; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); wpabuf_put_be16(msg, ATTR_E_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN); return 0;}static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); wpabuf_put_be16(msg, ATTR_E_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); return 0;}static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); wpabuf_put_be16(msg, ATTR_E_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); return 0;}static struct wpabuf * wps_build_m1(struct wps_data *wps){ struct wpabuf *msg; u16 methods; if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; if (wps->pbc) methods |= WPS_CONFIG_PUSHBUTTON; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || wps_build_mac_addr(wps, msg) || wps_build_enrollee_nonce(wps, msg) || wps_build_public_key(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods(msg, methods) || wps_build_wps_state(wps, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2; return msg;}static struct wpabuf * wps_build_m3(struct wps_data *wps){ struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); if (wps->dev_password == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); return NULL; } wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M4; return msg;}static struct wpabuf * wps_build_m5(struct wps_data *wps){ struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M5) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M6; return msg;}static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, wps->wps->ssid_len); wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); return 0;}static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * Authentication Type"); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, wps->wps->auth_types); return 0;}static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * Encryption Type"); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, wps->wps->encr_types); return 0;}static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * Network Key"); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, wps->wps->network_key_len); wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); return 0;}static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg){ wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); return 0;}static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain){ if (wps->wps->ap_settings) { wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); wpabuf_put_data(plain, wps->wps->ap_settings, wps->wps->ap_settings_len); return 0; } return wps_build_cred_ssid(wps, plain) || wps_build_cred_mac_addr(wps, plain) || wps_build_cred_auth_type(wps, plain) || wps_build_cred_encr_type(wps, plain) || wps_build_cred_network_key(wps, plain);}static struct wpabuf * wps_build_m7(struct wps_data *wps){ struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M7) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce2(wps, plain) || (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M8; return msg;}static struct wpabuf * wps_build_wsc_done(struct wps_data *wps){ struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_DONE) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } if (wps->wps->ap) wps->state = RECV_ACK; else { wps_success_event(wps->wps); wps->state = WPS_FINISHED; } return msg;}static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps){ struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } return msg;}static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps){ struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_NACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error)) { wpabuf_free(msg); return NULL; } return msg;}struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, enum wsc_op_code *op_code){ struct wpabuf *msg; switch (wps->state) { case SEND_M1: msg = wps_build_m1(wps); *op_code = WSC_MSG; break; case SEND_M3: msg = wps_build_m3(wps); *op_code = WSC_MSG; break; case SEND_M5: msg = wps_build_m5(wps); *op_code = WSC_MSG; break; case SEND_M7: msg = wps_build_m7(wps); *op_code = WSC_MSG; break; case RECEIVED_M2D: if (wps->wps->ap) { msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; } msg = wps_build_wsc_ack(wps); *op_code = WSC_ACK; if (msg) { /* Another M2/M2D may be received */ wps->state = RECV_M2; } break; case SEND_WSC_NACK: msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; case WPS_MSG_DONE: msg = wps_build_wsc_done(wps); *op_code = WSC_Done; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; } if (*op_code == WSC_MSG && msg) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return msg;}static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce){ if (r_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); return 0;}static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce){ if (e_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); return -1; } return 0;}static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r){ if (uuid_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); return -1; } os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); return 0;}static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len){ if (pk == NULL || pk_len == 0) { wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_r == NULL) return -1; if (wps_derive_keys(wps) < 0) return -1; if (wps->request_type == WPS_REQ_WLAN_MANAGER_REGISTRAR && wps_derive_mgmt_keys(wps) < 0) return -1; return 0;}static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1){ if (r_hash1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); return -1; } os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN); return 0;}static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2){ if (r_hash2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); return -1; } os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN); return 0;}static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1){ u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (r_snonce1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1, WPS_SECRET_NONCE_LEN); /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ addr[0] = r_snonce1; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -