Signed-off-by: Peddolla Harshavardhan Reddy <peddolla@xxxxxxxxxxxxxxxx> --- src/common/proximity_ranging.c | 85 ++++++++++++++++++++++++++++++++++ src/common/proximity_ranging.h | 22 +++++++++ 2 files changed, 107 insertions(+) diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c index 18701646b..33478bac3 100644 --- a/src/common/proximity_ranging.c +++ b/src/common/proximity_ranging.c @@ -14,6 +14,10 @@ #include "common/qca-vendor.h" #include "wps/wps_i.h" #include "proximity_ranging.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "crypto/crypto.h" + static void pr_device_free(struct pr_data *pr, struct pr_device *dev) { @@ -213,6 +217,62 @@ static void pr_get_ntb_capabilities(struct pr_data *pr, } +static int pr_derive_dira(struct pr_data *pr, struct pr_dira *dira) +{ + u8 nonce[DEVICE_IDENTITY_NONCE_LEN]; + u8 tag[DEVICE_MAX_HASH_LEN]; + u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN]; + + if (pr->cfg->dik_cipher != DIRA_CIPHER_VERSION_128) { + wpa_printf(MSG_ERROR, + "PR: Unsupported DIRA Cipher version = %d", + pr->cfg->dik_cipher); + return -1; + } + + if (pr->cfg->dik_len != DEVICE_IDENTITY_KEY_LEN) { + wpa_printf(MSG_ERROR, + "PR: Invalid DIK length = %zu", pr->cfg->dik_len); + return -1; + } + + os_memset(data, 0, sizeof(data)); + + if (os_get_random(nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) { + wpa_printf(MSG_ERROR, "PR: Failed to generate DIRA nonce"); + return -1; + } + + /* Tag = Truncate-64(HMAC-SHA-256(DevIK, "DIR" || PR Device Address || + * Nonce)) + */ + os_memcpy(data, "DIR", DIR_STR_LEN); + os_memcpy(&data[DIR_STR_LEN], pr->cfg->dev_addr, ETH_ALEN); + os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], nonce, + DEVICE_IDENTITY_NONCE_LEN); + + if (hmac_sha256(pr->cfg->dik_data, pr->cfg->dik_len, data, sizeof(data), + tag) < 0) { + wpa_printf(MSG_ERROR, "PR: Could not derive DIRA tag"); + return -1; + } + + os_memset(dira, 0, sizeof(struct pr_dira)); + dira->cipher_version = pr->cfg->dik_cipher; + dira->nonce_len = DEVICE_IDENTITY_NONCE_LEN; + os_memcpy(dira->nonce, nonce, DEVICE_IDENTITY_NONCE_LEN); + dira->tag_len = DEVICE_IDENTITY_TAG_LEN; + os_memcpy(dira->tag, tag, DEVICE_IDENTITY_TAG_LEN); + + wpa_hexdump_key(MSG_DEBUG, "PR: DIK", pr->cfg->dik_data, + pr->cfg->dik_len); + wpa_hexdump_key(MSG_DEBUG, "PR: DIRA-NONCE", dira->nonce, + dira->nonce_len); + wpa_hexdump_key(MSG_DEBUG, "PR: DIRA-TAG", dira->tag, dira->tag_len); + return 0; +} + + static void pr_buf_add_channel_list(struct wpabuf *buf, const char *country, struct pr_channels *chan) { @@ -327,6 +387,26 @@ static void pr_buf_add_ntb_capa_info(struct wpabuf *buf, } +static void pr_buf_add_dira(struct wpabuf *buf, struct pr_dira *dira) +{ + u8 *len; + + wpabuf_put_u8(buf, PR_ATTR_DEVICE_IDENTITY_RESOLUTION); + + /* Length to be filled */ + len = wpabuf_put(buf, 2); + + wpabuf_put_u8(buf, dira->cipher_version); + wpabuf_put_data(buf, dira->nonce, dira->nonce_len); + wpabuf_put_data(buf, dira->tag, dira->tag_len); + + /* Update attribute length */ + WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); + + wpa_printf(MSG_DEBUG, "PR: * DIRA"); +} + + struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country) { u32 ie_type; @@ -334,6 +414,7 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country) struct pr_capabilities pr_caps; struct edca_capabilities edca_caps; struct ntb_capabilities ntb_caps; + struct pr_dira dira; buf = wpabuf_alloc(1000); if (!buf) @@ -352,6 +433,10 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country) pr_buf_add_ntb_capa_info(buf, &ntb_caps); } + /* PR Device Identity Resolution attribute */ + if (!pr_derive_dira(pr, &dira)) + pr_buf_add_dira(buf, &dira); + ie_type = (OUI_WFA << 8) | PR_OUI_TYPE; buf2 = pr_encaps_ie(buf, ie_type); wpabuf_free(buf); diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h index d2847b62e..cbd7a7ef8 100644 --- a/src/common/proximity_ranging.h +++ b/src/common/proximity_ranging.h @@ -14,6 +14,13 @@ #include "drivers/driver.h" #define DEVICE_IDENTITY_KEY_LEN 16 +#define DEVICE_IDENTITY_TAG_LEN 8 +#define DEVICE_IDENTITY_NONCE_LEN 8 +#define DIR_STR_LEN 3 +#define DEVICE_MAX_HASH_LEN 32 + +/* DIRA Cipher versions */ +#define DIRA_CIPHER_VERSION_128 0 /** * P2P_MAX_REG_CLASSES - Maximum number of regulatory classes @@ -261,6 +268,21 @@ struct pr_data { struct dl_list devices; }; + +/* PR Device Identity Resolution Attribute parameters */ +struct pr_dira { + /* Cipher version type */ + int cipher_version; + /* Nonce used in DIRA attribute */ + u8 nonce[DEVICE_IDENTITY_NONCE_LEN]; + /* Length of nonce */ + size_t nonce_len; + /* Tag computed for nonce using NIK */ + u8 tag[DEVICE_IDENTITY_TAG_LEN]; + /* Length of tag in octets */ + size_t tag_len; +}; + struct pr_data * pr_init(const struct pr_config *cfg); void pr_deinit(struct pr_data *pr); struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country); -- 2.34.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap