]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Move dppCon signing to a set of helper functions
authorJouni Malinen <jouni@codeaurora.org>
Sat, 2 May 2020 16:43:10 +0000 (19:43 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 3 May 2020 21:39:19 +0000 (00:39 +0300)
This simplifies dpp_build_conf_obj_dpp() and makes it easier to share
the signing functionality for other purposes like reconfiguration where
the Configurator needs to sign a dppCon object for itself without
generating the encapsulating config object.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/common/dpp.c

index f8b13d6f5a21cdfc2c99f5c23afed799b8aa76d5..8a7ed4bcccef2e6aaba892856951928e16fe0ce4 100644 (file)
@@ -4948,17 +4948,38 @@ static const char * dpp_netrole_str(enum dpp_netrole netrole)
 }
 
 
-static struct wpabuf *
-dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
-                      struct dpp_configuration *conf)
+static char *
+dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len)
 {
-       struct wpabuf *buf = NULL;
-       char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
-       size_t tailroom;
-       const struct dpp_curve_params *curve;
        struct wpabuf *jws_prot_hdr;
-       size_t signed1_len, signed2_len, signed3_len;
-       struct wpabuf *dppcon = NULL;
+       char *signed1;
+
+       jws_prot_hdr = wpabuf_alloc(100);
+       if (!jws_prot_hdr)
+               return NULL;
+       json_start_object(jws_prot_hdr, NULL);
+       json_add_string(jws_prot_hdr, "typ", "dppCon");
+       json_value_sep(jws_prot_hdr);
+       json_add_string(jws_prot_hdr, "kid", conf->kid);
+       json_value_sep(jws_prot_hdr);
+       json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg);
+       json_end_object(jws_prot_hdr);
+       signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
+                                   wpabuf_len(jws_prot_hdr),
+                                   signed1_len);
+       wpabuf_free(jws_prot_hdr);
+       return signed1;
+}
+
+
+static char *
+dpp_build_conn_signature(struct dpp_configurator *conf,
+                        const char *signed1, size_t signed1_len,
+                        const char *signed2, size_t signed2_len,
+                        size_t *signed3_len)
+{
+       const struct dpp_curve_params *curve;
+       char *signed3 = NULL;
        unsigned char *signature = NULL;
        const unsigned char *p;
        size_t signature_len;
@@ -4967,17 +4988,8 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
        char *dot = ".";
        const EVP_MD *sign_md;
        const BIGNUM *r, *s;
-       size_t extra_len = 1000;
-       int incl_legacy;
-       enum dpp_akm akm;
-       const char *akm_str;
 
-       if (!auth->conf) {
-               wpa_printf(MSG_INFO,
-                          "DPP: No configurator specified - cannot generate DPP config object");
-               goto fail;
-       }
-       curve = auth->conf->curve;
+       curve = conf->curve;
        if (curve->hash_len == SHA256_MAC_LEN) {
                sign_md = EVP_sha256();
        } else if (curve->hash_len == SHA384_MAC_LEN) {
@@ -4989,6 +5001,120 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
                goto fail;
        }
 
+       md_ctx = EVP_MD_CTX_create();
+       if (!md_ctx)
+               goto fail;
+
+       ERR_clear_error();
+       if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) {
+               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
+                          ERR_error_string(ERR_get_error(), NULL));
+               goto fail;
+       }
+       if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
+           EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
+           EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
+               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
+                          ERR_error_string(ERR_get_error(), NULL));
+               goto fail;
+       }
+       if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
+               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
+                          ERR_error_string(ERR_get_error(), NULL));
+               goto fail;
+       }
+       signature = os_malloc(signature_len);
+       if (!signature)
+               goto fail;
+       if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
+               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
+                          ERR_error_string(ERR_get_error(), NULL));
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
+                   signature, signature_len);
+       /* Convert to raw coordinates r,s */
+       p = signature;
+       sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
+       if (!sig)
+               goto fail;
+       ECDSA_SIG_get0(sig, &r, &s);
+       if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
+           dpp_bn2bin_pad(s, signature + curve->prime_len,
+                          curve->prime_len) < 0)
+               goto fail;
+       signature_len = 2 * curve->prime_len;
+       wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
+                   signature, signature_len);
+       signed3 = base64_url_encode(signature, signature_len, signed3_len);
+fail:
+       EVP_MD_CTX_destroy(md_ctx);
+       ECDSA_SIG_free(sig);
+       os_free(signature);
+       return signed3;
+}
+
+static char *
+dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon)
+{
+       char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
+       char *signed_conn = NULL, *pos;
+       size_t signed1_len, signed2_len, signed3_len;
+
+       signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len);
+       signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
+                                   &signed2_len);
+       if (!signed1 || !signed2)
+               goto fail;
+
+       signed3 = dpp_build_conn_signature(conf, signed1, signed1_len,
+                                          signed2, signed2_len, &signed3_len);
+       if (!signed3)
+               goto fail;
+
+       signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3);
+       if (!signed_conn)
+               goto fail;
+       pos = signed_conn;
+       os_memcpy(pos, signed1, signed1_len);
+       pos += signed1_len;
+       *pos++ = '.';
+       os_memcpy(pos, signed2, signed2_len);
+       pos += signed2_len;
+       *pos++ = '.';
+       os_memcpy(pos, signed3, signed3_len);
+       pos += signed3_len;
+       *pos = '\0';
+
+fail:
+       os_free(signed1);
+       os_free(signed2);
+       os_free(signed3);
+       return signed_conn;
+}
+
+
+static struct wpabuf *
+dpp_build_conf_obj_dpp(struct dpp_authentication *auth,
+                      struct dpp_configuration *conf)
+{
+       struct wpabuf *buf = NULL;
+       char *signed_conn = NULL;
+       size_t tailroom;
+       const struct dpp_curve_params *curve;
+       struct wpabuf *dppcon = NULL;
+       size_t extra_len = 1000;
+       int incl_legacy;
+       enum dpp_akm akm;
+       const char *akm_str;
+
+       if (!auth->conf) {
+               wpa_printf(MSG_INFO,
+                          "DPP: No configurator specified - cannot generate DPP config object");
+               goto fail;
+       }
+       curve = auth->conf->curve;
+
        akm = conf->akm;
        if (dpp_akm_ver2(akm) && auth->peer_version < 2) {
                wpa_printf(MSG_DEBUG,
@@ -5060,79 +5186,14 @@ skip_groups:
        wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
                   (const char *) wpabuf_head(dppcon));
 
-       jws_prot_hdr = wpabuf_alloc(100);
-       if (!jws_prot_hdr)
-               goto fail;
-       json_start_object(jws_prot_hdr, NULL);
-       json_add_string(jws_prot_hdr, "typ", "dppCon");
-       json_value_sep(jws_prot_hdr);
-       json_add_string(jws_prot_hdr, "kid", auth->conf->kid);
-       json_value_sep(jws_prot_hdr);
-       json_add_string(jws_prot_hdr, "alg", curve->jws_alg);
-       json_end_object(jws_prot_hdr);
-       signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr),
-                                   wpabuf_len(jws_prot_hdr),
-                                   &signed1_len);
-       wpabuf_free(jws_prot_hdr);
-       signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon),
-                                   &signed2_len);
-       if (!signed1 || !signed2)
-               goto fail;
-
-       md_ctx = EVP_MD_CTX_create();
-       if (!md_ctx)
-               goto fail;
-
-       ERR_clear_error();
-       if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL,
-                              auth->conf->csign) != 1) {
-               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
-                          ERR_error_string(ERR_get_error(), NULL));
-               goto fail;
-       }
-       if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
-           EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
-           EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
-               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
-                          ERR_error_string(ERR_get_error(), NULL));
-               goto fail;
-       }
-       if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
-               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
-                          ERR_error_string(ERR_get_error(), NULL));
-               goto fail;
-       }
-       signature = os_malloc(signature_len);
-       if (!signature)
-               goto fail;
-       if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
-               wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
-                          ERR_error_string(ERR_get_error(), NULL));
-               goto fail;
-       }
-       wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
-                   signature, signature_len);
-       /* Convert to raw coordinates r,s */
-       p = signature;
-       sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
-       if (!sig)
-               goto fail;
-       ECDSA_SIG_get0(sig, &r, &s);
-       if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
-           dpp_bn2bin_pad(s, signature + curve->prime_len,
-                          curve->prime_len) < 0)
-               goto fail;
-       signature_len = 2 * curve->prime_len;
-       wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
-                   signature, signature_len);
-       signed3 = base64_url_encode(signature, signature_len, &signed3_len);
-       if (!signed3)
+       signed_conn = dpp_sign_connector(auth->conf, dppcon);
+       if (!signed_conn)
                goto fail;
 
        incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm);
        tailroom = 1000;
        tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
-       tailroom += signed1_len + signed2_len + signed3_len;
+       tailroom += os_strlen(signed_conn);
        if (incl_legacy)
                tailroom += 1000;
        buf = dpp_build_conf_start(auth, conf, tailroom);
@@ -5151,11 +5212,7 @@ skip_groups:
                json_value_sep(buf);
        }
        wpabuf_put_str(buf, "\"signedConnector\":\"");
-       wpabuf_put_str(buf, signed1);
-       wpabuf_put_u8(buf, '.');
-       wpabuf_put_str(buf, signed2);
-       wpabuf_put_u8(buf, '.');
-       wpabuf_put_str(buf, signed3);
+       wpabuf_put_str(buf, signed_conn);
        wpabuf_put_str(buf, "\"");
        json_value_sep(buf);
        if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
@@ -5171,12 +5228,7 @@ skip_groups:
                              wpabuf_head(buf), wpabuf_len(buf));
 
 out:
-       EVP_MD_CTX_destroy(md_ctx);
-       ECDSA_SIG_free(sig);
-       os_free(signed1);
-       os_free(signed2);
-       os_free(signed3);
-       os_free(signature);
+       os_free(signed_conn);
        wpabuf_free(dppcon);
        return buf;
 fail: