{
struct p2p_pairing_info *pairing_info;
+ if (p2p->cfg->pairing_config.dik_len > DEVICE_IDENTITY_KEY_MAX_LEN)
+ return -1;
+
pairing_info = os_zalloc(sizeof(struct p2p_pairing_info));
if (!pairing_info)
return -1;
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_deinit(p2p);
p2p->pairing_info = pairing_info;
}
+static int p2p_derive_nonce_tag(struct p2p_data *p2p)
+{
+ 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_INFO,
+ "P2P: Unsupported DIRA Cipher version = %d",
+ dev_ik->cipher_version);
+ return -1;
+ }
+
+ if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) {
+ wpa_printf(MSG_INFO, "P2P: Invalid DIK length = %zu",
+ dev_ik->dik_len);
+ return -1;
+ }
+
+ os_memset(data, 0, sizeof(data));
+
+ if (os_get_random(dira_nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) {
+ wpa_printf(MSG_ERROR, "P2P: Failed to generate DIRA nonce");
+ return -1;
+ }
+
+ /* Tag = Truncate-64(HMAC-SHA-256(DevIK,
+ * "DIR" || P2P Device Address || Nonce))
+ */
+ 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);
+
+ if (hmac_sha256(dev_ik->dik_data, dev_ik->dik_len, data, sizeof(data),
+ dira_tag) < 0) {
+ wpa_printf(MSG_ERROR, "P2P: Could not derive DIRA tag");
+ 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;
+}
+
+
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
{
struct wpabuf *buf;
p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL,
0, 0);
+ /* P2P Device Identity Resolution attribute */
+ if (p2p->pairing_info &&
+ p2p->cfg->pairing_config.pairing_capable &&
+ p2p->cfg->pairing_config.enable_pairing_cache &&
+ p2p->cfg->pairing_config.enable_pairing_verification &&
+ p2p_derive_nonce_tag(p2p) == 0)
+ p2p_buf_add_dira(buf, p2p);
+
p2p_buf_update_ie_hdr(buf, len);
return buf;
#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 */
* Bitmap of supported PASN types
*/
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 in octets */
+ size_t dik_len;
};
/**
}
+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;
+
+ 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: * DIRA");
+}
+
+
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
const char *val)
{
struct wpabuf *tlvs;
};
+/* P2P Device Identity Key parameters */
+struct p2p_id_key {
+ /* AKMP used for DevIK derviation */
+ int akmp;
+ /* Cipher version type */
+ int cipher_version;
+ /* 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 in octets */
+ size_t dira_tag_len;
+};
+
struct p2p_pairing_info {
/* P2P device own address */
u8 own_addr[ETH_ALEN];
bool enable_pairing_cache;
/* device supported bootstrapping */
u16 supported_bootstrap;
+ /* P2P Device Identity Key info */
+ struct p2p_id_key dev_ik;
};
/**
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,