Add DIRA attribute in P2P2 IE of NAN Subscribe and Publish frames to enable support for Device identity of paired peers. Signed-off-by: Shivani Baranwal <quic_shivbara@xxxxxxxxxxx> --- src/p2p/p2p.c | 10 ++++++ src/p2p/p2p.h | 18 +++++++++++ src/p2p/p2p_build.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/p2p/p2p_i.h | 25 +++++++++++++++ 4 files changed, 141 insertions(+) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 2f9482a..73fcb16 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2987,6 +2987,13 @@ int p2p_pairing_info_init(struct p2p_data *p2p) pairing_info->supported_bootstrap = p2p->cfg->pairing_config.bootstrap_methods; + pairing_info->dev_ik.cipher_version = + p2p->cfg->pairing_config.dik_cipher; + pairing_info->dev_ik.dik_len = + p2p->cfg->pairing_config.dik_len; + os_memcpy(pairing_info->dev_ik.dik_data, + p2p->cfg->pairing_config.dik_data, + p2p->cfg->pairing_config.dik_len); p2p->pairing_info = pairing_info; return 0; @@ -5760,6 +5767,9 @@ struct wpabuf * p2p_usd_elems(struct p2p_data *p2p) p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL, 0, 0); + /* P2P Device Identity Resolution attribute */ + p2p_buf_add_dira(buf, p2p); + p2p_buf_update_p2p2_ie_hdr(buf, len); return buf; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 700f839..b7d05e9 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -12,6 +12,16 @@ #include "common/ieee802_11_defs.h" #include "wps/wps.h" +#define DEVICE_IDENTITY_KEY_MAX_LEN 64 +#define DEVICE_IDENTITY_KEY_LEN 16 +#define DEVICE_IDENTITY_TAG_LEN 8 +#define DEVICE_IDENTITY_NONCE_LEN 8 +#define DEVICE_MAX_HASH_LEN 32 +#define DIR_STR_LEN 3 + +/* DIRA Cipher versions */ +#define DIRA_CIPHER_VERSION_128 0 + struct weighted_pcl; /* P2P ASP Setup Capability */ @@ -354,6 +364,14 @@ struct p2p_pairing_config { */ u8 pasn_type; + /* cipher version type */ + int dik_cipher; + + /* buffer to hold the DevIK */ + u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN]; + + /* length of DevIK */ + size_t dik_len; }; diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index 4bdfb7e..347e8a1 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -12,6 +12,8 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/qca-vendor.h" +#include "crypto/random.h" +#include "crypto/sha256.h" #include "wps/wps_i.h" #include "p2p_i.h" @@ -803,6 +805,92 @@ void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, bootstrap); } +static int p2p_derive_nonce_tag(struct p2p_data *p2p) +{ + int ret; + u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN]; + u8 dira_tag[DEVICE_MAX_HASH_LEN]; + u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN]; + struct p2p_id_key *dev_ik; + + dev_ik = &p2p->pairing_info->dev_ik; + + if (dev_ik->cipher_version != DIRA_CIPHER_VERSION_128) { + wpa_printf(MSG_ERROR, "Unsupported DIRA Cipher version = %d", + dev_ik->cipher_version); + return -1; + } + + if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) { + wpa_printf(MSG_ERROR, "Invalid DIK length = %ld", + dev_ik->dik_len); + return -1; + } + + os_memset(data, 0, sizeof(data)); + os_memset(dira_tag, 0, sizeof(dira_tag)); + + ret = random_get_bytes(dira_nonce, DEVICE_IDENTITY_NONCE_LEN); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Get DIRA nonce Failed, err = %d", ret); + return -1; + } + + os_memcpy(data, "DIR", DIR_STR_LEN); + os_memcpy(&data[DIR_STR_LEN], p2p->cfg->dev_addr, ETH_ALEN); + os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], dira_nonce, + DEVICE_IDENTITY_NONCE_LEN); + + ret = hmac_sha256(dev_ik->dik_data, dev_ik->dik_len, data, sizeof(data), + dira_tag); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Could not derive DIRA tag, err = %d", ret); + return -1; + } + + dev_ik->dira_nonce_len = DEVICE_IDENTITY_NONCE_LEN; + os_memcpy(dev_ik->dira_nonce, dira_nonce, DEVICE_IDENTITY_NONCE_LEN); + dev_ik->dira_tag_len = DEVICE_IDENTITY_TAG_LEN; + os_memcpy(dev_ik->dira_tag, dira_tag, DEVICE_IDENTITY_TAG_LEN); + + wpa_hexdump_key(MSG_DEBUG, "P2P: DIK", dev_ik->dik_data, + dev_ik->dik_len); + wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-NONCE", dev_ik->dira_nonce, + dev_ik->dira_nonce_len); + wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-TAG", dev_ik->dira_tag, + dev_ik->dira_tag_len); + return 0; +} + +void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p) +{ + u8 *len; + struct p2p_id_key *dev_ik; + + if (!p2p->cfg->pairing_config.pairing_capable || + !p2p->cfg->pairing_config.enable_pairing_cache || + !p2p->cfg->pairing_config.enable_pairing_verification) + return; + + if (p2p_derive_nonce_tag(p2p)) + return; + + dev_ik = &p2p->pairing_info->dev_ik; + /* P2P DIRA */ + wpabuf_put_u8(buf, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION); + /* Length to be filled */ + len = wpabuf_put(buf, 2); + + wpabuf_put_u8(buf, dev_ik->cipher_version); + wpabuf_put_data(buf, dev_ik->dira_nonce, dev_ik->dira_nonce_len); + wpabuf_put_data(buf, dev_ik->dira_tag, dev_ik->dira_tag_len); + + /* Update attribute length */ + WPA_PUT_LE16(len, (u8 *)wpabuf_put(buf, 0) - len - 2); + + wpa_printf(MSG_DEBUG, "P2P: * Added DIRA"); +} + static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr, const char *val) { diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 381a02e..0879add 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -161,6 +161,28 @@ struct p2p_sd_query { }; +/* This is p2p device identity key params */ +struct p2p_id_key { + /* AKMP used for DevIK derviation */ + int akmp; + /* cipher version type */ + int cipher_version; + /* DevIK expiration time in seconds */ + u32 expiration; + /* buffer to hold the DevIK */ + u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN]; + /* length of DevIK */ + size_t dik_len; + /* nonce used in DIRA attribute */ + u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN]; + /* length of nonce */ + size_t dira_nonce_len; + /* tag computed for nonce using NIK */ + u8 dira_tag[DEVICE_IDENTITY_TAG_LEN]; + /* length of tag */ + size_t dira_tag_len; +}; + struct p2p_pairing_info { /* P2P device own address */ u8 own_addr[ETH_ALEN]; @@ -170,6 +192,8 @@ struct p2p_pairing_info { u32 enable_pairing_cache; /* device supported bootstrapping */ u16 supported_bootstrap; + /* p2p device identity key info */ + struct p2p_id_key dev_ik; }; /** @@ -807,6 +831,7 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr, void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p); void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie, size_t cookie_len, int comeback_after); +void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p); int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, int all_attr); void p2p_buf_add_pref_channel_list(struct wpabuf *buf, -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap