aboutsummaryrefslogtreecommitdiffstats
path: root/src/wps
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-11-29 10:11:56 (GMT)
committerJouni Malinen <j@w1.fi>2008-11-29 10:11:56 (GMT)
commiteb76b7e3ffea75035836aa2313c3c69b60c2ac34 (patch)
tree173617da4dac74651ad392992c1f3a61356abd72 /src/wps
parente9ab39b4446e10fe3502c741973ba36ec45de7c4 (diff)
downloadhostap-06-eb76b7e3ffea75035836aa2313c3c69b60c2ac34.zip
hostap-06-eb76b7e3ffea75035836aa2313c3c69b60c2ac34.tar.gz
hostap-06-eb76b7e3ffea75035836aa2313c3c69b60c2ac34.tar.bz2
WPS: Parse Request Type from WPS IE in (Re)AssocReq and derive mgmt keys
WPS IE is now passed from hostapd association processing into EAP-WSC and WPS processing. Request Type attribute is parsed from this information and if the request is for a WLAN Manager Registrar, additional management keys are derived (to be used with UPnP).
Diffstat (limited to 'src/wps')
-rw-r--r--src/wps/wps.c18
-rw-r--r--src/wps/wps.h1
-rw-r--r--src/wps/wps_common.c71
-rw-r--r--src/wps/wps_defs.h3
-rw-r--r--src/wps/wps_enrollee.c9
-rw-r--r--src/wps/wps_i.h9
6 files changed, 100 insertions, 11 deletions
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 2b3751d..8dbab5e 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -60,6 +60,24 @@ struct wps_data * wps_init(const struct wps_config *cfg)
data->state = data->registrar ? RECV_M1 : SEND_M1;
+ if (cfg->assoc_wps_ie) {
+ struct wps_parse_attr attr;
+ wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq",
+ cfg->assoc_wps_ie);
+ if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) {
+ wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE "
+ "from (Re)AssocReq");
+ } else if (attr.request_type == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute "
+ "in (Re)AssocReq WPS IE");
+ } else {
+ wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE "
+ "in (Re)AssocReq WPS IE): %d",
+ *attr.request_type);
+ data->request_type = *attr.request_type;
+ }
+ }
+
return data;
}
diff --git a/src/wps/wps.h b/src/wps/wps.h
index 0d08e1a..e206c2d 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -47,6 +47,7 @@ struct wps_config {
size_t pin_len;
const u8 *uuid; /* 128-bit Enrollee UUID (NULL for Registrar) */
int pbc;
+ const struct wpabuf *assoc_wps_ie; /* (Re)AssocReq WPS IE (in AP) */
};
struct wps_data * wps_init(const struct wps_config *cfg);
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 1a4ae03..64f0a4d 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -433,11 +433,12 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
}
-void wps_kdf(const u8 *key, const char *label, u8 *res, size_t res_len)
+void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
+ const char *label, u8 *res, size_t res_len)
{
u8 i_buf[4], key_bits[4];
- const u8 *addr[3];
- size_t len[3];
+ const u8 *addr[4];
+ size_t len[4];
int i, iter;
u8 hash[SHA256_MAC_LEN], *opos;
size_t left;
@@ -446,10 +447,12 @@ void wps_kdf(const u8 *key, const char *label, u8 *res, size_t res_len)
addr[0] = i_buf;
len[0] = sizeof(i_buf);
- addr[1] = (const u8 *) label;
- len[1] = os_strlen(label);
- addr[2] = key_bits;
- len[2] = sizeof(key_bits);
+ addr[1] = label_prefix;
+ len[1] = label_prefix_len;
+ addr[2] = (const u8 *) label;
+ len[2] = os_strlen(label);
+ addr[3] = key_bits;
+ len[3] = sizeof(key_bits);
iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN;
opos = res;
@@ -457,7 +460,7 @@ void wps_kdf(const u8 *key, const char *label, u8 *res, size_t res_len)
for (i = 1; i <= iter; i++) {
WPA_PUT_BE32(i_buf, i);
- hmac_sha256_vector(key, SHA256_MAC_LEN, 3, addr, len, hash);
+ hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash);
if (i < iter) {
os_memcpy(opos, hash, SHA256_MAC_LEN);
opos += SHA256_MAC_LEN;
@@ -545,7 +548,7 @@ int wps_derive_keys(struct wps_data *wps)
hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk);
wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk));
- wps_kdf(kdk, "Wi-Fi Easy and Secure Key Derivation",
+ wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation",
keys, sizeof(keys));
os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN);
os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN);
@@ -562,6 +565,56 @@ int wps_derive_keys(struct wps_data *wps)
}
+int wps_derive_mgmt_keys(struct wps_data *wps)
+{
+ u8 nonces[2 * WPS_NONCE_LEN];
+ u8 keys[WPS_MGMTAUTHKEY_LEN + WPS_MGMTENCKEY_LEN];
+ u8 hash[SHA256_MAC_LEN];
+ const u8 *addr[2];
+ size_t len[2];
+ const char *auth_label = "WFA-WLAN-Management-MgmtAuthKey";
+ const char *enc_label = "WFA-WLAN-Management-MgmtEncKey";
+
+ /* MgmtAuthKey || MgmtEncKey =
+ * kdf(EMSK, N1 || N2 || "WFA-WLAN-Management-Keys", 384) */
+ os_memcpy(nonces, wps->nonce_e, WPS_NONCE_LEN);
+ os_memcpy(nonces + WPS_NONCE_LEN, wps->nonce_r, WPS_NONCE_LEN);
+ wps_kdf(wps->emsk, nonces, sizeof(nonces), "WFA-WLAN-Management-Keys",
+ keys, sizeof(keys));
+ os_memcpy(wps->mgmt_auth_key, keys, WPS_MGMTAUTHKEY_LEN);
+ os_memcpy(wps->mgmt_enc_key, keys + WPS_MGMTAUTHKEY_LEN,
+ WPS_MGMTENCKEY_LEN);
+
+ addr[0] = nonces;
+ len[0] = sizeof(nonces);
+
+ /* MgmtEncKeyID = first 128 bits of
+ * SHA-256(N1 || N2 || "WFA-WLAN-Management-MgmtAuthKey") */
+ addr[1] = (const u8 *) auth_label;
+ len[1] = os_strlen(auth_label);
+ sha256_vector(2, addr, len, hash);
+ os_memcpy(wps->mgmt_auth_key_id, hash, WPS_MGMT_KEY_ID_LEN);
+
+ /* MgmtEncKeyID = first 128 bits of
+ * SHA-256(N1 || N2 || "WFA-WLAN-Management-MgmtEncKey") */
+ addr[1] = (const u8 *) enc_label;
+ len[1] = os_strlen(enc_label);
+ sha256_vector(2, addr, len, hash);
+ os_memcpy(wps->mgmt_enc_key_id, hash, WPS_MGMT_KEY_ID_LEN);
+
+ wpa_hexdump_key(MSG_DEBUG, "WPS: MgmtAuthKey",
+ wps->mgmt_auth_key, WPS_MGMTAUTHKEY_LEN);
+ wpa_hexdump(MSG_DEBUG, "WPS: MgmtAuthKeyID",
+ wps->mgmt_auth_key_id, WPS_MGMT_KEY_ID_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "WPS: MgmtEncKey",
+ wps->mgmt_enc_key, WPS_MGMTENCKEY_LEN);
+ wpa_hexdump(MSG_DEBUG, "WPS: MgmtEncKeyID",
+ wps->mgmt_enc_key_id, WPS_MGMT_KEY_ID_LEN);
+
+ return 0;
+}
+
+
int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg)
{
u8 hash[SHA256_MAC_LEN];
diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h
index 141efba..bf6ccc5 100644
--- a/src/wps/wps_defs.h
+++ b/src/wps/wps_defs.h
@@ -30,6 +30,9 @@
#define WPS_SECRET_NONCE_LEN 16
#define WPS_HASH_LEN 32
#define WPS_KWA_LEN 8
+#define WPS_MGMTAUTHKEY_LEN 32
+#define WPS_MGMTENCKEY_LEN 16
+#define WPS_MGMT_KEY_ID_LEN 16
/* Attribute Types */
enum wps_attribute {
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index d89ca3d..4a0058a 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -553,7 +553,14 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
if (wps->dh_pubkey_r == NULL)
return -1;
- return wps_derive_keys(wps);
+ 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;
}
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 8d6242b..7f5f5ea 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -56,6 +56,10 @@ struct wps_data {
u8 authkey[WPS_AUTHKEY_LEN];
u8 keywrapkey[WPS_KEYWRAPKEY_LEN];
u8 emsk[WPS_EMSK_LEN];
+ u8 mgmt_auth_key[WPS_MGMTAUTHKEY_LEN];
+ u8 mgmt_auth_key_id[WPS_MGMT_KEY_ID_LEN];
+ u8 mgmt_enc_key[WPS_MGMTENCKEY_LEN];
+ u8 mgmt_enc_key_id[WPS_MGMT_KEY_ID_LEN];
struct wpabuf *last_msg;
@@ -63,6 +67,7 @@ struct wps_data {
size_t dev_password_len;
u16 dev_pw_id;
int pbc;
+ u8 request_type; /* Request Type attribute from (Re)AssocReq */
u16 encr_type; /* available encryption types */
u16 auth_type; /* available authentication types */
@@ -151,9 +156,11 @@ struct wps_parse_attr {
/* wps_common.c */
int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr);
-void wps_kdf(const u8 *key, const char *label, u8 *res, size_t res_len);
+void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
+ const char *label, u8 *res, size_t res_len);
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg);
int wps_derive_keys(struct wps_data *wps);
+int wps_derive_mgmt_keys(struct wps_data *wps);
int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg);
int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
const struct wpabuf *msg);