DPP2: Add E-id in Reconfig Announcement
Add an encrypted Enrollee identifier into Reconfig Announcement frames and decrypt that on the Configurator side. The actual E-id value is currently not used for anything, but it can be used in the future to provide better control over reconfiguration. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
ad2119cbc6
commit
c6d0e5a93d
8 changed files with 314 additions and 14 deletions
|
@ -1235,8 +1235,8 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
|
||||||
const u8 *hdr, const u8 *buf, size_t len,
|
const u8 *hdr, const u8 *buf, size_t len,
|
||||||
unsigned int freq)
|
unsigned int freq)
|
||||||
{
|
{
|
||||||
const u8 *csign_hash, *fcgroup;
|
const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
|
||||||
u16 csign_hash_len, fcgroup_len;
|
u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
|
||||||
struct dpp_configurator *conf;
|
struct dpp_configurator *conf;
|
||||||
struct dpp_authentication *auth;
|
struct dpp_authentication *auth;
|
||||||
unsigned int wait_time, max_wait_time;
|
unsigned int wait_time, max_wait_time;
|
||||||
|
@ -1282,8 +1282,12 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src,
|
||||||
group = WPA_GET_LE16(fcgroup);
|
group = WPA_GET_LE16(fcgroup);
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
||||||
|
|
||||||
|
a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
|
||||||
|
e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
|
||||||
|
|
||||||
auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx,
|
||||||
conf, freq, group);
|
conf, freq, group, a_nonce, a_nonce_len,
|
||||||
|
e_id, e_id_len);
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return;
|
return;
|
||||||
hostapd_dpp_set_testing_options(hapd, auth);
|
hostapd_dpp_set_testing_options(hapd, auth);
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct crypto_ecdh;
|
||||||
struct hostapd_ip_addr;
|
struct hostapd_ip_addr;
|
||||||
struct dpp_global;
|
struct dpp_global;
|
||||||
struct json_token;
|
struct json_token;
|
||||||
|
struct dpp_reconfig_id;
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
#define DPP_VERSION (dpp_version_override)
|
#define DPP_VERSION (dpp_version_override)
|
||||||
|
@ -87,6 +88,8 @@ enum dpp_attribute_id {
|
||||||
DPP_ATTR_RECONFIG_FLAGS = 0x101D,
|
DPP_ATTR_RECONFIG_FLAGS = 0x101D,
|
||||||
DPP_ATTR_C_SIGN_KEY_HASH = 0x101E,
|
DPP_ATTR_C_SIGN_KEY_HASH = 0x101E,
|
||||||
DPP_ATTR_CSR_ATTR_REQ = 0x101F,
|
DPP_ATTR_CSR_ATTR_REQ = 0x101F,
|
||||||
|
DPP_ATTR_A_NONCE = 0x1020,
|
||||||
|
DPP_ATTR_E_PRIME_ID = 0x1021,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum dpp_status_error {
|
enum dpp_status_error {
|
||||||
|
@ -685,10 +688,13 @@ void dpp_global_deinit(struct dpp_global *dpp);
|
||||||
struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
size_t csign_key_len,
|
size_t csign_key_len,
|
||||||
const u8 *net_access_key,
|
const u8 *net_access_key,
|
||||||
size_t net_access_key_len);
|
size_t net_access_key_len,
|
||||||
|
struct dpp_reconfig_id *id);
|
||||||
struct dpp_authentication *
|
struct dpp_authentication *
|
||||||
dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
||||||
struct dpp_configurator *conf, unsigned int freq, u16 group);
|
struct dpp_configurator *conf, unsigned int freq, u16 group,
|
||||||
|
const u8 *a_nonce_attr, size_t a_nonce_len,
|
||||||
|
const u8 *e_id_attr, size_t e_id_len);
|
||||||
struct dpp_authentication *
|
struct dpp_authentication *
|
||||||
dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
|
dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx,
|
||||||
const char *own_connector,
|
const char *own_connector,
|
||||||
|
@ -702,5 +708,10 @@ dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
const u8 *attr_start, size_t attr_len);
|
const u8 *attr_start, size_t attr_len);
|
||||||
|
|
||||||
|
struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
|
||||||
|
size_t csign_key_len);
|
||||||
|
int dpp_update_reconfig_id(struct dpp_reconfig_id *id);
|
||||||
|
void dpp_free_reconfig_id(struct dpp_reconfig_id *id);
|
||||||
|
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
#endif /* DPP_H */
|
#endif /* DPP_H */
|
||||||
|
|
|
@ -2988,6 +2988,193 @@ fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
|
||||||
|
size_t csign_key_len)
|
||||||
|
{
|
||||||
|
const unsigned char *p;
|
||||||
|
EVP_PKEY *csign = NULL;
|
||||||
|
struct dpp_reconfig_id *id = NULL;
|
||||||
|
BN_CTX *ctx = NULL;
|
||||||
|
BIGNUM *bn = NULL, *q = NULL;
|
||||||
|
const EC_KEY *eckey;
|
||||||
|
const EC_GROUP *group;
|
||||||
|
EC_POINT *e_id = NULL;
|
||||||
|
|
||||||
|
p = csign_key;
|
||||||
|
csign = d2i_PUBKEY(NULL, &p, csign_key_len);
|
||||||
|
if (!csign)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
eckey = EVP_PKEY_get0_EC_KEY(csign);
|
||||||
|
if (!eckey)
|
||||||
|
goto fail;
|
||||||
|
group = EC_KEY_get0_group(eckey);
|
||||||
|
if (!group)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
e_id = EC_POINT_new(group);
|
||||||
|
ctx = BN_CTX_new();
|
||||||
|
bn = BN_new();
|
||||||
|
q = BN_new();
|
||||||
|
if (!e_id || !ctx || !bn || !q ||
|
||||||
|
!EC_GROUP_get_order(group, q, ctx) ||
|
||||||
|
!BN_rand_range(bn, q) ||
|
||||||
|
!EC_POINT_mul(group, e_id, bn, NULL, NULL, ctx))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
dpp_debug_print_point("DPP: Generated random point E-id", group, e_id);
|
||||||
|
|
||||||
|
id = os_zalloc(sizeof(*id));
|
||||||
|
if (!id)
|
||||||
|
goto fail;
|
||||||
|
id->group = group;
|
||||||
|
id->e_id = e_id;
|
||||||
|
e_id = NULL;
|
||||||
|
id->csign = csign;
|
||||||
|
csign = NULL;
|
||||||
|
fail:
|
||||||
|
EC_POINT_free(e_id);
|
||||||
|
EVP_PKEY_free(csign);
|
||||||
|
BN_clear_free(bn);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static EVP_PKEY * dpp_pkey_from_point(const EC_GROUP *group,
|
||||||
|
const EC_POINT *point)
|
||||||
|
{
|
||||||
|
EC_KEY *eckey;
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
|
||||||
|
eckey = EC_KEY_new();
|
||||||
|
if (!eckey ||
|
||||||
|
EC_KEY_set_group(eckey, group) != 1 ||
|
||||||
|
EC_KEY_set_public_key(eckey, point) != 1) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"DPP: Failed to set EC_KEY: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
|
||||||
|
|
||||||
|
pkey = EVP_PKEY_new();
|
||||||
|
if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
|
||||||
|
wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
pkey = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
EC_KEY_free(eckey);
|
||||||
|
return pkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dpp_update_reconfig_id(struct dpp_reconfig_id *id)
|
||||||
|
{
|
||||||
|
BN_CTX *ctx = NULL;
|
||||||
|
BIGNUM *bn = NULL, *q = NULL;
|
||||||
|
EC_POINT *e_prime_id = NULL, *a_nonce = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
const EC_KEY *csign;
|
||||||
|
const EC_POINT *csign_point;
|
||||||
|
|
||||||
|
csign = EVP_PKEY_get0_EC_KEY(id->csign);
|
||||||
|
if (!csign)
|
||||||
|
goto fail;
|
||||||
|
csign_point = EC_KEY_get0_public_key(csign);
|
||||||
|
e_prime_id = EC_POINT_new(id->group);
|
||||||
|
a_nonce = EC_POINT_new(id->group);
|
||||||
|
ctx = BN_CTX_new();
|
||||||
|
bn = BN_new();
|
||||||
|
q = BN_new();
|
||||||
|
/* Generate random 0 <= a-nonce < q
|
||||||
|
* A-NONCE = a-nonce * G
|
||||||
|
* E'-id = E-id + a-nonce * S_C */
|
||||||
|
if (!csign_point || !e_prime_id || !a_nonce || !ctx || !bn || !q ||
|
||||||
|
!EC_GROUP_get_order(id->group, q, ctx) ||
|
||||||
|
!BN_rand_range(bn, q) || /* bn = a-nonce */
|
||||||
|
!EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) ||
|
||||||
|
!EC_POINT_mul(id->group, e_prime_id, NULL, csign_point, bn, ctx) ||
|
||||||
|
!EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
dpp_debug_print_point("DPP: Generated A-NONCE", id->group, a_nonce);
|
||||||
|
dpp_debug_print_point("DPP: Encrypted E-id to E'-id",
|
||||||
|
id->group, e_prime_id);
|
||||||
|
|
||||||
|
EVP_PKEY_free(id->a_nonce);
|
||||||
|
EVP_PKEY_free(id->e_prime_id);
|
||||||
|
id->a_nonce = dpp_pkey_from_point(id->group, a_nonce);
|
||||||
|
id->e_prime_id = dpp_pkey_from_point(id->group, e_prime_id);
|
||||||
|
if (!id->a_nonce || !id->e_prime_id)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
EC_POINT_free(e_prime_id);
|
||||||
|
EC_POINT_free(a_nonce);
|
||||||
|
BN_clear_free(bn);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dpp_free_reconfig_id(struct dpp_reconfig_id *id)
|
||||||
|
{
|
||||||
|
if (id) {
|
||||||
|
EC_POINT_clear_free(id->e_id);
|
||||||
|
EVP_PKEY_free(id->csign);
|
||||||
|
EVP_PKEY_free(id->a_nonce);
|
||||||
|
EVP_PKEY_free(id->e_prime_id);
|
||||||
|
os_free(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EC_POINT * dpp_decrypt_e_id(EVP_PKEY *csign, EVP_PKEY *a_nonce,
|
||||||
|
EVP_PKEY *e_prime_id)
|
||||||
|
{
|
||||||
|
const EC_KEY *csign_ec, *a_nonce_ec, *e_prime_id_ec;
|
||||||
|
const BIGNUM *csign_bn;
|
||||||
|
const EC_GROUP *group;
|
||||||
|
EC_POINT *e_id = NULL;
|
||||||
|
const EC_POINT *a_nonce_point, *e_prime_id_point;
|
||||||
|
BN_CTX *ctx = NULL;
|
||||||
|
|
||||||
|
/* E-id = E'-id - s_C * A-NONCE */
|
||||||
|
csign_ec = EVP_PKEY_get0_EC_KEY(csign);
|
||||||
|
a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce);
|
||||||
|
e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id);
|
||||||
|
if (!csign_ec || !a_nonce_ec || !e_prime_id_ec)
|
||||||
|
return NULL;
|
||||||
|
csign_bn = EC_KEY_get0_private_key(csign_ec);
|
||||||
|
group = EC_KEY_get0_group(csign_ec);
|
||||||
|
a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec);
|
||||||
|
e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec);
|
||||||
|
ctx = BN_CTX_new();
|
||||||
|
if (!csign_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx)
|
||||||
|
goto fail;
|
||||||
|
e_id = EC_POINT_new(group);
|
||||||
|
if (!e_id ||
|
||||||
|
!EC_POINT_mul(group, e_id, NULL, a_nonce_point, csign_bn, ctx) ||
|
||||||
|
!EC_POINT_invert(group, e_id, ctx) ||
|
||||||
|
!EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) {
|
||||||
|
EC_POINT_clear_free(e_id);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpp_debug_print_point("DPP: Decrypted E-id", group, e_id);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
return e_id;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -133,11 +133,21 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth,
|
||||||
int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
|
int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
|
||||||
const u8 *r_proto, u16 r_proto_len,
|
const u8 *r_proto, u16 r_proto_len,
|
||||||
struct json_token *net_access_key);
|
struct json_token *net_access_key);
|
||||||
|
EC_POINT * dpp_decrypt_e_id(EVP_PKEY *csign, EVP_PKEY *a_nonce,
|
||||||
|
EVP_PKEY *e_prime_id);
|
||||||
char * dpp_sign_connector(struct dpp_configurator *conf,
|
char * dpp_sign_connector(struct dpp_configurator *conf,
|
||||||
const struct wpabuf *dppcon);
|
const struct wpabuf *dppcon);
|
||||||
int dpp_test_gen_invalid_key(struct wpabuf *msg,
|
int dpp_test_gen_invalid_key(struct wpabuf *msg,
|
||||||
const struct dpp_curve_params *curve);
|
const struct dpp_curve_params *curve);
|
||||||
|
|
||||||
|
struct dpp_reconfig_id {
|
||||||
|
const EC_GROUP *group;
|
||||||
|
EC_POINT *e_id; /* E-id */
|
||||||
|
EVP_PKEY *csign;
|
||||||
|
EVP_PKEY *a_nonce; /* A-NONCE */
|
||||||
|
EVP_PKEY *e_prime_id; /* E'-id */
|
||||||
|
};
|
||||||
|
|
||||||
/* dpp_tcp.c */
|
/* dpp_tcp.c */
|
||||||
|
|
||||||
void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
|
void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
|
||||||
|
|
|
@ -36,7 +36,8 @@ static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash)
|
||||||
struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
size_t csign_key_len,
|
size_t csign_key_len,
|
||||||
const u8 *net_access_key,
|
const u8 *net_access_key,
|
||||||
size_t net_access_key_len)
|
size_t net_access_key_len,
|
||||||
|
struct dpp_reconfig_id *id)
|
||||||
{
|
{
|
||||||
struct wpabuf *msg = NULL;
|
struct wpabuf *msg = NULL;
|
||||||
EVP_PKEY *csign = NULL;
|
EVP_PKEY *csign = NULL;
|
||||||
|
@ -49,6 +50,7 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
size_t attr_len;
|
size_t attr_len;
|
||||||
const struct dpp_curve_params *own_curve;
|
const struct dpp_curve_params *own_curve;
|
||||||
EVP_PKEY *own_key;
|
EVP_PKEY *own_key;
|
||||||
|
struct wpabuf *a_nonce = NULL, *e_id = NULL;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
|
wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame");
|
||||||
|
|
||||||
|
@ -81,8 +83,20 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)",
|
wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)",
|
||||||
hash, SHA256_MAC_LEN);
|
hash, SHA256_MAC_LEN);
|
||||||
|
|
||||||
|
if (dpp_update_reconfig_id(id) < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "DPP: Failed to generate E'-id");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_nonce = dpp_get_pubkey_point(id->a_nonce, 0);
|
||||||
|
e_id = dpp_get_pubkey_point(id->e_prime_id, 0);
|
||||||
|
if (!a_nonce || !e_id)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
attr_len = 4 + SHA256_MAC_LEN;
|
attr_len = 4 + SHA256_MAC_LEN;
|
||||||
attr_len += 4 + 2;
|
attr_len += 4 + 2;
|
||||||
|
attr_len += 4 + wpabuf_len(a_nonce);
|
||||||
|
attr_len += 4 + wpabuf_len(e_id);
|
||||||
msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len);
|
msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -97,9 +111,21 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key,
|
||||||
wpabuf_put_le16(msg, 2);
|
wpabuf_put_le16(msg, 2);
|
||||||
wpabuf_put_le16(msg, own_curve->ike_group);
|
wpabuf_put_le16(msg, own_curve->ike_group);
|
||||||
|
|
||||||
|
/* A-NONCE */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_A_NONCE);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(a_nonce));
|
||||||
|
wpabuf_put_buf(msg, a_nonce);
|
||||||
|
|
||||||
|
/* E'-id */
|
||||||
|
wpabuf_put_le16(msg, DPP_ATTR_E_PRIME_ID);
|
||||||
|
wpabuf_put_le16(msg, wpabuf_len(e_id));
|
||||||
|
wpabuf_put_buf(msg, e_id);
|
||||||
|
|
||||||
wpa_hexdump_buf(MSG_DEBUG,
|
wpa_hexdump_buf(MSG_DEBUG,
|
||||||
"DPP: Reconfig Announcement frame attributes", msg);
|
"DPP: Reconfig Announcement frame attributes", msg);
|
||||||
fail:
|
fail:
|
||||||
|
wpabuf_free(a_nonce);
|
||||||
|
wpabuf_free(e_id);
|
||||||
EVP_PKEY_free(own_key);
|
EVP_PKEY_free(own_key);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
@ -198,10 +224,14 @@ fail:
|
||||||
|
|
||||||
struct dpp_authentication *
|
struct dpp_authentication *
|
||||||
dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
||||||
struct dpp_configurator *conf, unsigned int freq, u16 group)
|
struct dpp_configurator *conf, unsigned int freq, u16 group,
|
||||||
|
const u8 *a_nonce_attr, size_t a_nonce_len,
|
||||||
|
const u8 *e_id_attr, size_t e_id_len)
|
||||||
{
|
{
|
||||||
struct dpp_authentication *auth;
|
struct dpp_authentication *auth;
|
||||||
const struct dpp_curve_params *curve;
|
const struct dpp_curve_params *curve;
|
||||||
|
EVP_PKEY *a_nonce, *e_prime_id;
|
||||||
|
EC_POINT *e_id;
|
||||||
|
|
||||||
curve = dpp_get_curve_ike_group(group);
|
curve = dpp_get_curve_ike_group(group);
|
||||||
if (!curve) {
|
if (!curve) {
|
||||||
|
@ -211,6 +241,42 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!a_nonce_attr) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Missing required A-NONCE attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "DPP: A-NONCE", a_nonce_attr, a_nonce_len);
|
||||||
|
a_nonce = dpp_set_pubkey_point(conf->csign, a_nonce_attr, a_nonce_len);
|
||||||
|
if (!a_nonce) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Invalid A-NONCE");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dpp_debug_print_key("A-NONCE", a_nonce);
|
||||||
|
|
||||||
|
if (!e_id_attr) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Missing required E'-id attribute");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len);
|
||||||
|
if (!e_prime_id) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Invalid E'-id");
|
||||||
|
EVP_PKEY_free(a_nonce);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dpp_debug_print_key("E'-id", e_prime_id);
|
||||||
|
e_id = dpp_decrypt_e_id(conf->csign, a_nonce, e_prime_id);
|
||||||
|
EVP_PKEY_free(a_nonce);
|
||||||
|
EVP_PKEY_free(e_prime_id);
|
||||||
|
if (!e_id) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* TODO: could use E-id to determine whether reconfiguration with this
|
||||||
|
* Enrollee has already been started and is waiting for updated
|
||||||
|
* configuration instead of replying again before such configuration
|
||||||
|
* becomes available */
|
||||||
|
EC_POINT_clear_free(e_id);
|
||||||
|
|
||||||
auth = dpp_alloc_auth(dpp, msg_ctx);
|
auth = dpp_alloc_auth(dpp, msg_ctx);
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -844,8 +844,8 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn,
|
||||||
const u8 *hdr, const u8 *buf,
|
const u8 *hdr, const u8 *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
const u8 *csign_hash, *fcgroup;
|
const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
|
||||||
u16 csign_hash_len, fcgroup_len;
|
u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
|
||||||
struct dpp_configurator *conf;
|
struct dpp_configurator *conf;
|
||||||
struct dpp_global *dpp = conn->ctrl->global;
|
struct dpp_global *dpp = conn->ctrl->global;
|
||||||
struct dpp_authentication *auth;
|
struct dpp_authentication *auth;
|
||||||
|
@ -885,7 +885,11 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn,
|
||||||
group = WPA_GET_LE16(fcgroup);
|
group = WPA_GET_LE16(fcgroup);
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
||||||
|
|
||||||
auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group);
|
a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
|
||||||
|
e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
|
||||||
|
|
||||||
|
auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group,
|
||||||
|
a_nonce, a_nonce_len, e_id, e_id_len);
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return -1;
|
return -1;
|
||||||
if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
|
if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
|
||||||
|
|
|
@ -2022,8 +2022,8 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
const u8 *hdr, const u8 *buf, size_t len,
|
const u8 *hdr, const u8 *buf, size_t len,
|
||||||
unsigned int freq)
|
unsigned int freq)
|
||||||
{
|
{
|
||||||
const u8 *csign_hash, *fcgroup;
|
const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
|
||||||
u16 csign_hash_len, fcgroup_len;
|
u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
|
||||||
struct dpp_configurator *conf;
|
struct dpp_configurator *conf;
|
||||||
struct dpp_authentication *auth;
|
struct dpp_authentication *auth;
|
||||||
unsigned int wait_time, max_wait_time;
|
unsigned int wait_time, max_wait_time;
|
||||||
|
@ -2067,7 +2067,11 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
|
||||||
group = WPA_GET_LE16(fcgroup);
|
group = WPA_GET_LE16(fcgroup);
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
|
||||||
|
|
||||||
auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group);
|
a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
|
||||||
|
e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
|
||||||
|
|
||||||
|
auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group,
|
||||||
|
a_nonce, a_nonce_len, e_id, e_id_len);
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return;
|
return;
|
||||||
wpas_dpp_set_testing_options(wpa_s, auth);
|
wpas_dpp_set_testing_options(wpa_s, auth);
|
||||||
|
@ -3303,6 +3307,8 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
||||||
dpp_pfs_free(wpa_s->dpp_pfs);
|
dpp_pfs_free(wpa_s->dpp_pfs);
|
||||||
wpa_s->dpp_pfs = NULL;
|
wpa_s->dpp_pfs = NULL;
|
||||||
wpas_dpp_chirp_stop(wpa_s);
|
wpas_dpp_chirp_stop(wpa_s);
|
||||||
|
dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
|
||||||
|
wpa_s->dpp_reconfig_id = NULL;
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
offchannel_send_action_done(wpa_s);
|
offchannel_send_action_done(wpa_s);
|
||||||
wpas_dpp_listen_stop(wpa_s);
|
wpas_dpp_listen_stop(wpa_s);
|
||||||
|
@ -3642,14 +3648,25 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
|
||||||
|
wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign,
|
||||||
|
ssid->dpp_csign_len);
|
||||||
|
if (!wpa_s->dpp_reconfig_id) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Failed to generate E-id for reconfiguration");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
wpas_dpp_chirp_stop(wpa_s);
|
wpas_dpp_chirp_stop(wpa_s);
|
||||||
wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
|
wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
|
||||||
wpa_s->dpp_qr_mutual = 0;
|
wpa_s->dpp_qr_mutual = 0;
|
||||||
|
/* TODO: regenerate Reconfig Announcement frame to update A-NONCE/E'-id
|
||||||
|
* for each retransmission */
|
||||||
wpa_s->dpp_reconfig_announcement =
|
wpa_s->dpp_reconfig_announcement =
|
||||||
dpp_build_reconfig_announcement(ssid->dpp_csign,
|
dpp_build_reconfig_announcement(ssid->dpp_csign,
|
||||||
ssid->dpp_csign_len,
|
ssid->dpp_csign_len,
|
||||||
ssid->dpp_netaccesskey,
|
ssid->dpp_netaccesskey,
|
||||||
ssid->dpp_netaccesskey_len);
|
ssid->dpp_netaccesskey_len,
|
||||||
|
wpa_s->dpp_reconfig_id);
|
||||||
if (!wpa_s->dpp_reconfig_announcement)
|
if (!wpa_s->dpp_reconfig_announcement)
|
||||||
return -1;
|
return -1;
|
||||||
wpa_s->dpp_reconfig_ssid = ssid;
|
wpa_s->dpp_reconfig_ssid = ssid;
|
||||||
|
|
|
@ -1296,6 +1296,7 @@ struct wpa_supplicant {
|
||||||
int dpp_chirp_listen;
|
int dpp_chirp_listen;
|
||||||
struct wpa_ssid *dpp_reconfig_ssid;
|
struct wpa_ssid *dpp_reconfig_ssid;
|
||||||
int dpp_reconfig_ssid_id;
|
int dpp_reconfig_ssid_id;
|
||||||
|
struct dpp_reconfig_id *dpp_reconfig_id;
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *dpp_config_obj_override;
|
char *dpp_config_obj_override;
|
||||||
|
|
Loading…
Reference in a new issue