diff options
| author | Dmitry Shmidt <dimitrysh@google.com> | 2014-01-28 10:57:39 -0800 |
|---|---|---|
| committer | Dmitry Shmidt <dimitrysh@google.com> | 2014-01-28 11:02:20 -0800 |
| commit | cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50e (patch) | |
| tree | 454f4b5c08cbd7d8cd14a732784cfbf624806965 /src/wps | |
| parent | 1846323989242844f0e857458a8939fa5836429c (diff) | |
| download | android_external_wpa_supplicant_8-cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50e.tar.gz android_external_wpa_supplicant_8-cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50e.tar.bz2 android_external_wpa_supplicant_8-cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50e.zip | |
Cumulative patch from commit 2e988392436227c51002b573ee27a8cee37f70e9
2e98839 P2P: Disable DNS server from dnsmasq
c07f261 P2P NFC: Add script for connection handover with nfcpy
12288d8 WPS NFC: Protect nfcpy pretty print calls against exceptions
c209dd1 WPS NFC: nfcpy script to use new connection handover design
6202500 WPS NFC: Logging level configuration to wps-nfc.py and wps-ap-nfc.py
1f1b5b3 WPS NFC: Clean up nfcpy script no-wait operations
79ede5a WPS NFC: Validate ctrl_iface response before decoding it
ab1db08 WPS NFC: Use argparse in the nfcpy scripts
6f8fa6e WPS NFC: Update wps-nfc.py and wps-ap-nfc.py to use new nfcpy API
b56f6c8 P2P NFC: Add support for freq option in NFC ctrl_iface commands
91a6501 WPS NFC: Use BSSID and AP Channel from handover select
91226e0 WPS: Add testing option to corrupt public key hash
7312776 WPS NFC: add more debug prints for connection handover report
5cd4f66 WPS NFC: Use AP Channel information from credential container
d2f1837 WPS NFC: Add BSSID and AP channel info to Configuration Token
75dbf98 WPS-STRICT: Update valid Device Password ID and Config Error range
5cd4740 P2P NFC: WPA state machine config with driver-based BSS selection
8e9f53c P2P NFC: Static handover with NFC Tag on client
dd87677 P2P NFC: Enable own NFC Tag on GO Registrar
abe44e3 P2P NFC: Add GO info into handover message when in client role
23318be P2P NFC: Optimize join-a-group operation based on NFC information
86e3208 P2P NFC: Copy DH parameters to a separate group interface
d4b4d7f WPS NFC: Update DH keys for ER operations
ac08752 WPS NFC: Use pubkey mismatch config error from Enrollee
59b45d1 P2P NFC: Add processing of P2P client while NFC handover case
74df9ec P2P NFC: Do not try to join peer if both devices are already GO
201b0f5 P2P: Add test option to disable IP address assignment request
25ef852 P2P: Add support for IP address assignment in 4-way handshake
fdd48ff P2P NFC: Optimize GO Negotiation retries
c4f87a7 P2P NFC: Add NFC tag enabling for static handover
dd37a93 P2P NFC: Report handover select from tag for static handover
db6ae69 P2P NFC: Report connection handover as trigger for P2P
9358878 P2P NFC: Build connection handover messages
c00ab85 P2P NFC: Define WPS_NFC config method
0deab08 P2P NFC: Allow separate WPS/P2P IES to be parsed
fca9958 P2P NFC: Pass OOB Dev Password through P2P parser
ab9e344 P2P NFC: Pass OOB Device Password ID to P2P
5154689 P2P NFC: Add WPS attribute building for P2P NFC
01afd8d P2P NFC: Add NDEF helpers for P2P connection handover messages
9e323a2 P2P NFC: Add OOB GO Negotiation Channel attribute
14d8645 WPS NFC: Allow BSSID and channel to be included in handover select
50d1f89 NFC: Update WPS ER to use the new connection handover design
d950793 WPS NFC: Add support for wpa_supplicant AP/GO mode to use handover
fa4c298 WPS NFC: Process new style handover select
068cdb1 WPS NFC: New style connection handover select from AP/Registrar
3189ca0 WPS NFC: Add AP mode connection handover report
41f9ffb WPS NFC: Build new style carrier record for connection handover request
3f1639d WPS NFC: Split DH key generation to a separate function
9754917 WPS NFC: Update NFC connection handover design
34b6795 WPS NFC: Use abbreviated handshake if both PK hashes delivered OOB
57630e6 WPS: Preparations for allowing SSID filtering for provisioning step
5f45455 WPS NFC: Validate peer public key hash on Enrollee
ff40cd6 WPS NFC: Send M2D with config error 20 on pkhash mismatch
e435417 WPS: Remove Version attribute from NFC messages
72403ec WPS: Add builder functions for AP Channel and RF Bands attributes
ea43ad9 P2P: Make group operating channel available
9f7cd9a P2P: Split add-group-info into a helper function
253f2e3 P2P: Apply unsafe frequency rules to available channels
1682c62 Add a header file defining QCA OUI and vendor extensions
Change-Id: Ia7604d018e1ffb25e06bdc01ce258fc4a0569245
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'src/wps')
| -rw-r--r-- | src/wps/ndef.c | 90 | ||||
| -rw-r--r-- | src/wps/wps.c | 12 | ||||
| -rw-r--r-- | src/wps/wps.h | 30 | ||||
| -rw-r--r-- | src/wps/wps_attr_build.c | 47 | ||||
| -rw-r--r-- | src/wps/wps_attr_parse.c | 9 | ||||
| -rw-r--r-- | src/wps/wps_common.c | 258 | ||||
| -rw-r--r-- | src/wps/wps_defs.h | 8 | ||||
| -rw-r--r-- | src/wps/wps_dev_attr.c | 9 | ||||
| -rw-r--r-- | src/wps/wps_dev_attr.h | 1 | ||||
| -rw-r--r-- | src/wps/wps_enrollee.c | 50 | ||||
| -rw-r--r-- | src/wps/wps_er.c | 28 | ||||
| -rw-r--r-- | src/wps/wps_i.h | 5 | ||||
| -rw-r--r-- | src/wps/wps_registrar.c | 109 | ||||
| -rw-r--r-- | src/wps/wps_validate.c | 4 |
14 files changed, 531 insertions, 129 deletions
diff --git a/src/wps/ndef.c b/src/wps/ndef.c index 96685d2b..2b350647 100644 --- a/src/wps/ndef.c +++ b/src/wps/ndef.c @@ -30,6 +30,7 @@ struct ndef_record { }; static char wifi_handover_type[] = "application/vnd.wfa.wsc"; +static char p2p_handover_type[] = "application/vnd.wfa.p2p"; static int ndef_parse_record(const u8 *data, u32 size, struct ndef_record *record) @@ -170,85 +171,26 @@ struct wpabuf * ndef_build_wifi(const struct wpabuf *buf) } -struct wpabuf * ndef_build_wifi_hc(int begin) +static int p2p_filter(struct ndef_record *record) { - struct wpabuf *hc, *carrier; - - carrier = wpabuf_alloc(2 + os_strlen(wifi_handover_type)); - if (carrier == NULL) - return NULL; - wpabuf_put_u8(carrier, 0x02); /* Carrier Type Format */ - wpabuf_put_u8(carrier, os_strlen(wifi_handover_type)); - wpabuf_put_str(carrier, wifi_handover_type); - - hc = ndef_build_record((begin ? FLAG_MESSAGE_BEGIN : 0) | - FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "Hc", 2, - "0", 1, carrier); - wpabuf_free(carrier); - - return hc; + if (record->type_length != os_strlen(p2p_handover_type)) + return 0; + if (os_memcmp(record->type, p2p_handover_type, + os_strlen(p2p_handover_type)) != 0) + return 0; + return 1; } -struct wpabuf * ndef_build_wifi_hr(void) +struct wpabuf * ndef_parse_p2p(const struct wpabuf *buf) { - struct wpabuf *rn, *cr, *ac_payload, *ac, *hr_payload, *hr; - struct wpabuf *hc; - - rn = wpabuf_alloc(2); - if (rn == NULL) - return NULL; - wpabuf_put_be16(rn, os_random() & 0xffff); - - cr = ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_TNF_NFC_FORUM, "cr", 2, - NULL, 0, rn); - wpabuf_free(rn); - - if (cr == NULL) - return NULL; - - ac_payload = wpabuf_alloc(4); - if (ac_payload == NULL) { - wpabuf_free(cr); - return NULL; - } - wpabuf_put_u8(ac_payload, 0x01); /* Carrier Flags: CRS=1 "active" */ - wpabuf_put_u8(ac_payload, 0x01); /* Carrier Data Reference Length */ - wpabuf_put_u8(ac_payload, '0'); /* Carrier Data Reference: "0" */ - wpabuf_put_u8(ac_payload, 0); /* Aux Data Reference Count */ - - ac = ndef_build_record(FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "ac", 2, - NULL, 0, ac_payload); - wpabuf_free(ac_payload); - if (ac == NULL) { - wpabuf_free(cr); - return NULL; - } - - hr_payload = wpabuf_alloc(1 + wpabuf_len(cr) + wpabuf_len(ac)); - if (hr_payload == NULL) { - wpabuf_free(cr); - wpabuf_free(ac); - return NULL; - } - - wpabuf_put_u8(hr_payload, 0x12); /* Connection Handover Version 1.2 */ - wpabuf_put_buf(hr_payload, cr); - wpabuf_put_buf(hr_payload, ac); - wpabuf_free(cr); - wpabuf_free(ac); + return ndef_parse_records(buf, p2p_filter); +} - hr = ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_TNF_NFC_FORUM, "Hr", 2, - NULL, 0, hr_payload); - wpabuf_free(hr_payload); - if (hr == NULL) - return NULL; - hc = ndef_build_wifi_hc(0); - if (hc == NULL) { - wpabuf_free(hr); - return NULL; - } - - return wpabuf_concat(hr, hc); +struct wpabuf * ndef_build_p2p(const struct wpabuf *buf) +{ + return ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_MESSAGE_END | + FLAG_TNF_RFC2046, p2p_handover_type, + os_strlen(p2p_handover_type), NULL, 0, buf); } diff --git a/src/wps/wps.c b/src/wps/wps.c index 22d7eeaa..3d019f10 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -18,6 +18,7 @@ #ifdef CONFIG_WPS_TESTING int wps_version_number = 0x20; int wps_testing_dummy_cred = 0; +int wps_corrupt_pkhash = 0; #endif /* CONFIG_WPS_TESTING */ @@ -58,6 +59,10 @@ struct wps_data * wps_init(const struct wps_config *cfg) } #ifdef CONFIG_WPS_NFC + if (cfg->pin == NULL && + cfg->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) + data->dev_pw_id = cfg->dev_pw_id; + if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) { /* Keep AP PIN as alternative Device Password */ data->alt_dev_pw_id = data->dev_pw_id; @@ -133,6 +138,12 @@ struct wps_data * wps_init(const struct wps_config *cfg) data->use_psk_key = cfg->use_psk_key; data->pbc_in_m1 = cfg->pbc_in_m1; + if (cfg->peer_pubkey_hash) { + os_memcpy(data->peer_pubkey_hash, cfg->peer_pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN); + data->peer_pubkey_hash_set = 1; + } + return data; } @@ -168,7 +179,6 @@ void wps_deinit(struct wps_data *data) wps_device_data_free(&data->peer_dev); os_free(data->new_ap_settings); dh5_free(data->dh_ctx); - os_free(data->nfc_pw_token); os_free(data); } diff --git a/src/wps/wps.h b/src/wps/wps.h index 15137a8a..6ccce1a9 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -183,6 +183,11 @@ struct wps_config { * PBC with the AP. */ int pbc_in_m1; + + /** + * peer_pubkey_hash - Peer public key hash or %NULL if not known + */ + const u8 *peer_pubkey_hash; }; struct wps_data * wps_init(const struct wps_config *cfg); @@ -801,7 +806,8 @@ int wps_registrar_config_ap(struct wps_registrar *reg, struct wps_credential *cred); int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, const u8 *pubkey_hash, u16 pw_id, - const u8 *dev_pw, size_t dev_pw_len); + const u8 *dev_pw, size_t dev_pw_len, + int pk_hash_provided_oob); int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, const u8 *oob_dev_pw, size_t oob_dev_pw_len); @@ -815,7 +821,8 @@ unsigned int wps_generate_pin(void); int wps_pin_str_valid(const char *pin); void wps_free_pending_msgs(struct upnp_pending_message *msgs); -struct wpabuf * wps_get_oob_cred(struct wps_context *wps); +struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, + int channel); int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr); int wps_attr_text(struct wpabuf *data, char *buf, char *end); const char * wps_ei_str(enum wps_error_indication ei); @@ -839,6 +846,9 @@ struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, struct wps_credential *cred); struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, const u8 *addr); +struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, + struct wps_context *wps, const u8 *uuid, + const u8 *addr, struct wpabuf *pubkey); int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]); char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, @@ -850,15 +860,27 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, const struct wpabuf *dev_pw); struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, struct wpabuf *dev_pw); +int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey); struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, struct wpabuf **privkey, struct wpabuf **dev_pw); +struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey); +struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey, + const u8 *bssid, int freq); +struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey); +struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, + int nfc_dev_pw_id, + struct wpabuf *nfc_dh_pubkey, + struct wpabuf *nfc_dev_pw); /* ndef.c */ struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf); struct wpabuf * ndef_build_wifi(const struct wpabuf *buf); -struct wpabuf * ndef_build_wifi_hc(int begin); -struct wpabuf * ndef_build_wifi_hr(void); +struct wpabuf * ndef_parse_p2p(const struct wpabuf *buf); +struct wpabuf * ndef_build_p2p(const struct wpabuf *buf); #ifdef CONFIG_WPS_STRICT int wps_validate_beacon(const struct wpabuf *wps_ie); diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index 336246ea..62d0feb9 100644 --- a/src/wps/wps_attr_build.c +++ b/src/wps/wps_attr_build.c @@ -38,8 +38,15 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) wps->wps->dh_ctx = NULL; pubkey = wpabuf_dup(wps->wps->dh_pubkey); #ifdef CONFIG_WPS_NFC - } else if (wps->dev_pw_id >= 0x10 && wps->wps->ap && - wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) { + } else if ((wps->dev_pw_id >= 0x10 || + wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) && + (wps->wps->ap || + (wps->wps->ap_nfc_dh_pubkey && + wps->wps->ap_nfc_dev_pw_id == + DEV_PW_NFC_CONNECTION_HANDOVER && + wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) && + (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id || + wps->wps->ap_nfc_dh_pubkey)) { wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); if (wps->wps->ap_nfc_dh_privkey == NULL) { wpa_printf(MSG_DEBUG, @@ -392,6 +399,14 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, addr[0] = wpabuf_head(pubkey); hash_len = wpabuf_len(pubkey); sha256_vector(1, addr, &hash_len, pubkey_hash); +#ifdef CONFIG_WPS_TESTING + if (wps_corrupt_pkhash) { + wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash", + pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); + wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash"); + pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++; + } +#endif /* CONFIG_WPS_TESTING */ wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len); @@ -399,9 +414,11 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); wpabuf_put_be16(msg, dev_pw_id); - wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password", - dev_pw, dev_pw_len); - wpabuf_put_data(msg, dev_pw, dev_pw_len); + if (dev_pw) { + wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password", + dev_pw, dev_pw_len); + wpabuf_put_data(msg, dev_pw, dev_pw_len); + } return 0; } @@ -449,3 +466,23 @@ int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr) wpabuf_put_data(msg, addr, ETH_ALEN); return 0; } + + +int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands) +{ + wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", rf_bands); + wpabuf_put_be16(msg, ATTR_RF_BANDS); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, rf_bands); + return 0; +} + + +int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel) +{ + wpa_printf(MSG_DEBUG, "WPS: * AP Channel (%u)", ap_channel); + wpabuf_put_be16(msg, ATTR_AP_CHANNEL); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, ap_channel); + return 0; +} diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c index 3999b1b8..f4e2e385 100644 --- a/src/wps/wps_attr_parse.c +++ b/src/wps/wps_attr_parse.c @@ -263,10 +263,13 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, attr->dev_password_id = pos; break; case ATTR_OOB_DEVICE_PASSWORD: - if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + - WPS_OOB_DEVICE_PASSWORD_MIN_LEN || + if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 || len > WPS_OOB_PUBKEY_HASH_LEN + 2 + - WPS_OOB_DEVICE_PASSWORD_LEN) { + WPS_OOB_DEVICE_PASSWORD_LEN || + (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + + WPS_OOB_DEVICE_PASSWORD_MIN_LEN && + WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) != + DEV_PW_NFC_CONNECTION_HANDOVER)) { wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " "Password length %u", len); return -1; diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c index 4b431adc..abf3a4fc 100644 --- a/src/wps/wps_common.c +++ b/src/wps/wps_common.c @@ -9,6 +9,8 @@ #include "includes.h" #include "common.h" +#include "common/defs.h" +#include "common/ieee802_11_common.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "crypto/dh_group5.h" @@ -16,6 +18,7 @@ #include "crypto/sha256.h" #include "crypto/random.h" #include "wps_i.h" +#include "wps_dev_attr.h" void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, @@ -349,7 +352,8 @@ void wps_pbc_disable_event(struct wps_context *wps) #ifdef CONFIG_WPS_OOB -struct wpabuf * wps_get_oob_cred(struct wps_context *wps) +struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, + int channel) { struct wps_data data; struct wpabuf *plain; @@ -365,8 +369,10 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps) data.wps = wps; data.auth_type = wps->auth_types; data.encr_type = wps->encr_types; - if (wps_build_version(plain) || - wps_build_cred(&data, plain) || + if (wps_build_cred(&data, plain) || + (rf_band && wps_build_rf_bands_attr(plain, rf_band)) || + (channel && wps_build_ap_channel(plain, channel)) || + wps_build_mac_addr(plain, wps->dev.mac_addr) || wps_build_wfa_ext(plain, 0, NULL, 0)) { os_free(data.new_psk); wpabuf_free(plain); @@ -412,8 +418,7 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, if (data == NULL) return NULL; - if (wps_build_version(data) || - wps_build_oob_dev_pw(data, dev_pw_id, pubkey, + if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey, wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || wps_build_wfa_ext(data, 0, NULL, 0)) { wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " @@ -636,12 +641,36 @@ struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, } +int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey) +{ + struct wpabuf *priv = NULL, *pub = NULL; + void *dh_ctx; + + dh_ctx = dh5_init(&priv, &pub); + if (dh_ctx == NULL) + return -1; + pub = wpabuf_zeropad(pub, 192); + if (pub == NULL) { + wpabuf_free(priv); + return -1; + } + wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub); + dh5_free(dh_ctx); + + wpabuf_free(*pubkey); + *pubkey = pub; + wpabuf_free(*privkey); + *privkey = priv; + + return 0; +} + + struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, struct wpabuf **privkey, struct wpabuf **dev_pw) { - struct wpabuf *priv = NULL, *pub = NULL, *pw; - void *dh_ctx; + struct wpabuf *pw; u16 val; pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); @@ -655,22 +684,223 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, return NULL; } - dh_ctx = dh5_init(&priv, &pub); - if (dh_ctx == NULL) { + if (wps_nfc_gen_dh(pubkey, privkey) < 0) { wpabuf_free(pw); return NULL; } - dh5_free(dh_ctx); *id = 0x10 + val % 0xfff0; - wpabuf_free(*pubkey); - *pubkey = pub; - wpabuf_free(*privkey); - *privkey = priv; wpabuf_free(*dev_pw); *dev_pw = pw; return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw); } + +struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey) +{ + struct wpabuf *msg; + void *len; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover request"); + + if (nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " + "configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + len = wpabuf_put(msg, 2); + + if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, + nfc_dh_pubkey, NULL, 0) || + wps_build_uuid_e(msg, ctx->uuid) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + WPA_PUT_BE16(len, wpabuf_len(msg) - 2); + + return msg; +} + + +static int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps) +{ + wpa_printf(MSG_DEBUG, "WPS: * SSID"); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select", + wps->ssid, wps->ssid_len); + wpabuf_put_be16(msg, ATTR_SSID); + wpabuf_put_be16(msg, wps->ssid_len); + wpabuf_put_data(msg, wps->ssid, wps->ssid_len); + return 0; +} + + +static int wps_build_ap_freq(struct wpabuf *msg, int freq) +{ + enum hostapd_hw_mode mode; + u8 channel, rf_band; + u16 ap_channel; + + if (freq <= 0) + return 0; + + mode = ieee80211_freq_to_chan(freq, &channel); + if (mode == NUM_HOSTAPD_MODES) + return 0; /* Unknown channel */ + + if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B) + rf_band = WPS_RF_24GHZ; + else if (mode == HOSTAPD_MODE_IEEE80211A) + rf_band = WPS_RF_50GHZ; + else + return 0; /* Unknown band */ + ap_channel = channel; + + if (wps_build_rf_bands_attr(msg, rf_band) || + wps_build_ap_channel(msg, ap_channel)) + return -1; + + return 0; +} + + +struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey, + const u8 *bssid, int freq) +{ + struct wpabuf *msg; + void *len; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover select"); + + if (nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " + "configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + len = wpabuf_put(msg, 2); + + if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, + nfc_dh_pubkey, NULL, 0) || + wps_build_ssid(msg, ctx) || + wps_build_ap_freq(msg, freq) || + (bssid && wps_build_mac_addr(msg, bssid)) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + WPA_PUT_BE16(len, wpabuf_len(msg) - 2); + + return msg; +} + + +struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey) +{ + struct wpabuf *msg; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover request (P2P)"); + + if (nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + + if (wps_build_manufacturer(&ctx->dev, msg) || + wps_build_model_name(&ctx->dev, msg) || + wps_build_model_number(&ctx->dev, msg) || + wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, + nfc_dh_pubkey, NULL, 0) || + wps_build_rf_bands(&ctx->dev, msg, 0) || + wps_build_serial_number(&ctx->dev, msg) || + wps_build_uuid_e(msg, ctx->uuid) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + + +struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, + int nfc_dev_pw_id, + struct wpabuf *nfc_dh_pubkey, + struct wpabuf *nfc_dev_pw) +{ + struct wpabuf *msg; + const u8 *dev_pw; + size_t dev_pw_len; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover select (P2P)"); + + if (nfc_dh_pubkey == NULL || + (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && + nfc_dev_pw == NULL)) { + wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " + "configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + + if (nfc_dev_pw) { + dev_pw = wpabuf_head(nfc_dev_pw); + dev_pw_len = wpabuf_len(nfc_dev_pw); + } else { + dev_pw = NULL; + dev_pw_len = 0; + } + + if (wps_build_manufacturer(&ctx->dev, msg) || + wps_build_model_name(&ctx->dev, msg) || + wps_build_model_number(&ctx->dev, msg) || + wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey, + dev_pw, dev_pw_len) || + wps_build_rf_bands(&ctx->dev, msg, 0) || + wps_build_serial_number(&ctx->dev, msg) || + wps_build_uuid_e(msg, ctx->uuid) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + #endif /* CONFIG_WPS_NFC */ diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h index 3421ac5f..6f8a49f0 100644 --- a/src/wps/wps_defs.h +++ b/src/wps/wps_defs.h @@ -13,6 +13,7 @@ extern int wps_version_number; extern int wps_testing_dummy_cred; +extern int wps_corrupt_pkhash; #define WPS_VERSION wps_version_number #else /* CONFIG_WPS_TESTING */ @@ -155,7 +156,8 @@ enum wps_dev_password_id { DEV_PW_MACHINE_SPECIFIED = 0x0002, DEV_PW_REKEY = 0x0003, DEV_PW_PUSHBUTTON = 0x0004, - DEV_PW_REGISTRAR_SPECIFIED = 0x0005 + DEV_PW_REGISTRAR_SPECIFIED = 0x0005, + DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007 }; /* Message Type */ @@ -215,7 +217,9 @@ enum wps_config_error { WPS_CFG_SETUP_LOCKED = 15, WPS_CFG_MSG_TIMEOUT = 16, WPS_CFG_REG_SESS_TIMEOUT = 17, - WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 + WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18, + WPS_CFG_60G_CHAN_NOT_SUPPORTED = 19, + WPS_CFG_PUBLIC_KEY_HASH_MISMATCH = 20 }; /* Vendor specific Error Indication for WPS event messages */ diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c index fe736f32..0d01211a 100644 --- a/src/wps/wps_dev_attr.c +++ b/src/wps/wps_dev_attr.c @@ -85,8 +85,7 @@ int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg) } -static int wps_build_serial_number(struct wps_device_data *dev, - struct wpabuf *msg) +int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); @@ -220,11 +219,7 @@ int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg) int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg, u8 rf_band) { - wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); - wpabuf_put_be16(msg, ATTR_RF_BANDS); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, rf_band ? rf_band : dev->rf_bands); - return 0; + return wps_build_rf_bands_attr(msg, rf_band ? rf_band : dev->rf_bands); } diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h index f0169a79..c9034add 100644 --- a/src/wps/wps_dev_attr.h +++ b/src/wps/wps_dev_attr.h @@ -14,6 +14,7 @@ struct wps_parse_attr; int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 7b86ff7a..9d48ca51 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -514,6 +514,24 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, return -1; } + if (wps->peer_pubkey_hash_set) { + u8 hash[WPS_HASH_LEN]; + sha256_vector(1, &pk, &pk_len, hash); + if (os_memcmp(hash, wps->peer_pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN) != 0) { + wpa_printf(MSG_ERROR, "WPS: Public Key hash mismatch"); + wpa_hexdump(MSG_DEBUG, "WPS: Received public key", + pk, pk_len); + wpa_hexdump(MSG_DEBUG, "WPS: Calculated public key " + "hash", hash, WPS_OOB_PUBKEY_HASH_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: Expected public key hash", + wps->peer_pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN); + wps->config_error = WPS_CFG_PUBLIC_KEY_HASH_MISMATCH; + return -1; + } + } + wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_r == NULL) @@ -929,6 +947,38 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps, return WPS_CONTINUE; } +#ifdef CONFIG_WPS_NFC + if (wps->peer_pubkey_hash_set) { + struct wpabuf *decrypted; + struct wps_parse_attr eattr; + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt " + "Encrypted Settings attribute"); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted " + "Settings attribute"); + if (wps_parse_msg(decrypted, &eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, + eattr.key_wrap_auth) || + wps_process_creds(wps, eattr.cred, eattr.cred_len, + eattr.num_cred, attr->version2 != NULL)) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + wpabuf_free(decrypted); + + wps->state = WPS_MSG_DONE; + return WPS_CONTINUE; + } +#endif /* CONFIG_WPS_NFC */ + wps->state = SEND_M3; return WPS_CONTINUE; } diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index e729617c..8e9ee7a5 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -2040,8 +2040,7 @@ struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, os_memset(&data, 0, sizeof(data)); data.wps = wps; data.use_cred = cred; - if (wps_build_version(ret) || - wps_build_cred(&data, ret) || + if (wps_build_cred(&data, ret) || wps_build_wfa_ext(ret, 0, NULL, 0)) { wpabuf_free(ret); return NULL; @@ -2071,4 +2070,29 @@ struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, return wps_er_config_token_from_cred(er->wps, ap->ap_settings); } + +struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, + struct wps_context *wps, const u8 *uuid, + const u8 *addr, struct wpabuf *pubkey) +{ + struct wps_er_ap *ap; + + if (er == NULL) + return NULL; + + ap = wps_er_ap_get(er, NULL, uuid, addr); + if (ap == NULL) + return NULL; + if (ap->ap_settings == NULL) { + wpa_printf(MSG_DEBUG, "WPS ER: No settings known for the " + "selected AP"); + return NULL; + } + + os_memcpy(wps->ssid, ap->ap_settings->ssid, ap->ap_settings->ssid_len); + wps->ssid_len = ap->ap_settings->ssid_len; + + return wps_build_nfc_handover_sel(wps, pubkey, addr, 0); +} + #endif /* CONFIG_WPS_NFC */ diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index dac12508..22070db9 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -75,6 +75,9 @@ struct wps_data { size_t alt_dev_password_len; u16 alt_dev_pw_id; + u8 peer_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + int peer_pubkey_hash_set; + /** * request_type - Request Type attribute from (Re)AssocReq */ @@ -173,6 +176,8 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, size_t dev_pw_len); struct wpabuf * wps_ie_encapsulate(struct wpabuf *data); int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr); +int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands); +int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel); /* wps_attr_process.c */ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 19490a15..6d879be2 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -31,9 +31,11 @@ struct wps_nfc_pw_token { struct dl_list list; u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + unsigned int peer_pk_hash_known:1; u16 pw_id; u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1]; size_t dev_pw_len; + int pk_hash_provided_oob; /* whether own PK hash was provided OOB */ }; @@ -1360,10 +1362,23 @@ static int wps_get_dev_password(struct wps_data *wps) pin_len = 8; #ifdef CONFIG_WPS_NFC } else if (wps->nfc_pw_token) { + if (wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) + { + wpa_printf(MSG_DEBUG, "WPS: Using NFC connection " + "handover and abbreviated WPS handshake " + "without Device Password"); + return 0; + } wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC " "Password Token"); pin = wps->nfc_pw_token->dev_pw; pin_len = wps->nfc_pw_token->dev_pw_len; + } else if (wps->dev_pw_id >= 0x10 && + wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id && + wps->wps->ap_nfc_dev_pw) { + wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from own NFC Password Token"); + pin = wpabuf_head(wps->wps->ap_nfc_dev_pw); + pin_len = wpabuf_len(wps->wps->ap_nfc_dev_pw); #endif /* CONFIG_WPS_NFC */ } else { pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, @@ -1777,6 +1792,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps) static struct wpabuf * wps_build_m2(struct wps_data *wps) { struct wpabuf *msg; + int config_in_m2 = 0; if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0) return NULL; @@ -1807,14 +1823,41 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps) wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0) || - wps_build_authenticator(wps, msg)) { + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + +#ifdef CONFIG_WPS_NFC + if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob && + wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) { + /* + * Use abbreviated handshake since public key hash allowed + * Enrollee to validate our public key similarly to how Enrollee + * public key was validated. There is no need to validate Device + * Password in this case. + */ + struct wpabuf *plain = wpabuf_alloc(500); + if (plain == NULL || + wps_build_cred(wps, plain) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain)) { + wpabuf_free(msg); + wpabuf_free(plain); + return NULL; + } + wpabuf_free(plain); + config_in_m2 = 1; + } +#endif /* CONFIG_WPS_NFC */ + + if (wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->int_reg = 1; - wps->state = RECV_M3; + wps->state = config_in_m2 ? RECV_DONE : RECV_M3; return msg; } @@ -2528,6 +2571,9 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, wps->dev_pw_id != DEV_PW_USER_SPECIFIED && wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED && wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED && +#ifdef CONFIG_WPS_NFC + wps->dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && +#endif /* CONFIG_WPS_NFC */ (wps->dev_pw_id != DEV_PW_PUSHBUTTON || !wps->wps->registrar->pbc)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", @@ -2537,7 +2583,8 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, } #ifdef CONFIG_WPS_NFC - if (wps->dev_pw_id >= 0x10) { + if (wps->dev_pw_id >= 0x10 || + wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) { struct wps_nfc_pw_token *token; const u8 *addr[1]; u8 hash[WPS_HASH_LEN]; @@ -2546,7 +2593,7 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, wps->dev_pw_id, wps->wps, wps->wps->registrar); token = wps_get_nfc_pw_token( &wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id); - if (token) { + if (token && token->peer_pk_hash_known) { wpa_printf(MSG_DEBUG, "WPS: Found matching NFC " "Password Token"); dl_list_del(&token->list); @@ -2558,8 +2605,19 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, WPS_OOB_PUBKEY_HASH_LEN) != 0) { wpa_printf(MSG_ERROR, "WPS: Public Key hash " "mismatch"); - return WPS_FAILURE; + wps->state = SEND_M2D; + wps->config_error = + WPS_CFG_PUBLIC_KEY_HASH_MISMATCH; + return WPS_CONTINUE; } + } else if (token) { + wpa_printf(MSG_DEBUG, "WPS: Found matching NFC " + "Password Token (no peer PK hash)"); + wps->nfc_pw_token = token; + } else if (wps->dev_pw_id >= 0x10 && + wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id && + wps->wps->ap_nfc_dev_pw) { + wpa_printf(MSG_DEBUG, "WPS: Found match with own NFC Password Token"); } } #endif /* CONFIG_WPS_NFC */ @@ -3493,25 +3551,39 @@ int wps_registrar_config_ap(struct wps_registrar *reg, int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, const u8 *pubkey_hash, u16 pw_id, - const u8 *dev_pw, size_t dev_pw_len) + const u8 *dev_pw, size_t dev_pw_len, + int pk_hash_provided_oob) { struct wps_nfc_pw_token *token; if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN) return -1; + if (pw_id == DEV_PW_NFC_CONNECTION_HANDOVER && + (pubkey_hash == NULL || !pk_hash_provided_oob)) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected NFC Password Token " + "addition - missing public key hash"); + return -1; + } + wps_free_nfc_pw_tokens(®->nfc_pw_tokens, pw_id); token = os_zalloc(sizeof(*token)); if (token == NULL) return -1; - os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); + token->peer_pk_hash_known = pubkey_hash != NULL; + if (pubkey_hash) + os_memcpy(token->pubkey_hash, pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN); token->pw_id = pw_id; - wpa_snprintf_hex_uppercase((char *) token->dev_pw, - sizeof(token->dev_pw), - dev_pw, dev_pw_len); - token->dev_pw_len = dev_pw_len * 2; + token->pk_hash_provided_oob = pk_hash_provided_oob; + if (dev_pw) { + wpa_snprintf_hex_uppercase((char *) token->dev_pw, + sizeof(token->dev_pw), + dev_pw, dev_pw_len); + token->dev_pw_len = dev_pw_len * 2; + } dl_list_add(®->nfc_pw_tokens, &token->list); @@ -3540,8 +3612,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, u16 id; size_t dev_pw_len; - if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 + - WPS_OOB_DEVICE_PASSWORD_MIN_LEN || + if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 || oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 + WPS_OOB_DEVICE_PASSWORD_LEN) return -1; @@ -3560,7 +3631,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len); return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw, - dev_pw_len); + dev_pw_len, 0); } @@ -3570,6 +3641,14 @@ void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, wps_registrar_remove_authorized_mac(reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); wps_registrar_selected_registrar_changed(reg, 0); + + /* + * Free the NFC password token if it was used only for a single protocol + * run. The static handover case uses the same password token multiple + * times, so do not free that case here. + */ + if (token->peer_pk_hash_known) + os_free(token); } #endif /* CONFIG_WPS_NFC */ diff --git a/src/wps/wps_validate.c b/src/wps/wps_validate.c index e3662562..1c6a14bc 100644 --- a/src/wps/wps_validate.c +++ b/src/wps/wps_validate.c @@ -267,7 +267,7 @@ static int wps_validate_config_error(const u8 *config_error, int mandatory) return 0; } val = WPA_GET_BE16(config_error); - if (val > 18) { + if (val > 20) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration Error " "attribute value 0x%04x", val); return -1; @@ -290,7 +290,7 @@ static int wps_validate_dev_password_id(const u8 *dev_password_id, return 0; } val = WPA_GET_BE16(dev_password_id); - if (val >= 0x0006 && val <= 0x000f) { + if (val >= 0x0008 && val <= 0x000f) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Device Password ID " "attribute value 0x%04x", val); return -1; |
