DPP3: Push button bootstrap mechanism

Add support to use a push button -based bootstrap mechanism with DPP.
The new DPP_PUSH_BUTTON control interface command enables this mode on
the AP/hostapd and station/wpa_supplicant. This goes through the
following sequence of events: a suitable peer in active push button mode
is discovered with session overlap detection, PKEX is executed with
bootstrap key hash validation, DPP authentication and configuration
exchanges are performed.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-07-06 17:11:12 +03:00 committed by Jouni Malinen
parent a0054fe7ca
commit 37bccfcab8
17 changed files with 1047 additions and 29 deletions

View file

@ -4950,3 +4950,64 @@ void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
}
#endif /* CONFIG_DPP2 */
#ifdef CONFIG_DPP3
struct wpabuf * dpp_build_pb_announcement(struct dpp_bootstrap_info *bi)
{
struct wpabuf *msg;
wpa_printf(MSG_DEBUG,
"DPP: Build Push Button Presence Announcement frame");
msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT,
4 + SHA256_MAC_LEN);
if (!msg)
return NULL;
/* Responder Bootstrapping Key Hash */
dpp_build_attr_r_bootstrap_key_hash(msg, bi->pubkey_hash_chirp);
wpa_hexdump_buf(MSG_DEBUG,
"DPP: Push Button Presence Announcement frame attributes",
msg);
return msg;
}
struct wpabuf * dpp_build_pb_announcement_resp(struct dpp_bootstrap_info *bi,
const u8 *e_hash,
const u8 *c_nonce,
size_t c_nonce_len)
{
struct wpabuf *msg;
wpa_printf(MSG_DEBUG,
"DPP: Build Push Button Presence Announcement Response frame");
msg = dpp_alloc_msg(DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP,
2 * (4 + SHA256_MAC_LEN) + 4 + c_nonce_len);
if (!msg)
return NULL;
/* Initiator Bootstrapping Key Hash */
wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash");
wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
wpabuf_put_le16(msg, SHA256_MAC_LEN);
wpabuf_put_data(msg, bi->pubkey_hash_chirp, SHA256_MAC_LEN);
/* Responder Bootstrapping Key Hash */
dpp_build_attr_r_bootstrap_key_hash(msg, e_hash);
/* Configurator Nonce */
wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE);
wpabuf_put_le16(msg, c_nonce_len);
wpabuf_put_data(msg, c_nonce, c_nonce_len);
wpa_hexdump_buf(MSG_DEBUG,
"DPP: Push Button Presence Announcement Response frame attributes",
msg);
return msg;
}
#endif /* CONFIG_DPP3 */

View file

@ -56,6 +56,8 @@ enum dpp_public_action_frame_type {
DPP_PA_RECONFIG_AUTH_RESP = 16,
DPP_PA_RECONFIG_AUTH_CONF = 17,
DPP_PA_PKEX_EXCHANGE_REQ = 18,
DPP_PA_PB_PRESENCE_ANNOUNCEMENT = 19,
DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP = 20,
};
enum dpp_attribute_id {
@ -203,6 +205,7 @@ struct dpp_pkex {
u8 peer_mac[ETH_ALEN];
char *identifier;
char *code;
size_t code_len;
struct crypto_ec_key *x;
struct crypto_ec_key *y;
u8 Mx[DPP_MAX_SHARED_SECRET_LEN];
@ -644,13 +647,13 @@ int dpp_get_connector_version(const char *connector);
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
const u8 *own_mac,
const char *identifier, const char *code,
bool v2);
size_t code_len, bool v2);
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
struct dpp_bootstrap_info *bi,
const u8 *own_mac,
const u8 *peer_mac,
const char *identifier,
const char *code,
const char *code, size_t code_len,
const u8 *buf, size_t len, bool v2);
struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
const u8 *peer_mac,
@ -759,6 +762,12 @@ struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi);
void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
unsigned int freq, const u8 *hash);
struct wpabuf * dpp_build_pb_announcement(struct dpp_bootstrap_info *bi);
struct wpabuf * dpp_build_pb_announcement_resp(struct dpp_bootstrap_info *bi,
const u8 *e_hash,
const u8 *c_nonce,
size_t c_nonce_len);
struct dpp_global_config {
void *cb_ctx;
void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);

View file

@ -1437,7 +1437,7 @@ dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init)
struct crypto_ec_point *
dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
const char *code, const char *identifier,
const char *code, size_t code_len, const char *identifier,
struct crypto_ec **ret_ec)
{
u8 hash[DPP_MAX_HASH_LEN];
@ -1465,9 +1465,9 @@ dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
len[num_elem] = os_strlen(identifier);
num_elem++;
}
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
addr[num_elem] = (const u8 *) code;
len[num_elem] = os_strlen(code);
len[num_elem] = code_len;
num_elem++;
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
goto fail;
@ -1512,7 +1512,7 @@ fail:
struct crypto_ec_point *
dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
const char *code, const char *identifier,
const char *code, size_t code_len, const char *identifier,
struct crypto_ec **ret_ec)
{
u8 hash[DPP_MAX_HASH_LEN];
@ -1540,9 +1540,9 @@ dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
len[num_elem] = os_strlen(identifier);
num_elem++;
}
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, code_len);
addr[num_elem] = (const u8 *) code;
len[num_elem] = os_strlen(code);
len[num_elem] = code_len;
num_elem++;
if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
goto fail;
@ -1590,7 +1590,7 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
u8 ver_init, u8 ver_resp,
const u8 *Mx, size_t Mx_len,
const u8 *Nx, size_t Nx_len,
const char *code,
const char *code, size_t code_len,
const u8 *Kx, size_t Kx_len,
u8 *z, unsigned int hash_len)
{
@ -1615,7 +1615,7 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
info_len = 2 * ETH_ALEN;
else
info_len = 2;
info_len += Mx_len + Nx_len + os_strlen(code);
info_len += Mx_len + Nx_len + code_len;
info = os_malloc(info_len);
if (!info)
return -1;
@ -1633,7 +1633,7 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
pos += Mx_len;
os_memcpy(pos, Nx, Nx_len);
pos += Nx_len;
os_memcpy(pos, code, os_strlen(code));
os_memcpy(pos, code, code_len);
/* HKDF-Expand(PRK, info, L) */
if (hash_len == 32)

View file

@ -113,17 +113,17 @@ int dpp_derive_pmkid(const struct dpp_curve_params *curve,
struct crypto_ec_key *peer_key, u8 *pmkid);
struct crypto_ec_point *
dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init,
const char *code, const char *identifier,
const char *code, size_t code_len, const char *identifier,
struct crypto_ec **ret_ec);
struct crypto_ec_point *
dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp,
const char *code, const char *identifier,
const char *code, size_t code_len, const char *identifier,
struct crypto_ec **ret_ec);
int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
u8 ver_init, u8 ver_resp,
const u8 *Mx, size_t Mx_len,
const u8 *Nx, size_t Nx_len,
const char *code,
const char *code, size_t code_len,
const u8 *Kx, size_t Kx_len,
u8 *z, unsigned int hash_len);
int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,

View file

@ -41,7 +41,7 @@ static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex,
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : pkex->own_mac, pkex->code,
pkex->identifier, &ec);
pkex->code_len, pkex->identifier, &ec);
if (!Qi)
goto fail;
@ -171,7 +171,7 @@ static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt)
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
const u8 *own_mac,
const char *identifier, const char *code,
bool v2)
size_t code_len, bool v2)
{
struct dpp_pkex *pkex;
@ -196,9 +196,10 @@ struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
if (!pkex->identifier)
goto fail;
}
pkex->code = os_strdup(code);
pkex->code = os_memdup(code, code_len);
if (!pkex->code)
goto fail;
pkex->code_len = code_len;
pkex->exchange_req = dpp_pkex_build_exchange_req(pkex, v2);
if (!pkex->exchange_req)
goto fail;
@ -340,7 +341,7 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
const u8 *own_mac,
const u8 *peer_mac,
const char *identifier,
const char *code,
const char *code, size_t code_len,
const u8 *buf, size_t len, bool v2)
{
const u8 *attr_group, *attr_id, *attr_key;
@ -437,8 +438,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
}
/* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, identifier,
&ec);
Qi = dpp_pkex_derive_Qi(curve, v2 ? NULL : peer_mac, code, code_len,
identifier, &ec);
if (!Qi)
goto fail;
@ -477,9 +478,10 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
if (!pkex->identifier)
goto fail;
}
pkex->code = os_strdup(code);
pkex->code = os_memdup(code, code_len);
if (!pkex->code)
goto fail;
pkex->code_len = code_len;
os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
@ -495,8 +497,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
goto fail;
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, identifier,
NULL);
Qr = dpp_pkex_derive_Qr(curve, v2 ? NULL : own_mac, code, code_len,
identifier, NULL);
if (!Qr)
goto fail;
@ -550,7 +552,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
pkex->peer_version, DPP_VERSION,
pkex->Mx, curve->prime_len,
pkex->Nx, curve->prime_len, pkex->code,
Kx, Kx_len, pkex->z, curve->hash_len);
pkex->code_len, Kx, Kx_len, pkex->z,
curve->hash_len);
os_memset(Kx, 0, Kx_len);
if (res < 0)
goto fail;
@ -791,7 +794,8 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
/* Qr = H([MAC-Responder |] [identifier |] code) * Pr */
Qr = dpp_pkex_derive_Qr(curve, pkex->v2 ? NULL : pkex->peer_mac,
pkex->code, pkex->identifier, &ec);
pkex->code, pkex->code_len, pkex->identifier,
&ec);
if (!Qr)
goto fail;
@ -869,7 +873,7 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
DPP_VERSION, pkex->peer_version,
pkex->Mx, curve->prime_len,
attr_key /* N.x */, attr_key_len / 2,
pkex->code, Kx, Kx_len,
pkex->code, pkex->code_len, Kx, Kx_len,
pkex->z, curve->hash_len);
os_memset(Kx, 0, Kx_len);
if (res < 0)

View file

@ -1017,6 +1017,7 @@ static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
NULL, NULL,
ctrl->pkex_identifier,
ctrl->pkex_code,
os_strlen(ctrl->pkex_code),
buf, len, true);
if (!conn->pkex) {
wpa_printf(MSG_DEBUG,

View file

@ -213,6 +213,8 @@ extern "C" {
#define DPP_EVENT_CSR "DPP-CSR "
#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX "
#define DPP_EVENT_CONF_NEEDED "DPP-CONF-NEEDED "
#define DPP_EVENT_PB_STATUS "DPP-PB-STATUS "
#define DPP_EVENT_PB_RESULT "DPP-PB-RESULT "
/* MESH events */
#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "