DPP: Curve change for netAccessKey
Allow the Configurator to be configured to use a specific curve for the netAccessKey so that it can request the Enrollee to generate a new key during the configuration exchange to allow a compatible Connector to be generated when the network uses a different curve than the protocol keys used during the authentication exchange. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
fd2eb7a41e
commit
de64dfe98e
7 changed files with 466 additions and 11 deletions
|
@ -31,6 +31,7 @@ static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx);
|
|||
static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd);
|
||||
static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
|
||||
struct dpp_authentication *auth);
|
||||
static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd);
|
||||
#ifdef CONFIG_DPP2
|
||||
static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
|
||||
void *timeout_ctx);
|
||||
|
@ -1154,6 +1155,21 @@ static int hostapd_dpp_handle_key_pkg(struct hostapd_data *hapd,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
static void hostapd_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct hostapd_data *hapd = eloop_ctx;
|
||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||
|
||||
if (!auth || !auth->waiting_new_key)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
|
||||
hostapd_dpp_start_gas_client(hapd);
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
|
||||
static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
||||
enum gas_query_ap_result result,
|
||||
const struct wpabuf *adv_proto,
|
||||
|
@ -1163,6 +1179,7 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
const u8 *pos;
|
||||
struct dpp_authentication *auth = hapd->dpp_auth;
|
||||
enum dpp_status_error status = DPP_STATUS_CONFIG_REJECTED;
|
||||
int res;
|
||||
|
||||
if (!auth || !auth->auth_success) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
|
||||
|
@ -1193,7 +1210,16 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (dpp_conf_resp_rx(auth, resp) < 0) {
|
||||
res = dpp_conf_resp_rx(auth, resp);
|
||||
#ifdef CONFIG_DPP3
|
||||
if (res == -3) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
|
||||
eloop_register_timeout(0, 0, hostapd_dpp_build_new_key, hapd,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2354,6 +2380,13 @@ void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok)
|
|||
if (!auth)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
if (auth->waiting_new_key && ok) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
|
||||
ok);
|
||||
eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL);
|
||||
|
@ -2651,6 +2684,9 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
|
|||
if (hapd->iface->interfaces)
|
||||
dpp_controller_stop_for_ctx(hapd->iface->interfaces->dpp, hapd);
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#ifdef CONFIG_DPP3
|
||||
eloop_cancel_timeout(hostapd_dpp_build_new_key, hapd, NULL);
|
||||
#endif /* CONFIG_DPP3 */
|
||||
dpp_auth_deinit(hapd->dpp_auth);
|
||||
hapd->dpp_auth = NULL;
|
||||
hostapd_dpp_pkex_remove(hapd, "*");
|
||||
|
|
268
src/common/dpp.c
268
src/common/dpp.c
|
@ -658,9 +658,12 @@ static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
|
|||
{
|
||||
size_t nonce_len;
|
||||
size_t json_len, clear_len;
|
||||
struct wpabuf *clear = NULL, *msg = NULL;
|
||||
struct wpabuf *clear = NULL, *msg = NULL, *pe = NULL;
|
||||
u8 *wrapped;
|
||||
size_t attr_len;
|
||||
#ifdef CONFIG_DPP3
|
||||
u8 auth_i[DPP_MAX_HASH_LEN];
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
|
||||
|
||||
|
@ -675,6 +678,18 @@ static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth,
|
|||
|
||||
/* { E-nonce, configAttrib }ke */
|
||||
clear_len = 4 + nonce_len + 4 + json_len;
|
||||
#ifdef CONFIG_DPP3
|
||||
if (auth->waiting_new_key) {
|
||||
pe = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
|
||||
if (!pe)
|
||||
goto fail;
|
||||
clear_len += 4 + wpabuf_len(pe);
|
||||
|
||||
if (dpp_derive_auth_i(auth, auth_i) < 0)
|
||||
goto fail;
|
||||
clear_len += 4 + auth->new_curve->hash_len;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
clear = wpabuf_alloc(clear_len);
|
||||
attr_len = 4 + clear_len + AES_BLOCK_SIZE;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
|
@ -716,6 +731,21 @@ skip_e_nonce:
|
|||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
if (pe) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Pe");
|
||||
wpabuf_put_le16(clear, DPP_ATTR_I_PROTOCOL_KEY);
|
||||
wpabuf_put_le16(clear, wpabuf_len(pe));
|
||||
wpabuf_put_buf(clear, pe);
|
||||
}
|
||||
if (auth->waiting_new_key && auth->new_curve) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Initiator Authentication Tag");
|
||||
wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
|
||||
wpabuf_put_le16(clear, auth->new_curve->hash_len);
|
||||
wpabuf_put_data(clear, auth_i, auth->new_curve->hash_len);
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
/* configAttrib */
|
||||
wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
|
||||
wpabuf_put_le16(clear, json_len);
|
||||
|
@ -748,13 +778,15 @@ skip_wrapped_data:
|
|||
|
||||
wpa_hexdump_buf(MSG_DEBUG,
|
||||
"DPP: Configuration Request frame attributes", msg);
|
||||
out:
|
||||
wpabuf_free(clear);
|
||||
wpabuf_free(pe);
|
||||
return msg;
|
||||
|
||||
fail:
|
||||
wpabuf_free(clear);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
msg = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1430,7 +1462,8 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
|
|||
struct wpabuf *buf = NULL;
|
||||
char *signed_conn = NULL;
|
||||
size_t tailroom;
|
||||
const struct dpp_curve_params *curve;
|
||||
const struct dpp_curve_params *curve; /* C-sign-key curve */
|
||||
const struct dpp_curve_params *nak_curve; /* netAccessKey curve */
|
||||
struct wpabuf *dppcon = NULL;
|
||||
size_t extra_len = 1000;
|
||||
int incl_legacy;
|
||||
|
@ -1443,6 +1476,10 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
|
|||
goto fail;
|
||||
}
|
||||
curve = auth->conf->curve;
|
||||
if (auth->new_curve && auth->new_key_received)
|
||||
nak_curve = auth->new_curve;
|
||||
else
|
||||
nak_curve = auth->curve;
|
||||
|
||||
akm = conf->akm;
|
||||
if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
|
||||
|
@ -1460,7 +1497,7 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
|
|||
extra_len += os_strlen(conf->group_id);
|
||||
|
||||
/* Connector (JSON dppCon object) */
|
||||
dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3);
|
||||
dppcon = wpabuf_alloc(extra_len + 2 * nak_curve->prime_len * 4 / 3);
|
||||
if (!dppcon)
|
||||
goto fail;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
|
@ -1490,9 +1527,31 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
|
|||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
skip_groups:
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
if (!auth->peer_protocol_key ||
|
||||
dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
|
||||
auth->curve) < 0) {
|
||||
if (!auth->peer_protocol_key) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: No peer protocol key available to build netAccessKey JWK");
|
||||
goto fail;
|
||||
}
|
||||
#ifdef CONFIG_DPP3
|
||||
if (auth->conf->net_access_key_curve &&
|
||||
auth->curve != auth->conf->net_access_key_curve &&
|
||||
!auth->new_key_received) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Peer protocol key curve (%s) does not match the required netAccessKey curve (%s) - %s",
|
||||
auth->curve->name,
|
||||
auth->conf->net_access_key_curve->name,
|
||||
auth->waiting_new_key ?
|
||||
"the required key not received" :
|
||||
"request a new key");
|
||||
if (auth->waiting_new_key)
|
||||
auth->waiting_new_key = false; /* failed */
|
||||
else
|
||||
auth->waiting_new_key = true;
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
|
||||
nak_curve) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1731,7 +1790,7 @@ struct wpabuf *
|
|||
dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
||||
u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req)
|
||||
{
|
||||
struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL;
|
||||
struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL, *pc = NULL;
|
||||
size_t clear_len, attr_len;
|
||||
struct wpabuf *clear = NULL, *msg = NULL;
|
||||
u8 *wrapped;
|
||||
|
@ -1765,6 +1824,10 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
|||
else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta &&
|
||||
auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr)
|
||||
status = DPP_STATUS_CSR_NEEDED;
|
||||
#ifdef CONFIG_DPP3
|
||||
else if (auth->waiting_new_key)
|
||||
status = DPP_STATUS_NEW_KEY_NEEDED;
|
||||
#endif /* CONFIG_DPP3 */
|
||||
else
|
||||
status = DPP_STATUS_CONFIGURE_FAILURE;
|
||||
forced_status:
|
||||
|
@ -1784,6 +1847,31 @@ forced_status:
|
|||
if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta &&
|
||||
auth->conf_sta->csrattrs)
|
||||
clear_len += 4 + os_strlen(auth->conf_sta->csrattrs);
|
||||
#ifdef CONFIG_DPP3
|
||||
if (status == DPP_STATUS_NEW_KEY_NEEDED) {
|
||||
struct crypto_ec_key *new_pc;
|
||||
|
||||
clear_len += 6; /* Finite Cyclic Group attribute */
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Generate a new own protocol key for the curve %s",
|
||||
auth->conf->net_access_key_curve->name);
|
||||
new_pc = dpp_gen_keypair(auth->conf->net_access_key_curve);
|
||||
if (!new_pc) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Failed to generate new Pc");
|
||||
return NULL;
|
||||
}
|
||||
pc = crypto_ec_key_get_pubkey_point(new_pc, 0);
|
||||
if (!pc) {
|
||||
crypto_ec_key_deinit(new_pc);
|
||||
return NULL;
|
||||
}
|
||||
crypto_ec_key_deinit(auth->own_protocol_key);
|
||||
auth->own_protocol_key = new_pc;
|
||||
auth->new_curve = auth->conf->net_access_key_curve;
|
||||
clear_len += 4 + wpabuf_len(pc);
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
clear = wpabuf_alloc(clear_len);
|
||||
attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
|
@ -1861,6 +1949,27 @@ skip_e_nonce:
|
|||
wpabuf_put_str(clear, auth->conf_sta->csrattrs);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
if (status == DPP_STATUS_NEW_KEY_NEEDED && auth->conf &&
|
||||
auth->conf->net_access_key_curve) {
|
||||
u16 ike_group = auth->conf->net_access_key_curve->ike_group;
|
||||
|
||||
/* Finite Cyclic Group attribute */
|
||||
wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u",
|
||||
ike_group);
|
||||
wpabuf_put_le16(clear, DPP_ATTR_FINITE_CYCLIC_GROUP);
|
||||
wpabuf_put_le16(clear, 2);
|
||||
wpabuf_put_le16(clear, ike_group);
|
||||
|
||||
if (pc) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Pc");
|
||||
wpabuf_put_le16(clear, DPP_ATTR_R_PROTOCOL_KEY);
|
||||
wpabuf_put_le16(clear, wpabuf_len(pc));
|
||||
wpabuf_put_buf(clear, pc);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
skip_config_obj:
|
||||
if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
|
||||
|
@ -1911,6 +2020,7 @@ out:
|
|||
wpabuf_clear_free(conf2);
|
||||
wpabuf_clear_free(env_data);
|
||||
wpabuf_clear_free(clear);
|
||||
wpabuf_free(pc);
|
||||
|
||||
return msg;
|
||||
fail:
|
||||
|
@ -1932,6 +2042,10 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
|||
struct json_token *root = NULL, *token;
|
||||
enum dpp_netrole netrole;
|
||||
struct wpabuf *cert_req = NULL;
|
||||
#ifdef CONFIG_DPP3
|
||||
const u8 *i_proto;
|
||||
u16 i_proto_len;
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) {
|
||||
|
@ -1985,6 +2099,60 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
|||
wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
|
||||
os_memcpy(auth->e_nonce, e_nonce, e_nonce_len);
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
i_proto = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_I_PROTOCOL_KEY, &i_proto_len);
|
||||
if (i_proto && !auth->waiting_new_key) {
|
||||
dpp_auth_fail(auth,
|
||||
"Enrollee included a new protocol key even though one was not expected");
|
||||
goto fail;
|
||||
}
|
||||
if (i_proto) {
|
||||
struct crypto_ec_key *pe;
|
||||
u8 auth_i[DPP_MAX_HASH_LEN];
|
||||
const u8 *rx_auth_i;
|
||||
u16 rx_auth_i_len;
|
||||
|
||||
wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key (new Pe)",
|
||||
i_proto, i_proto_len);
|
||||
|
||||
pe = dpp_set_pubkey_point(auth->own_protocol_key,
|
||||
i_proto, i_proto_len);
|
||||
if (!pe) {
|
||||
dpp_auth_fail(auth,
|
||||
"Invalid Initiator Protocol Key (Pe)");
|
||||
goto fail;
|
||||
}
|
||||
dpp_debug_print_key("New Peer Protocol Key (Pe)", pe);
|
||||
crypto_ec_key_deinit(auth->peer_protocol_key);
|
||||
auth->peer_protocol_key = pe;
|
||||
auth->new_key_received = true;
|
||||
auth->waiting_new_key = false;
|
||||
|
||||
if (dpp_derive_auth_i(auth, auth_i) < 0)
|
||||
goto fail;
|
||||
|
||||
rx_auth_i = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_I_AUTH_TAG, &rx_auth_i_len);
|
||||
if (!rx_auth_i) {
|
||||
dpp_auth_fail(auth,
|
||||
"Missing Initiator Authentication Tag");
|
||||
goto fail;
|
||||
}
|
||||
if (rx_auth_i_len != auth->new_curve->hash_len ||
|
||||
os_memcmp(rx_auth_i, auth_i,
|
||||
auth->new_curve->hash_len) != 0) {
|
||||
dpp_auth_fail(auth,
|
||||
"Mismatch in Initiator Authenticating Tag");
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: Received Auth-I",
|
||||
rx_auth_i, rx_auth_i_len);
|
||||
wpa_hexdump(MSG_DEBUG, "DPP: Derived Auth-I'",
|
||||
auth_i, auth->new_curve->hash_len);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
config_attr = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_CONFIG_ATTR_OBJ,
|
||||
&config_attr_len);
|
||||
|
@ -2983,6 +3151,72 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
|||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#ifdef CONFIG_DPP3
|
||||
if (status[0] == DPP_STATUS_NEW_KEY_NEEDED) {
|
||||
const u8 *fcgroup, *r_proto;
|
||||
u16 fcgroup_len, r_proto_len;
|
||||
u16 group;
|
||||
const struct dpp_curve_params *curve;
|
||||
struct crypto_ec_key *new_pe;
|
||||
struct crypto_ec_key *pc;
|
||||
|
||||
fcgroup = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_FINITE_CYCLIC_GROUP,
|
||||
&fcgroup_len);
|
||||
if (!fcgroup || fcgroup_len != 2) {
|
||||
dpp_auth_fail(auth,
|
||||
"Missing or invalid required Finite Cyclic Group attribute");
|
||||
goto fail;
|
||||
}
|
||||
group = WPA_GET_LE16(fcgroup);
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Configurator requested a new protocol key from group %u",
|
||||
group);
|
||||
curve = dpp_get_curve_ike_group(group);
|
||||
if (!curve) {
|
||||
dpp_auth_fail(auth,
|
||||
"Unsupported group for new protocol key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
new_pe = dpp_gen_keypair(curve);
|
||||
if (!new_pe) {
|
||||
dpp_auth_fail(auth,
|
||||
"Failed to generate a new protocol key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
crypto_ec_key_deinit(auth->own_protocol_key);
|
||||
auth->own_protocol_key = new_pe;
|
||||
auth->new_curve = curve;
|
||||
|
||||
r_proto = dpp_get_attr(unwrapped, unwrapped_len,
|
||||
DPP_ATTR_R_PROTOCOL_KEY,
|
||||
&r_proto_len);
|
||||
if (!r_proto) {
|
||||
dpp_auth_fail(auth,
|
||||
"Missing required Responder Protocol Key attribute (Pc)");
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key (new Pc)",
|
||||
r_proto, r_proto_len);
|
||||
|
||||
pc = dpp_set_pubkey_point(new_pe, r_proto, r_proto_len);
|
||||
if (!pc) {
|
||||
dpp_auth_fail(auth, "Invalid Responder Protocol Key (Pc)");
|
||||
goto fail;
|
||||
}
|
||||
dpp_debug_print_key("New Peer Protocol Key (Pc)", pc);
|
||||
|
||||
crypto_ec_key_deinit(auth->peer_protocol_key);
|
||||
auth->peer_protocol_key = pc;
|
||||
|
||||
auth->waiting_new_key = true;
|
||||
ret = -3;
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
if (status[0] != DPP_STATUS_OK) {
|
||||
dpp_auth_fail(auth, "Configurator rejected configuration");
|
||||
goto fail;
|
||||
|
@ -4204,12 +4438,25 @@ static unsigned int dpp_next_configurator_id(struct dpp_global *dpp)
|
|||
|
||||
int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
|
||||
{
|
||||
char *curve = NULL;
|
||||
char *curve;
|
||||
char *key = NULL, *ppkey = NULL;
|
||||
u8 *privkey = NULL, *pp_key = NULL;
|
||||
size_t privkey_len = 0, pp_key_len = 0;
|
||||
int ret = -1;
|
||||
struct dpp_configurator *conf = NULL;
|
||||
const struct dpp_curve_params *net_access_key_curve = NULL;
|
||||
|
||||
curve = get_param(cmd, " net_access_key_curve=");
|
||||
if (curve) {
|
||||
net_access_key_curve = dpp_get_curve_name(curve);
|
||||
if (!net_access_key_curve) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Unsupported net_access_key_curve: %s",
|
||||
curve);
|
||||
goto fail;
|
||||
}
|
||||
os_free(curve);
|
||||
}
|
||||
|
||||
curve = get_param(cmd, " curve=");
|
||||
key = get_param(cmd, " key=");
|
||||
|
@ -4236,6 +4483,7 @@ int dpp_configurator_add(struct dpp_global *dpp, const char *cmd)
|
|||
if (!conf)
|
||||
goto fail;
|
||||
|
||||
conf->net_access_key_curve = net_access_key_curve;
|
||||
conf->id = dpp_next_configurator_id(dpp);
|
||||
dl_list_add(&dpp->configurator, &conf->list);
|
||||
ret = conf->id;
|
||||
|
|
|
@ -110,6 +110,7 @@ enum dpp_status_error {
|
|||
DPP_STATUS_CONFIGURE_PENDING = 11,
|
||||
DPP_STATUS_CSR_NEEDED = 12,
|
||||
DPP_STATUS_CSR_BAD = 13,
|
||||
DPP_STATUS_NEW_KEY_NEEDED = 14,
|
||||
};
|
||||
|
||||
/* DPP Reconfig Flags object - connectorKey values */
|
||||
|
@ -258,6 +259,7 @@ struct dpp_authentication {
|
|||
void *msg_ctx;
|
||||
u8 peer_version;
|
||||
const struct dpp_curve_params *curve;
|
||||
const struct dpp_curve_params *new_curve;
|
||||
struct dpp_bootstrap_info *peer_bi;
|
||||
struct dpp_bootstrap_info *own_bi;
|
||||
struct dpp_bootstrap_info *tmp_own_bi;
|
||||
|
@ -358,6 +360,8 @@ struct dpp_authentication {
|
|||
char *trusted_eap_server_name;
|
||||
struct wpabuf *cacert;
|
||||
struct wpabuf *certbag;
|
||||
bool waiting_new_key;
|
||||
bool new_key_received;
|
||||
void *config_resp_ctx;
|
||||
void *gas_server_ctx;
|
||||
bool use_config_query;
|
||||
|
@ -381,6 +385,7 @@ struct dpp_configurator {
|
|||
u8 kid_hash[SHA256_MAC_LEN];
|
||||
char *kid;
|
||||
const struct dpp_curve_params *curve;
|
||||
const struct dpp_curve_params *net_access_key_curve;
|
||||
char *connector; /* own Connector for reconfiguration */
|
||||
struct crypto_ec_key *connector_key;
|
||||
struct crypto_ec_key *pp_key;
|
||||
|
|
|
@ -2355,6 +2355,100 @@ fail:
|
|||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i)
|
||||
{
|
||||
int ret = -1, res;
|
||||
u8 Sx[DPP_MAX_SHARED_SECRET_LEN];
|
||||
size_t Sx_len;
|
||||
unsigned int hash_len;
|
||||
const char *info = "New DPP Protocol Key";
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
u8 tmp[DPP_MAX_HASH_LEN], k[DPP_MAX_HASH_LEN];
|
||||
struct wpabuf *pcx = NULL, *pex = NULL;
|
||||
|
||||
if (!auth->new_curve)
|
||||
return -1;
|
||||
|
||||
hash_len = auth->new_curve->hash_len;
|
||||
|
||||
/*
|
||||
* Configurator: S = pc * Pe
|
||||
* Enrollee: S = pe * Pc
|
||||
* k = HKDF(bk, "New DPP Protocol Key", S.x)
|
||||
* = HKDF-Expand(HKDF-Extract(bk, S.X), "New DPP Protocol Key",
|
||||
* len(new-curve-hash-out))
|
||||
* Auth-I = H(k, E-nonce | Pc.x | Pe.x)
|
||||
* Note: Assume this H(k, ..) is actually H(k | ..)
|
||||
*
|
||||
* auth->own_protocol_key, auth->peer_protocol_key, and auth->curve have
|
||||
* already been updated to use the new keys and curve.
|
||||
*/
|
||||
|
||||
if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
|
||||
Sx, &Sx_len) < 0)
|
||||
goto fail;
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "DPP: S.x", Sx, Sx_len);
|
||||
|
||||
/* tmp = HKDF-Extract(bk, S.x) */
|
||||
addr[0] = Sx;
|
||||
len[0] = Sx_len;
|
||||
res = dpp_hmac_vector(hash_len, auth->bk, auth->new_curve->hash_len,
|
||||
1, addr, len, tmp);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG, "DPP: HKDF-Extract(bk, S.x)",
|
||||
tmp, hash_len);
|
||||
/* k = HKDF-Expand(tmp, "New DPP Protocol Key", len(new-curve-hash-out))
|
||||
*/
|
||||
res = dpp_hkdf_expand(hash_len, tmp, hash_len, info, k, hash_len);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG,
|
||||
"DPP: k = HKDF-Expand(\"New DPP Protocol Key\")",
|
||||
k, hash_len);
|
||||
|
||||
/* Auth-I = H(k | E-nonce | Pc.x | Pe.x) */
|
||||
addr[0] = k;
|
||||
len[0] = hash_len;
|
||||
addr[1] = auth->e_nonce;
|
||||
len[1] = auth->new_curve->nonce_len;
|
||||
|
||||
if (auth->configurator) {
|
||||
pcx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
|
||||
pex = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
|
||||
0);
|
||||
} else {
|
||||
pcx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key,
|
||||
0);
|
||||
pex = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0);
|
||||
}
|
||||
if (!pcx || !pex)
|
||||
goto fail;
|
||||
addr[2] = wpabuf_head(pcx);
|
||||
len[2] = wpabuf_len(pcx) / 2;
|
||||
addr[3] = wpabuf_head(pex);
|
||||
len[3] = wpabuf_len(pex) / 2;
|
||||
|
||||
if (dpp_hash_vector(auth->new_curve, 4, addr, len, auth_i) < 0)
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG, "DPP: Auth-I = H(k | E-nonce | Pc.x | Pe.x)",
|
||||
auth_i, hash_len);
|
||||
ret = 0;
|
||||
fail:
|
||||
forced_memzero(Sx, sizeof(Sx));
|
||||
forced_memzero(tmp, sizeof(tmp));
|
||||
forced_memzero(k, sizeof(k));
|
||||
wpabuf_free(pcx);
|
||||
wpabuf_free(pex);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
|
||||
int dpp_test_gen_invalid_key(struct wpabuf *msg,
|
||||
|
|
|
@ -136,6 +136,7 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth,
|
|||
struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey,
|
||||
struct crypto_ec_key *a_nonce,
|
||||
struct crypto_ec_key *e_prime_id);
|
||||
int dpp_derive_auth_i(struct dpp_authentication *auth, u8 *auth_i);
|
||||
char * dpp_sign_connector(struct dpp_configurator *conf,
|
||||
const struct wpabuf *dppcon);
|
||||
int dpp_test_gen_invalid_key(struct wpabuf *msg,
|
||||
|
|
|
@ -89,6 +89,9 @@ static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
|
|||
static void dpp_controller_auth_success(struct dpp_connection *conn,
|
||||
int initiator);
|
||||
static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx);
|
||||
#ifdef CONFIG_DPP3
|
||||
static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx);
|
||||
#endif /* CONFIG_DPP3 */
|
||||
static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx);
|
||||
static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
|
||||
|
@ -107,6 +110,9 @@ static void dpp_connection_free(struct dpp_connection *conn)
|
|||
eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL);
|
||||
eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
|
||||
eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
|
||||
#ifdef CONFIG_DPP3
|
||||
eloop_cancel_timeout(dpp_tcp_build_new_key, conn, NULL);
|
||||
#endif /* CONFIG_DPP3 */
|
||||
wpabuf_free(conn->msg);
|
||||
wpabuf_free(conn->msg_out);
|
||||
dpp_auth_deinit(conn->auth);
|
||||
|
@ -193,6 +199,14 @@ static void dpp_controller_gas_done(struct dpp_connection *conn)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
if (auth->waiting_new_key) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
|
||||
conn->on_tcp_tx_complete_gas_done = 0;
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
if (auth->peer_version >= 2 &&
|
||||
auth->conf_resp_status == DPP_STATUS_OK) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
|
||||
|
@ -1440,6 +1454,21 @@ static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct dpp_connection *conn = eloop_ctx;
|
||||
struct dpp_authentication *auth = conn->auth;
|
||||
|
||||
if (!auth || !auth->waiting_new_key)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
|
||||
dpp_controller_start_gas_client(conn);
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
|
||||
static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
|
||||
{
|
||||
struct dpp_authentication *auth = conn->auth;
|
||||
|
@ -1460,6 +1489,14 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
|
|||
eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL);
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_DPP3
|
||||
if (res == -3) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
|
||||
eloop_register_timeout(0, 0, dpp_tcp_build_new_key, conn,
|
||||
NULL);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
|
||||
return -1;
|
||||
|
|
|
@ -1656,6 +1656,21 @@ static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
|
|||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
static void wpas_dpp_build_new_key(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
||||
|
||||
if (!auth || !auth->waiting_new_key)
|
||||
return;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
|
||||
wpas_dpp_start_gas_client(wpa_s);
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
|
||||
static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
||||
enum gas_query_result result,
|
||||
const struct wpabuf *adv_proto,
|
||||
|
@ -1709,6 +1724,14 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#ifdef CONFIG_DPP3
|
||||
if (res == -3) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
|
||||
eloop_register_timeout(0, 0, wpas_dpp_build_new_key, wpa_s,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
|
||||
goto fail;
|
||||
|
@ -3356,6 +3379,14 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
|
|||
}
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
#ifdef CONFIG_DPP3
|
||||
if (auth->waiting_new_key && ok) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
|
||||
wpabuf_free(resp);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_DPP3 */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
|
||||
ok);
|
||||
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
||||
|
@ -3809,6 +3840,9 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
|||
dpp_free_reconfig_id(wpa_s->dpp_reconfig_id);
|
||||
wpa_s->dpp_reconfig_id = NULL;
|
||||
#endif /* CONFIG_DPP2 */
|
||||
#ifdef CONFIG_DPP3
|
||||
eloop_cancel_timeout(wpas_dpp_build_new_key, wpa_s, NULL);
|
||||
#endif /* CONFIG_DPP3 */
|
||||
offchannel_send_action_done(wpa_s);
|
||||
wpas_dpp_listen_stop(wpa_s);
|
||||
wpas_dpp_stop(wpa_s);
|
||||
|
|
Loading…
Reference in a new issue