]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Allow a list of supported curves to be used in bootstrapping URI
authorJouni Malinen <quic_jouni@quicinc.com>
Thu, 14 Apr 2022 13:57:11 +0000 (16:57 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 14 Apr 2022 13:57:11 +0000 (16:57 +0300)
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>
src/common/dpp.c
src/common/dpp.h
src/utils/common.c
src/utils/common.h

index a5165b9b3701f25494b074f1e2701e2df27ad14a..460d138a2b163cbc7bfd659002f3f545f105949a 100644 (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)
 {
        const char *pos = uri;
        const char *end;
        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;
 
        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;
                else if (pos[0] == 'V' && pos[1] == ':' && !version)
                        version = pos + 2;
+               else if (pos[0] == 'B' && pos[1] == ':' && !supported_curves)
+                       supported_curves = pos + 2;
                else
                        wpa_hexdump_ascii(MSG_DEBUG,
                                          "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_info(bi, info) < 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_bootstrap_info_free(bi);
                bi = NULL;
@@ -604,6 +631,7 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
 {
        char macstr[ETH_ALEN * 2 + 10];
        size_t len;
+       char supp_curves[10];
 
        len = 4; /* "DPP:" */
        if (bi->chan)
@@ -621,11 +649,26 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
 #endif /* CONFIG_DPP2 */
        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);
        bi->uri = os_malloc(len + 1);
        if (!bi->uri)
                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 ? ";" : "",
                    macstr,
@@ -633,6 +676,7 @@ int dpp_gen_uri(struct dpp_bootstrap_info *bi)
                    bi->info ? ";" : "",
                    DPP_VERSION == 3 ? "V:3;" :
                    (DPP_VERSION == 2 ? "V:2;" : ""),
+                   supp_curves,
                    bi->pk);
        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)
 {
        char *mac = NULL, *info = NULL, *curve = NULL;
-       char *key = NULL;
+       char *key = NULL, *supported_curves = NULL;
        u8 *privkey = NULL;
        size_t privkey_len = 0;
        int ret = -1;
@@ -4174,6 +4255,7 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd)
        info = get_param(cmd, " info=");
        curve = get_param(cmd, " curve=");
        key = get_param(cmd, " key=");
+       supported_curves = get_param(cmd, " supported_curves=");
 
        if (key) {
                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_mac(bi, mac) < 0 ||
            dpp_parse_uri_info(bi, info) < 0 ||
+           dpp_parse_supported_curves_list(bi, supported_curves) < 0 ||
            dpp_gen_uri(bi) < 0)
                goto fail;
 
@@ -4199,6 +4282,7 @@ fail:
        os_free(mac);
        os_free(info);
        str_clear_free(key);
+       os_free(supported_curves);
        bin_clear_free(privkey, privkey_len);
        dpp_bootstrap_info_free(bi);
        return ret;
@@ -4253,12 +4337,43 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id,
 {
        struct dpp_bootstrap_info *bi;
        char pkhash[2 * SHA256_MAC_LEN + 1];
+       char supp_curves[100];
 
        bi = dpp_bootstrap_get_id(dpp, id);
        if (!bi)
                return -1;
        wpa_snprintf_hex(pkhash, sizeof(pkhash), bi->pubkey_hash,
                         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"
                           "mac_addr=" MACSTR "\n"
                           "info=%s\n"
@@ -4266,7 +4381,7 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id,
                           "use_freq=%u\n"
                           "curve=%s\n"
                           "pkhash=%s\n"
-                          "version=%d\n",
+                          "version=%d\n%s",
                           dpp_bootstrap_type_txt(bi->type),
                           MAC2STR(bi->mac_addr),
                           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->curve->name,
                           pkhash,
-                          bi->version);
+                          bi->version,
+                          supp_curves);
 }
 
 
index 72899f9f95ddef93bc17b1cdc78039e28bdc1375..2950de79eca8f2204a3a40010df00b2e2970380e 100644 (file)
@@ -146,6 +146,15 @@ enum dpp_bootstrap_type {
        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 dl_list list;
        unsigned int id;
@@ -159,6 +168,7 @@ struct dpp_bootstrap_info {
        unsigned int num_freq;
        bool channels_listed;
        u8 version;
+       u8 supported_curves; /* enum dpp_bootstrap_supported_curves bitmap */
        int own;
        struct crypto_ec_key *pubkey;
        u8 pubkey_hash[SHA256_MAC_LEN];
index 2c12751938e531eb6f1f5fa26a1c765b5b8a74c0..6acfcbd898429c4c938a4cdfcb64830efc0d2ce7 100644 (file)
@@ -13,7 +13,7 @@
 #include "common.h"
 
 
-static int hex2num(char c)
+int hex2num(char c)
 {
        if (c >= '0' && c <= '9')
                return c - '0';
index 45f72bb30984e089620433c8123b0279f9673148..435a9a84cac4d2e828bfda8462a189724484dc67 100644 (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_compact_aton(const char *txt, u8 *addr);
 int hwaddr_aton2(const char *txt, u8 *addr);
+int hex2num(char c);
 int hex2byte(const char *hex);
 int hexstr2bin(const char *hex, u8 *buf, size_t len);
 void inc_byte_array(u8 *counter, size_t len);