DPP: Allow a list of supported curves to be used in bootstrapping URI

The new DPP_BOOTSTRAP_GEN command parameter supported_curves can be used
to specify a colon separated list of supported curves. Information from
a parsed URI shows this information with a new supp_curves line in the
DPP_BOOTSTRAP_INFO output.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-04-14 16:57:11 +03:00 committed by Jouni Malinen
parent 73b41762d0
commit b0769ce61c
4 changed files with 133 additions and 6 deletions

View file

@ -345,12 +345,36 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
} }
static int dpp_parse_uri_supported_curves(struct dpp_bootstrap_info *bi,
const char *txt)
{
int val;
if (!txt)
return 0;
val = hex2num(txt[0]);
if (val < 0)
return -1;
bi->supported_curves = val;
val = hex2num(txt[1]);
if (val > 0)
bi->supported_curves |= val << 4;
wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x",
bi->supported_curves);
return 0;
}
static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
{ {
const char *pos = uri; const char *pos = uri;
const char *end; const char *end;
const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL; const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
const char *version = NULL; const char *version = NULL, *supported_curves = NULL;
struct dpp_bootstrap_info *bi; struct dpp_bootstrap_info *bi;
wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri)); wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
@ -383,6 +407,8 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
pk = pos + 2; pk = pos + 2;
else if (pos[0] == 'V' && pos[1] == ':' && !version) else if (pos[0] == 'V' && pos[1] == ':' && !version)
version = pos + 2; version = pos + 2;
else if (pos[0] == 'B' && pos[1] == ':' && !supported_curves)
supported_curves = pos + 2;
else else
wpa_hexdump_ascii(MSG_DEBUG, wpa_hexdump_ascii(MSG_DEBUG,
"DPP: Ignore unrecognized URI parameter", "DPP: Ignore unrecognized URI parameter",
@ -404,6 +430,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
dpp_parse_uri_mac(bi, mac) < 0 || dpp_parse_uri_mac(bi, mac) < 0 ||
dpp_parse_uri_info(bi, info) < 0 || dpp_parse_uri_info(bi, info) < 0 ||
dpp_parse_uri_version(bi, version) < 0 || dpp_parse_uri_version(bi, version) < 0 ||
dpp_parse_uri_supported_curves(bi, supported_curves) < 0 ||
dpp_parse_uri_pk(bi, pk) < 0) { dpp_parse_uri_pk(bi, pk) < 0) {
dpp_bootstrap_info_free(bi); dpp_bootstrap_info_free(bi);
bi = NULL; bi = NULL;
@ -604,6 +631,7 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
{ {
char macstr[ETH_ALEN * 2 + 10]; char macstr[ETH_ALEN * 2 + 10];
size_t len; size_t len;
char supp_curves[10];
len = 4; /* "DPP:" */ len = 4; /* "DPP:" */
if (bi->chan) if (bi->chan)
@ -621,11 +649,26 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
len += 4 + os_strlen(bi->pk); /* K:...;; */ len += 4 + os_strlen(bi->pk); /* K:...;; */
if (bi->supported_curves) {
u8 val = bi->supported_curves;
if (val & 0xf0) {
val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
len += os_snprintf(supp_curves, sizeof(supp_curves),
"B:%02x;", val);
} else {
len += os_snprintf(supp_curves, sizeof(supp_curves),
"B:%x;", val);
}
} else {
supp_curves[0] = '\0';
}
os_free(bi->uri); os_free(bi->uri);
bi->uri = os_malloc(len + 1); bi->uri = os_malloc(len + 1);
if (!bi->uri) if (!bi->uri)
return -1; return -1;
os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%sK:%s;;", os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
bi->chan ? "C:" : "", bi->chan ? bi->chan : "", bi->chan ? "C:" : "", bi->chan ? bi->chan : "",
bi->chan ? ";" : "", bi->chan ? ";" : "",
macstr, macstr,
@ -633,6 +676,7 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
bi->info ? ";" : "", bi->info ? ";" : "",
DPP_VERSION == 3 ? "V:3;" : DPP_VERSION == 3 ? "V:3;" :
(DPP_VERSION == 2 ? "V:2;" : ""), (DPP_VERSION == 2 ? "V:2;" : ""),
supp_curves,
bi->pk); bi->pk);
return 0; return 0;
} }
@ -4144,10 +4188,47 @@ struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
} }
static int dpp_parse_supported_curves_list(struct dpp_bootstrap_info *bi,
char *txt)
{
char *token, *context = NULL;
u8 curves = 0;
if (!txt)
return 0;
while ((token = str_token(txt, ":", &context))) {
if (os_strcmp(token, "P-256") == 0) {
curves |= BIT(DPP_BOOTSTRAP_CURVE_P_256);
} else if (os_strcmp(token, "P-384") == 0) {
curves |= BIT(DPP_BOOTSTRAP_CURVE_P_384);
} else if (os_strcmp(token, "P-521") == 0) {
curves |= BIT(DPP_BOOTSTRAP_CURVE_P_521);
} else if (os_strcmp(token, "BP-256") == 0) {
curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_256);
} else if (os_strcmp(token, "BP-384") == 0) {
curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_384);
} else if (os_strcmp(token, "BP-512") == 0) {
curves |= BIT(DPP_BOOTSTRAP_CURVE_BP_512);
} else {
wpa_printf(MSG_DEBUG, "DPP: Unsupported curve '%s'",
token);
return -1;
}
}
bi->supported_curves = curves;
wpa_printf(MSG_DEBUG, "DPP: URI supported curves: 0x%x",
bi->supported_curves);
return 0;
}
int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
{ {
char *mac = NULL, *info = NULL, *curve = NULL; char *mac = NULL, *info = NULL, *curve = NULL;
char *key = NULL; char *key = NULL, *supported_curves = NULL;
u8 *privkey = NULL; u8 *privkey = NULL;
size_t privkey_len = 0; size_t privkey_len = 0;
int ret = -1; int ret = -1;
@ -4174,6 +4255,7 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
info = get_param(cmd, " info="); info = get_param(cmd, " info=");
curve = get_param(cmd, " curve="); curve = get_param(cmd, " curve=");
key = get_param(cmd, " key="); key = get_param(cmd, " key=");
supported_curves = get_param(cmd, " supported_curves=");
if (key) { if (key) {
privkey_len = os_strlen(key) / 2; privkey_len = os_strlen(key) / 2;
@ -4187,6 +4269,7 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
dpp_parse_uri_chan_list(bi, bi->chan) < 0 || dpp_parse_uri_chan_list(bi, bi->chan) < 0 ||
dpp_parse_uri_mac(bi, mac) < 0 || dpp_parse_uri_mac(bi, mac) < 0 ||
dpp_parse_uri_info(bi, info) < 0 || dpp_parse_uri_info(bi, info) < 0 ||
dpp_parse_supported_curves_list(bi, supported_curves) < 0 ||
dpp_gen_uri(bi) < 0) dpp_gen_uri(bi) < 0)
goto fail; goto fail;
@ -4199,6 +4282,7 @@ fail:
os_free(mac); os_free(mac);
os_free(info); os_free(info);
str_clear_free(key); str_clear_free(key);
os_free(supported_curves);
bin_clear_free(privkey, privkey_len); bin_clear_free(privkey, privkey_len);
dpp_bootstrap_info_free(bi); dpp_bootstrap_info_free(bi);
return ret; return ret;
@ -4253,12 +4337,43 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id,
{ {
struct dpp_bootstrap_info *bi; struct dpp_bootstrap_info *bi;
char pkhash[2 * SHA256_MAC_LEN + 1]; char pkhash[2 * SHA256_MAC_LEN + 1];
char supp_curves[100];
bi = dpp_bootstrap_get_id(dpp, id); bi = dpp_bootstrap_get_id(dpp, id);
if (!bi) if (!bi)
return -1; return -1;
wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash, wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
SHA256_MAC_LEN); SHA256_MAC_LEN);
supp_curves[0] = '\0';
if (bi->supported_curves) {
int ret;
size_t i;
char *pos = supp_curves;
char *end = &supp_curves[sizeof(supp_curves)];
const char *curve[6] = { "P-256", "P-384", "P-521",
"BP-256", "BP-384", "BP-512" };
ret = os_snprintf(pos, end - pos, "supp_curves=");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
for (i = 0; i < ARRAY_SIZE(curve); i++) {
if (!(bi->supported_curves & BIT(i)))
continue;
ret = os_snprintf(pos, end - pos, "%s:", curve[i]);
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (pos[-1] == ':')
pos[-1] = '\n';
else
supp_curves[0] = '\0';
}
return os_snprintf(reply, reply_size, "type=%s\n" return os_snprintf(reply, reply_size, "type=%s\n"
"mac_addr=" MACSTR "\n" "mac_addr=" MACSTR "\n"
"info=%s\n" "info=%s\n"
@ -4266,7 +4381,7 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id,
"use_freq=%u\n" "use_freq=%u\n"
"curve=%s\n" "curve=%s\n"
"pkhash=%s\n" "pkhash=%s\n"
"version=%d\n", "version=%d\n%s",
dpp_bootstrap_type_txt(bi->type), dpp_bootstrap_type_txt(bi->type),
MAC2STR(bi->mac_addr), MAC2STR(bi->mac_addr),
bi->info ? bi->info : "", bi->info ? bi->info : "",
@ -4274,7 +4389,8 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id,
bi->num_freq == 1 ? bi->freq[0] : 0, bi->num_freq == 1 ? bi->freq[0] : 0,
bi->curve->name, bi->curve->name,
pkhash, pkhash,
bi->version); bi->version,
supp_curves);
} }

View file

@ -146,6 +146,15 @@ enum dpp_bootstrap_type {
DPP_BOOTSTRAP_NFC_URI, DPP_BOOTSTRAP_NFC_URI,
}; };
enum dpp_bootstrap_supported_curves {
DPP_BOOTSTRAP_CURVE_P_256 = 0,
DPP_BOOTSTRAP_CURVE_P_384 = 1,
DPP_BOOTSTRAP_CURVE_P_521 = 2,
DPP_BOOTSTRAP_CURVE_BP_256 = 3,
DPP_BOOTSTRAP_CURVE_BP_384 = 4,
DPP_BOOTSTRAP_CURVE_BP_512 = 5,
};
struct dpp_bootstrap_info { struct dpp_bootstrap_info {
struct dl_list list; struct dl_list list;
unsigned int id; unsigned int id;
@ -159,6 +168,7 @@ struct dpp_bootstrap_info {
unsigned int num_freq; unsigned int num_freq;
bool channels_listed; bool channels_listed;
u8 version; u8 version;
u8 supported_curves; /* enum dpp_bootstrap_supported_curves bitmap */
int own; int own;
struct crypto_ec_key *pubkey; struct crypto_ec_key *pubkey;
u8 pubkey_hash[SHA256_MAC_LEN]; u8 pubkey_hash[SHA256_MAC_LEN];

View file

@ -13,7 +13,7 @@
#include "common.h" #include "common.h"
static int hex2num(char c) int hex2num(char c)
{ {
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
return c - '0'; return c - '0';

View file

@ -477,6 +477,7 @@ int hwaddr_aton(const char *txt, u8 *addr);
int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable); int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable);
int hwaddr_compact_aton(const char *txt, u8 *addr); int hwaddr_compact_aton(const char *txt, u8 *addr);
int hwaddr_aton2(const char *txt, u8 *addr); int hwaddr_aton2(const char *txt, u8 *addr);
int hex2num(char c);
int hex2byte(const char *hex); int hex2byte(const char *hex);
int hexstr2bin(const char *hex, u8 *buf, size_t len); int hexstr2bin(const char *hex, u8 *buf, size_t len);
void inc_byte_array(u8 *counter, size_t len); void inc_byte_array(u8 *counter, size_t len);