WPS: Moved Credential building to use struct wps_credential

This makes it easier to store old AP settings into wps->cred (and allow
them to modified and taken into use in the future). Separation between
Credential and AP Settings building is also cleaner in this design.
This commit is contained in:
Jouni Malinen 2008-11-27 21:14:39 +02:00
parent 96a2ed9f50
commit 3f42d42c07

View file

@ -758,7 +758,8 @@ static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg)
} }
static int wps_build_cred_network_idx(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_network_idx(struct wpabuf *msg,
struct wps_credential *cred)
{ {
wpa_printf(MSG_DEBUG, "WPS: * Network Index"); wpa_printf(MSG_DEBUG, "WPS: * Network Index");
wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); wpabuf_put_be16(msg, ATTR_NETWORK_INDEX);
@ -768,96 +769,73 @@ static int wps_build_cred_network_idx(struct wps_data *wps, struct wpabuf *msg)
} }
static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_ssid(struct wpabuf *msg,
struct wps_credential *cred)
{ {
wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpa_printf(MSG_DEBUG, "WPS: * SSID");
wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, ATTR_SSID);
wpabuf_put_be16(msg, wps->wps->ssid_len); wpabuf_put_be16(msg, cred->ssid_len);
wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); wpabuf_put_data(msg, cred->ssid, cred->ssid_len);
return 0; return 0;
} }
static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_auth_type(struct wpabuf *msg,
struct wps_credential *cred)
{ {
wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)",
wps->auth_type); cred->auth_type);
wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, 2);
wpabuf_put_be16(msg, wps->auth_type); wpabuf_put_be16(msg, cred->auth_type);
return 0; return 0;
} }
static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_encr_type(struct wpabuf *msg,
struct wps_credential *cred)
{ {
wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)",
wps->encr_type); cred->encr_type);
wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, 2);
wpabuf_put_be16(msg, wps->encr_type); wpabuf_put_be16(msg, cred->encr_type);
return 0; return 0;
} }
static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_network_key(struct wpabuf *msg,
struct wps_credential *cred)
{ {
wpa_printf(MSG_DEBUG, "WPS: * Network Key"); wpa_printf(MSG_DEBUG, "WPS: * Network Key");
wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap) { wpabuf_put_be16(msg, cred->key_len);
u8 r[16]; wpabuf_put_data(msg, cred->key, cred->key_len);
/* Generate a random passphrase */
if (os_get_random(r, sizeof(r)) < 0)
return -1;
os_free(wps->new_psk);
wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
wps->new_psk_len--; /* remove newline */
while (wps->new_psk_len &&
wps->new_psk[wps->new_psk_len - 1] == '=')
wps->new_psk_len--;
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
wps->new_psk, wps->new_psk_len);
wpabuf_put_be16(msg, wps->new_psk_len);
wpabuf_put_data(msg, wps->new_psk, wps->new_psk_len);
} else if (wps->wps->network_key) {
wpabuf_put_be16(msg, wps->wps->network_key_len);
wpabuf_put_data(msg, wps->wps->network_key,
wps->wps->network_key_len);
} else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
char hex[65];
/* Generate a random per-device PSK */
os_free(wps->new_psk);
wps->new_psk_len = 32;
wps->new_psk = os_malloc(wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) {
os_free(wps->new_psk);
wps->new_psk = NULL;
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
wps->new_psk, wps->new_psk_len);
wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
wps->new_psk_len);
wpabuf_put_be16(msg, wps->new_psk_len * 2);
wpabuf_put_data(msg, hex, wps->new_psk_len * 2);
} else {
/* No Network Key */
wpabuf_put_be16(msg, 0);
}
return 0; return 0;
} }
static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_mac_addr(struct wpabuf *msg,
struct wps_credential *cred)
{ {
wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); wpa_printf(MSG_DEBUG, "WPS: * MAC Address");
wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ATTR_MAC_ADDR);
wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_be16(msg, ETH_ALEN);
wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN);
return 0;
}
static int wps_build_credential(struct wpabuf *msg,
struct wps_credential *cred)
{
if (wps_build_cred_network_idx(msg, cred) ||
wps_build_cred_ssid(msg, cred) ||
wps_build_cred_auth_type(msg, cred) ||
wps_build_cred_encr_type(msg, cred) ||
wps_build_cred_network_key(msg, cred) ||
wps_build_cred_mac_addr(msg, cred))
return -1;
return 0; return 0;
} }
@ -865,14 +843,12 @@ static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
{ {
struct wpabuf *cred; struct wpabuf *cred;
int ap_settings;
ap_settings = !wps->wps->ap;
if (ap_settings)
wpa_printf(MSG_DEBUG, "WPS: * AP Settings");
else
wpa_printf(MSG_DEBUG, "WPS: * Credential"); wpa_printf(MSG_DEBUG, "WPS: * Credential");
os_memset(&wps->cred, 0, sizeof(wps->cred));
os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
wps->cred.ssid_len = wps->wps->ssid_len;
/* Select the best authentication and encryption type */ /* Select the best authentication and encryption type */
if (wps->auth_type & WPS_AUTH_WPA2PSK) if (wps->auth_type & WPS_AUTH_WPA2PSK)
@ -888,6 +864,7 @@ static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
wps->auth_type); wps->auth_type);
return -1; return -1;
} }
wps->cred.auth_type = wps->auth_type;
if (wps->auth_type == WPS_AUTH_WPA2PSK || if (wps->auth_type == WPS_AUTH_WPA2PSK ||
wps->auth_type == WPS_AUTH_WPAPSK) { wps->auth_type == WPS_AUTH_WPAPSK) {
@ -911,30 +888,75 @@ static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
return -1; return -1;
} }
} }
wps->cred.encr_type = wps->encr_type;
os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN);
if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap) {
u8 r[16];
/* Generate a random passphrase */
if (os_get_random(r, sizeof(r)) < 0)
return -1;
os_free(wps->new_psk);
wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
wps->new_psk_len--; /* remove newline */
while (wps->new_psk_len &&
wps->new_psk[wps->new_psk_len - 1] == '=')
wps->new_psk_len--;
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase",
wps->new_psk, wps->new_psk_len);
os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
wps->cred.key_len = wps->new_psk_len;
} else if (wps->wps->network_key) {
os_memcpy(wps->cred.key, wps->wps->network_key,
wps->wps->network_key_len);
wps->cred.key_len = wps->wps->network_key_len;
} else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
char hex[65];
/* Generate a random per-device PSK */
os_free(wps->new_psk);
wps->new_psk_len = 32;
wps->new_psk = os_malloc(wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) {
os_free(wps->new_psk);
wps->new_psk = NULL;
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
wps->new_psk, wps->new_psk_len);
wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk,
wps->new_psk_len);
os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2);
wps->cred.key_len = wps->new_psk_len * 2;
}
cred = wpabuf_alloc(200); cred = wpabuf_alloc(200);
if (cred == NULL) if (cred == NULL)
return -1; return -1;
if (wps_build_cred_network_idx(wps, cred) || if (wps_build_credential(cred, &wps->cred)) {
wps_build_cred_ssid(wps, cred) ||
wps_build_cred_auth_type(wps, cred) ||
wps_build_cred_encr_type(wps, cred) ||
wps_build_cred_network_key(wps, cred) ||
wps_build_cred_mac_addr(wps, cred)) {
wpabuf_free(cred); wpabuf_free(cred);
return -1; return -1;
} }
if (ap_settings) {
wpabuf_put_buf(msg, cred);
wpabuf_free(cred);
} else {
wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(cred)); wpabuf_put_be16(msg, wpabuf_len(cred));
wpabuf_put_buf(msg, cred); wpabuf_put_buf(msg, cred);
wpabuf_free(cred); wpabuf_free(cred);
}
return 0;
}
static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg)
{
wpa_printf(MSG_DEBUG, "WPS: * AP Settings");
if (wps_build_credential(msg, &wps->cred))
return -1;
return 0; return 0;
} }
@ -1106,7 +1128,8 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
if (wps_build_version(msg) || if (wps_build_version(msg) ||
wps_build_msg_type(msg, WPS_M8) || wps_build_msg_type(msg, WPS_M8) ||
wps_build_enrollee_nonce(wps, msg) || wps_build_enrollee_nonce(wps, msg) ||
wps_build_cred(wps, plain) || (wps->wps->ap && wps_build_cred(wps, plain)) ||
(!wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
wps_build_key_wrap_auth(wps, plain) || wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain) || wps_build_encr_settings(wps, msg, plain) ||
wps_build_authenticator(wps, msg)) { wps_build_authenticator(wps, msg)) {
@ -1659,13 +1682,11 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
static int wps_process_ap_settings_r(struct wps_data *wps, static int wps_process_ap_settings_r(struct wps_data *wps,
struct wps_parse_attr *attr) struct wps_parse_attr *attr)
{ {
struct wps_credential cred;
if (wps->wps->ap) if (wps->wps->ap)
return 0; return 0;
/* AP Settings Attributes in M7 when Enrollee is an AP */ /* AP Settings Attributes in M7 when Enrollee is an AP */
if (wps_process_ap_settings(attr, &cred) < 0) if (wps_process_ap_settings(attr, &wps->cred) < 0)
return -1; return -1;
wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP"); wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP");
@ -1674,17 +1695,6 @@ static int wps_process_ap_settings_r(struct wps_data *wps,
* TODO: Provide access to AP settings and allow changes before sending * TODO: Provide access to AP settings and allow changes before sending
* out M8. For now, just copy the settings unchanged into M8. * out M8. For now, just copy the settings unchanged into M8.
*/ */
wps->auth_type = cred.auth_type;
wps->encr_type = cred.encr_type;
os_memcpy(wps->wps->ssid, cred.ssid, cred.ssid_len);
wps->wps->ssid_len = cred.ssid_len;
os_memcpy(wps->mac_addr_e, cred.mac_addr, ETH_ALEN);
os_free(wps->wps->network_key);
wps->wps->network_key = os_malloc(cred.key_len);
if (wps->wps->network_key) {
os_memcpy(wps->wps->network_key, cred.key, cred.key_len);
wps->wps->network_key_len = cred.key_len;
}
return 0; return 0;
} }