DPP: Helper function for bootstrapping URI generation

The new dpp_gen_uri() helper function can be used to build the
bootstrapping URI from locally stored information. This can be used to
make it easier to update the URI, e.g., for NFC negotiated connection
handover cases.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2020-01-27 17:04:26 +02:00 committed by Jouni Malinen
parent f5b7b24912
commit 2bbe6ad3aa
3 changed files with 57 additions and 57 deletions

View file

@ -1,7 +1,7 @@
/*
* DPP functionality shared between hostapd and wpa_supplicant
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation
* Copyright (c) 2018-2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -820,6 +820,8 @@ void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
return;
os_free(info->uri);
os_free(info->info);
os_free(info->chan);
os_free(info->pk);
EVP_PKEY_free(info->pubkey);
os_free(info);
}
@ -1471,7 +1473,7 @@ int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
}
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
static int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len)
{
char *base64 = NULL;
@ -1488,7 +1490,7 @@ char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
if (!bi->curve) {
wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
curve);
return NULL;
return -1;
}
}
if (privkey)
@ -1528,11 +1530,13 @@ char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
break;
os_memmove(pos, pos + 1, end - pos);
}
return base64;
os_free(bi->pk);
bi->pk = base64;
return 0;
fail:
os_free(base64);
wpabuf_free(der);
return NULL;
return -1;
}
@ -2198,11 +2202,42 @@ static int dpp_prepare_channel_list(struct dpp_authentication *auth,
}
static int dpp_gen_uri(struct dpp_bootstrap_info *bi)
{
char macstr[ETH_ALEN * 2 + 10];
size_t len;
len = 4; /* "DPP:" */
if (bi->chan)
len += 3 + os_strlen(bi->chan); /* C:...; */
if (is_zero_ether_addr(bi->mac_addr))
macstr[0] = '\0';
else
os_snprintf(macstr, sizeof(macstr), "M:" COMPACT_MACSTR ";",
MAC2STR(bi->mac_addr));
len += os_strlen(macstr); /* M:...; */
if (bi->info)
len += 3 + os_strlen(bi->info); /* I:...; */
len += 4 + os_strlen(bi->pk); /* K:...;; */
os_free(bi->uri);
bi->uri = os_malloc(len + 1);
if (!bi->uri)
return -1;
os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%sK:%s;;",
bi->chan ? "C:" : "", bi->chan ? bi->chan : "",
bi->chan ? ";" : "",
macstr,
bi->info ? "I:" : "", bi->info ? bi->info : "",
bi->info ? ";" : "",
bi->pk);
return 0;
}
static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
{
struct dpp_bootstrap_info *bi;
char *pk = NULL;
size_t len;
if (auth->own_bi)
return 0; /* already generated */
@ -2211,27 +2246,17 @@ static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth)
if (!bi)
return -1;
bi->type = DPP_BOOTSTRAP_QR_CODE;
pk = dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0);
if (!pk)
if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 ||
dpp_gen_uri(bi) < 0)
goto fail;
len = 4; /* "DPP:" */
len += 4 + os_strlen(pk);
bi->uri = os_malloc(len + 1);
if (!bi->uri)
goto fail;
os_snprintf(bi->uri, len + 1, "DPP:K:%s;;", pk);
wpa_printf(MSG_DEBUG,
"DPP: Auto-generated own bootstrapping key info: URI %s",
bi->uri);
auth->tmp_own_bi = auth->own_bi = bi;
os_free(pk);
return 0;
fail:
os_free(pk);
dpp_bootstrap_info_free(bi);
return -1;
}
@ -9000,11 +9025,10 @@ struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
{
char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
char *mac = NULL, *info = NULL, *curve = NULL;
char *key = NULL;
u8 *privkey = NULL;
size_t privkey_len = 0;
size_t len;
int ret = -1;
struct dpp_bootstrap_info *bi;
@ -9024,7 +9048,7 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
else
goto fail;
chan = get_param(cmd, " chan=");
bi->chan = get_param(cmd, " chan=");
mac = get_param(cmd, " mac=");
info = get_param(cmd, " info=");
curve = get_param(cmd, " curve=");
@ -9038,43 +9062,19 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
goto fail;
}
pk = dpp_keygen(bi, curve, privkey, privkey_len);
if (!pk)
if (dpp_keygen(bi, curve, privkey, privkey_len) < 0 ||
dpp_parse_uri_chan_list(bi, bi->chan) < 0 ||
dpp_parse_uri_mac(bi, mac) < 0 ||
dpp_parse_uri_info(bi, info) < 0 ||
dpp_gen_uri(bi) < 0)
goto fail;
len = 4; /* "DPP:" */
if (chan) {
if (dpp_parse_uri_chan_list(bi, chan) < 0)
goto fail;
len += 3 + os_strlen(chan); /* C:...; */
}
if (mac) {
if (dpp_parse_uri_mac(bi, mac) < 0)
goto fail;
len += 3 + os_strlen(mac); /* M:...; */
}
if (info) {
if (dpp_parse_uri_info(bi, info) < 0)
goto fail;
len += 3 + os_strlen(info); /* I:...; */
}
len += 4 + os_strlen(pk);
bi->uri = os_malloc(len + 1);
if (!bi->uri)
goto fail;
os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
info ? "I:" : "", info ? info : "", info ? ";" : "",
pk);
bi->id = dpp_next_id(dpp);
dl_list_add(&dpp->bootstrap, &bi->list);
ret = bi->id;
bi = NULL;
fail:
os_free(curve);
os_free(pk);
os_free(chan);
os_free(mac);
os_free(info);
str_clear_free(key);

View file

@ -1,7 +1,7 @@
/*
* DPP functionality shared between hostapd and wpa_supplicant
* Copyright (c) 2017, Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation
* Copyright (c) 2018-2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -115,7 +115,9 @@ struct dpp_bootstrap_info {
enum dpp_bootstrap_type type;
char *uri;
u8 mac_addr[ETH_ALEN];
char *chan;
char *info;
char *pk;
unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ];
unsigned int num_freq;
int own;
@ -416,8 +418,6 @@ int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
const char *chan_list);
int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac);
int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info);
char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
const u8 *privkey, size_t privkey_len);
struct hostapd_hw_modes;
struct dpp_authentication * dpp_auth_init(void *msg_ctx,
struct dpp_bootstrap_info *peer_bi,

View file

@ -3894,7 +3894,7 @@ def test_dpp_bootstrap_key_autogen_issues(dev, apdev):
dev[0].dpp_listen(2412)
with alloc_fail(dev[1], 1, "dpp_autogen_bootstrap_key"):
dev[1].dpp_auth_init(peer=id1, expect_fail=True)
with alloc_fail(dev[1], 2, "=dpp_autogen_bootstrap_key"):
with alloc_fail(dev[1], 1, "dpp_gen_uri;dpp_autogen_bootstrap_key"):
dev[1].dpp_auth_init(peer=id1, expect_fail=True)
with fail_test(dev[1], 1, "dpp_keygen;dpp_autogen_bootstrap_key"):
dev[1].dpp_auth_init(peer=id1, expect_fail=True)
@ -4198,7 +4198,7 @@ def run_dpp_bootstrap_gen_failures(dev):
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GEN type=qrcode"):
raise Exception("Command accepted unexpectedly")
with alloc_fail(dev, 2, "=" + func):
with alloc_fail(dev, 1, "dpp_gen_uri;dpp_bootstrap_gen"):
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GEN type=qrcode"):
raise Exception("Command accepted unexpectedly")