DPP3: Private Peer Introduction protocol

Add a privacy protecting variant of the peer introduction protocol to
allow the station device to hide its Connector from 3rd parties. The new
wpa_supplicant network profile parameter dpp_connector_privacy=1 can be
used to select this alternative mechanism to the peer introduction
protocol added in the initial release of DPP.

It should be noted that the new variant does not work with older DPP APs
(i.e., requires support for release 3). As such, this new variant is
disabled by default.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-07-18 23:41:24 +03:00 committed by Jouni Malinen
parent 786ea402bc
commit 148de3e0dc
11 changed files with 694 additions and 27 deletions

View file

@ -4100,7 +4100,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
struct json_token *root = NULL, *netkey, *token;
struct json_token *own_root = NULL;
enum dpp_status_error ret = 255, res;
struct crypto_ec_key *own_key = NULL, *peer_key = NULL;
struct crypto_ec_key *own_key = NULL;
struct wpabuf *own_key_pub = NULL;
const struct dpp_curve_params *curve, *own_curve;
struct dpp_signed_connector_info info;
@ -4173,12 +4173,12 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
goto fail;
}
peer_key = dpp_parse_jwk(netkey, &curve);
if (!peer_key) {
intro->peer_key = dpp_parse_jwk(netkey, &curve);
if (!intro->peer_key) {
ret = DPP_STATUS_INVALID_CONNECTOR;
goto fail;
}
dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
dpp_debug_print_key("DPP: Received netAccessKey", intro->peer_key);
if (own_curve != curve) {
wpa_printf(MSG_DEBUG,
@ -4189,7 +4189,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
}
/* ECDH: N = nk * PK */
if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
if (dpp_ecdh(own_key, intro->peer_key, Nx, &Nx_len) < 0)
goto fail;
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
@ -4203,26 +4203,45 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
intro->pmk_len = curve->hash_len;
/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
if (dpp_derive_pmkid(curve, own_key, intro->peer_key, intro->pmkid) <
0) {
wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
goto fail;
}
#ifdef CONFIG_DPP3
if (dpp_hpke_suite(curve->ike_group, &intro->kem_id, &intro->kdf_id,
&intro->aead_id) < 0) {
wpa_printf(MSG_ERROR, "DPP: Unsupported group %d",
curve->ike_group);
goto fail;
}
#endif /* CONFIG_DPP3 */
ret = DPP_STATUS_OK;
fail:
if (ret != DPP_STATUS_OK)
os_memset(intro, 0, sizeof(*intro));
dpp_peer_intro_deinit(intro);
os_memset(Nx, 0, sizeof(Nx));
os_free(info.payload);
crypto_ec_key_deinit(own_key);
wpabuf_free(own_key_pub);
crypto_ec_key_deinit(peer_key);
json_free(root);
json_free(own_root);
return ret;
}
void dpp_peer_intro_deinit(struct dpp_introduction *intro)
{
if (!intro)
return;
crypto_ec_key_deinit(intro->peer_key);
os_memset(intro, 0, sizeof(*intro));
}
#ifdef CONFIG_DPP3
int dpp_get_connector_version(const char *connector)
{

View file

@ -58,6 +58,9 @@ enum dpp_public_action_frame_type {
DPP_PA_PKEX_EXCHANGE_REQ = 18,
DPP_PA_PB_PRESENCE_ANNOUNCEMENT = 19,
DPP_PA_PB_PRESENCE_ANNOUNCEMENT_RESP = 20,
DPP_PA_PRIV_PEER_INTRO_QUERY = 21,
DPP_PA_PRIV_PEER_INTRO_NOTIFY = 22,
DPP_PA_PRIV_PEER_INTRO_UPDATE = 23,
};
enum dpp_attribute_id {
@ -413,6 +416,10 @@ struct dpp_introduction {
u8 pmk[PMK_LEN_MAX];
size_t pmk_len;
int peer_version;
struct crypto_ec_key *peer_key;
enum hpke_kem_id kem_id;
enum hpke_kdf_id kdf_id;
enum hpke_aead_id aead_id;
};
struct dpp_relay_config {
@ -650,6 +657,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
const u8 *csign_key, size_t csign_key_len,
const u8 *peer_connector, size_t peer_connector_len,
os_time_t *expiry);
void dpp_peer_intro_deinit(struct dpp_introduction *intro);
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,
@ -687,6 +695,11 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
void dpp_pfs_free(struct dpp_pfs *pfs);
struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
const u8 *privkey, size_t privkey_len);
int dpp_hpke_suite(int iana_group, enum hpke_kem_id *kem_id,
enum hpke_kdf_id *kdf_id, enum hpke_aead_id *aead_id);
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth,
const char *name);
int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr);

View file

@ -2367,6 +2367,7 @@ fail:
#ifdef CONFIG_DPP3
int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
{
int ret = -1, res;
@ -2454,6 +2455,47 @@ fail:
wpabuf_free(pex);
return ret;
}
int dpp_hpke_suite(int iana_group, enum hpke_kem_id *kem_id,
enum hpke_kdf_id *kdf_id, enum hpke_aead_id *aead_id)
{
switch (iana_group) {
case 19:
*kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
*kdf_id = HPKE_KDF_HKDF_SHA256;
*aead_id = HPKE_AEAD_AES_128_GCM;
return 0;
case 20:
*kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
*kdf_id = HPKE_KDF_HKDF_SHA384;
*aead_id = HPKE_AEAD_AES_256_GCM;
return 0;
case 21:
*kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
*kdf_id = HPKE_KDF_HKDF_SHA512;
*aead_id = HPKE_AEAD_AES_256_GCM;
return 0;
case 28:
*kem_id = HPKE_DHKEM_P256_HKDF_SHA256;
*kdf_id = HPKE_KDF_HKDF_SHA256;
*aead_id = HPKE_AEAD_AES_128_GCM;
return 0;
case 29:
*kem_id = HPKE_DHKEM_P384_HKDF_SHA384;
*kdf_id = HPKE_KDF_HKDF_SHA384;
*aead_id = HPKE_AEAD_AES_256_GCM;
return 0;
case 30:
*kem_id = HPKE_DHKEM_P521_HKDF_SHA512;
*kdf_id = HPKE_KDF_HKDF_SHA512;
*aead_id = HPKE_AEAD_AES_256_GCM;
return 0;
}
return -1;
}
#endif /* CONFIG_DPP3 */

View file

@ -98,8 +98,6 @@ int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi,
int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi);
int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len);
struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
const u8 *privkey, size_t privkey_len);
struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve);
int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len);
int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len);