From patchwork Mon Jun 28 16:25:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cedric Izoard X-Patchwork-Id: 1498061 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=XAvBxWiW; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ceva-dsp.com header.i=@ceva-dsp.com header.a=rsa-sha256 header.s=mail header.b=C1nGsuXa; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GDCq941w3z9sVp for ; Tue, 29 Jun 2021 02:33:57 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:To:From:Reply-To:Cc:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ChEAR1ew2xqsQpHfg9ncZ9K3cYjmHkMN02I4P7/7b5w=; b=XAvBxWiWWBkq+a Ou2s610zQt5gbi/AOxaXDS0ZuC1LD5zUxZ2Is4xUXQ0QLkss8mWjY37Kbkz2zgCwwtIti8ESPkImK uriq4UaNEJ6BOAX2j+gippUvriYBJzwpXQY3Nt9Qn0fYY+iofa6HPvgrqfQrIKypYfUFkwQQxtRLX fhl0QIemXmZK8YzqZNTm8O98/Z6OnMpe8DdYy7/p8gyVfHNPB9BJR2INGsNlYLgIc6FrGKOR4zaty dm/ZT1gk72w/+s9um3ToWgH8d0WINe4STLAIaEjq8F5qxQq6OBcX/j8+lJRD6PvISS5aW733vE43Y yF7vnSDFgdIhDi/V3R1Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1lxuB2-008cpt-KA; Mon, 28 Jun 2021 16:32:05 +0000 Received: from mxil.ceva-dsp.com ([195.82.129.9]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lxu5H-008alG-Gt for hostap@lists.infradead.org; Mon, 28 Jun 2021 16:26:10 +0000 DKIM-Signature: v=1; a=rsa-sha256; d=ceva-dsp.com; s=mail; c=relaxed/simple; q=dns/txt; i=@ceva-dsp.com; t=1624897549; x=1627489549; h=From:Sender:Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=uo27Y13KgC5yZV9JBstyNzif6t4sMfrVzaV/XaEJk+k=; b=C1nGsuXaSG4Wo06qu+4ecs69xcWk4frxum/vrcNGwUI5D73whHoks6pw7H7c1Hv1 DWFymsH0LKd0FPwpp/uH3ZUii1BGc9VC5chMKCw0sTpkEs3RoC7YG3IRHLEQq/mU QAaf1i8r6P9DOaL/gYn2dASONpxfFhZBZNEEywV+weU=; X-AuditID: c3528109-8b7e670000004490-69-60d9f80d8e22 Received: from Mail-IL1.corp.local (Mail-IL1.corp.local [192.168.61.11]) by mxil.ceva-dsp.com (CEVA eMail Gateway) with SMTP id 36.2B.17552.D08F9D06; Mon, 28 Jun 2021 19:25:49 +0300 (IDT) Received: from valium.corp.local (192.168.140.70) by Mail-IL1.corp.local (192.168.61.31) with Microsoft SMTP Server id 15.1.2176.14; Mon, 28 Jun 2021 19:25:48 +0300 From: Cedric Izoard To: Subject: [PATCH 14/21] dpp: Update connector signing to use crypto.h Date: Mon, 28 Jun 2021 18:25:31 +0200 Message-ID: <20210628162538.21067-15-cedric.izoard@ceva-dsp.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20210628162538.21067-1-cedric.izoard@ceva-dsp.com> References: <20210628162538.21067-1-cedric.izoard@ceva-dsp.com> MIME-Version: 1.0 X-TM-AS-Product-Ver: SMEX-12.5.0.1684-8.6.1018-26244.007 X-TM-AS-Result: No-8.480400-4.000000-10 X-TMASE-MatchedRID: djTJXvzTDSe9TGmwrVcPSwrcxrzwsv5uTEFC0zV7bKTXLRpcXl5f6Aeu SGhEYtH1eQrcH5KVRJ3bD0X+5QL5NdfjMZoQKrxg8G8CATEgS6Y/pOSL72dTfwdkFovAReUog9x e4gtUJtptIv0A3hSOW6peFvl7iFd6tj6iWm5m5ksaPMGCcVm9DhA5wxKjT3bqw1abgzWsDaYyPG HCA/ugLQpLGykC1l3C1IK9WU5wBDZsNL4m3BkfhwKDWtq/hHcNEg7si725wwYKQo6lRC5cFR87r iQs1geE7uQj048Sa8y+HoeTMBhreO8QljqNvuG6DOs94g784gcxEreX72bHnou6fTXJM2TrjxgU EedJtNM6tcWDghNdsF2AwuFj2AoKjNCnuZyJlEgwiJTf3kjwff79kuWeDe6KPPeIpQtMl0nA9u7 fv3J9YYvDu0BEKrFOo++iWQl7ChdlVUx1Cd2cjHIyzDBHWyvr64sVlliWKx8fE8yM4pjsDwtuKB GekqUpOlxBO2IcOBaMmfGs4CMayCKQNDVf98x5XGlK6UeuSOyo6oa1Wu0eulXsxvwmJQ06 X-TM-AS-User-Approved-Sender: No X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--8.480400-4.000000 X-TMASE-Version: SMEX-12.5.0.1684-8.6.1018-26244.007 X-TM-SNTS-SMTP: 5A59B611343B21DB164F27A0256ACA55273D1A31BC0291651DCC9E743B6E18E92000:9 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrOIsWRmVeSWpSXmKPExsVyYIUtty7vj5sJBouPSFisfZTmwOixeUl9 AGOUrk1SYklZcGZ6nr6dTUlOsUJxaklJZl66rZKvY6QSUCypsiCxuFi3uCAxV98uQTfjWOcx loJlFRWPls9kbWA8kdDFyMkhIWAi8Xv/TeYuRi4OIYG9jBJzbn1nA0kICaxglHjfIQxiswkY SHz9MZ8JxBYRUJDofLqdGcQWFnCRWLjiBpjNIqAq0TzrISOIzSvgIDHp4URWiAXyEs+mz2MH sTmB4j/3fWaFmG8vcWjWChaIekGJkzOfgNnMAhISB1+8YIaoUZfYuaaZBWKOhcSenhVAN3AA 2eoSb+d4gNwsIfCSReLKkg8sEHEFic8zjGHWfrwwgxHCVpW4eHMGO8y/C35dgxoZIfF45yP2 CYxis5BcMQvJFQsYmVYxCuZWZOboJaeWJeqmFBfoJefnbmIExszhoEbOHYyfl8YfYmTiYDzE KMHBrCTCK1Z1LUGINyWxsiq1KD++qDQntfgQYzIweCYyS4km5wNjNq8k3tDU3NLcyMDCwtzU 0IwIYQNzMxNzIGVsbqIkzpsmuDVBSCA9sSQ1OzW1ILUIZgsTByfIFVxSIsWpeSmpRYmlJRnx oDQSXwxMJFINjLwKMh97PkyLiNF6zFLX/v3Zc/F2GRkOI5OZ3/+dfCLE13FFnN9/x4/jvmrX vhZZpKT1n9Pg/ckyPdj6eAHL6z7HZ8f3n5GKiLnJtpOBt1Thm+9m6RvOJ56vCcp70pkexLBC MUNxzlKZuktCdi7isguupuX5XqjQOPnXIPj09KrCt5XZ+x67KbEUZyQaajEXFScCANm2/Bbq AgAA X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210628_092608_032758_E2071516 X-CRM114-Status: GOOD ( 20.80 ) X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Add 2 new functions in crypto.h that "wraps" around already defined signing function with (r, s) interface instead of DER Ecdsa-Sig-Value. Using those functions implies to compute the hash to sign manually before. Content analysis details: (-0.2 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add 2 new functions in crypto.h that "wraps" around already defined signing function with (r,s) interface instead of DER Ecdsa-Sig-Value. Using those functions implies to compute the hash to sign manually before. Signed-off-by: Cedric Izoard --- src/common/dpp_crypto.c | 195 +++++++++++------------------------- src/crypto/crypto.h | 27 +++++ src/crypto/crypto_openssl.c | 106 ++++++++++++++++++++ 3 files changed, 194 insertions(+), 134 deletions(-) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index ef9aa14bc..1844ae7e7 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -29,24 +29,6 @@ LIBRESSL_VERSION_NUMBER < 0x20700000L) /* Compatibility wrappers for older versions. */ -static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) -{ - sig->r = r; - sig->s = s; - return 1; -} - - -static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, - const BIGNUM **ps) -{ - if (pr) - *pr = sig->r; - if (ps) - *ps = sig->s; -} - - static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) @@ -710,7 +692,7 @@ fail: static struct wpabuf * dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, const u8 *prot_hdr, u16 prot_hdr_len, - const EVP_MD **ret_md) + int *hash_func) { struct json_token *root, *token; struct wpabuf *kid = NULL; @@ -757,16 +739,15 @@ dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, } if (os_strcmp(token->string, "ES256") == 0 || os_strcmp(token->string, "BS256") == 0) - *ret_md = EVP_sha256(); + *hash_func = CRYPTO_HASH_ALG_SHA256; else if (os_strcmp(token->string, "ES384") == 0 || os_strcmp(token->string, "BS384") == 0) - *ret_md = EVP_sha384(); + *hash_func = CRYPTO_HASH_ALG_SHA384; else if (os_strcmp(token->string, "ES512") == 0 || os_strcmp(token->string, "BS512") == 0) - *ret_md = EVP_sha512(); - else - *ret_md = NULL; - if (!*ret_md) { + *hash_func = CRYPTO_HASH_ALG_SHA512; + else { + *hash_func = -1; wpa_printf(MSG_DEBUG, "DPP: Unsupported JWS Protected Header alg=%s", token->string); @@ -827,27 +808,12 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, const char *pos, *end, *signed_start, *signed_end; struct wpabuf *kid = NULL; unsigned char *prot_hdr = NULL, *signature = NULL; - size_t prot_hdr_len = 0, signature_len = 0; - const EVP_MD *sign_md = NULL; - unsigned char *der = NULL; - int der_len; - int res; - EVP_MD_CTX *md_ctx = NULL; - ECDSA_SIG *sig = NULL; - BIGNUM *r = NULL, *s = NULL; + size_t prot_hdr_len = 0, signature_len = 0, signed_len; + int res, hash_func = -1; const struct dpp_curve_params *curve; - const EC_KEY *eckey; - const EC_GROUP *group; - int nid; + u8 *hash = NULL; - eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *)csign_pub); - if (!eckey) - goto fail; - group = EC_KEY_get0_group(eckey); - if (!group) - goto fail; - nid = EC_GROUP_get_curve_name(group); - curve = dpp_get_curve_nid(nid); + curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub)); if (!curve) goto fail; wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); @@ -870,7 +836,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector - JWS Protected Header", prot_hdr, prot_hdr_len); - kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md); + kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func); if (!kid) { ret = DPP_STATUS_INVALID_CONNECTOR; goto fail; @@ -926,57 +892,41 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, goto fail; } - /* JWS Signature encodes the signature (r,s) as two octet strings. Need - * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ - r = BN_bin2bn(signature, signature_len / 2, NULL); - s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL); - sig = ECDSA_SIG_new(); - if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1) + hash = os_malloc(curve->hash_len); + if (!hash) goto fail; - r = NULL; - s = NULL; - der_len = i2d_ECDSA_SIG(sig, &der); - if (der_len <= 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len); - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) + signed_len = signed_end - signed_start + 1; + if (hash_func == CRYPTO_HASH_ALG_SHA256) + res = sha256_vector(1, (const u8**)&signed_start, &signed_len, hash); + else if (hash_func == CRYPTO_HASH_ALG_SHA384) + res = sha384_vector(1, (const u8**)&signed_start, &signed_len, hash); + else if (hash_func == CRYPTO_HASH_ALG_SHA512) + res = sha512_vector(1, (const u8**)&signed_start, &signed_len, hash); + else goto fail; - ERR_clear_error(); - if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, (EVP_PKEY *)csign_pub) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestVerifyUpdate(md_ctx, signed_start, - signed_end - signed_start + 1) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s", - ERR_error_string(ERR_get_error(), NULL)); + if (res) goto fail; - } - res = EVP_DigestVerifyFinal(md_ctx, der, der_len); + + res = crypto_ec_key_verify_signature_r_s(csign_pub, hash, curve->hash_len, + signature, signature_len / 2, + signature + signature_len / 2, + signature_len / 2); if (res != 1) { wpa_printf(MSG_DEBUG, - "DPP: EVP_DigestVerifyFinal failed (res=%d): %s", - res, ERR_error_string(ERR_get_error(), NULL)); + "DPP: signedConnector signature check failed (res=%d)", + res); ret = DPP_STATUS_INVALID_CONNECTOR; goto fail; } ret = DPP_STATUS_OK; fail: - EVP_MD_CTX_destroy(md_ctx); + os_free(hash); os_free(prot_hdr); wpabuf_free(kid); os_free(signature); - ECDSA_SIG_free(sig); - BN_free(r); - BN_free(s); - OPENSSL_free(der); return ret; } @@ -2036,78 +1986,55 @@ dpp_build_conn_signature(struct dpp_configurator *conf, size_t *signed3_len) { const struct dpp_curve_params *curve; + struct wpabuf *sig = NULL; char *signed3 = NULL; - unsigned char *signature = NULL; - const unsigned char *p; - size_t signature_len; - EVP_MD_CTX *md_ctx = NULL; - ECDSA_SIG *sig = NULL; char *dot = "."; - const EVP_MD *sign_md; - const BIGNUM *r, *s; + const u8 *vector[3]; + size_t vector_len[3]; + u8 *hash = NULL; + int ret; + + vector[0] = (const u8 *)signed1; + vector[1] = (const u8 *)dot; + vector[2] = (const u8 *)signed2; + vector_len[0] = signed1_len; + vector_len[1] = 1; + vector_len[2] = signed2_len; curve = conf->curve; + hash = os_malloc(curve->hash_len); + if (!hash) + goto fail; if (curve->hash_len == SHA256_MAC_LEN) { - sign_md = EVP_sha256(); + ret = sha256_vector(3, vector, vector_len, hash); } else if (curve->hash_len == SHA384_MAC_LEN) { - sign_md = EVP_sha384(); + ret = sha384_vector(3, vector, vector_len, hash); } else if (curve->hash_len == SHA512_MAC_LEN) { - sign_md = EVP_sha512(); + ret = sha512_vector(3, vector, vector_len, hash); } else { wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 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, (EVP_PKEY *)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)); + if (ret) { + wpa_printf(MSG_DEBUG, "DPP: Hash computation failed"); 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)); + wpa_hexdump(MSG_DEBUG, "HASH: ", hash, curve->hash_len); + + sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len); + if (!sig) { + wpa_printf(MSG_ERROR, "DPP: Signature computation failed"); 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); + wpabuf_head(sig), wpabuf_len(sig)); + signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig), signed3_len); + fail: - EVP_MD_CTX_destroy(md_ctx); - ECDSA_SIG_free(sig); - os_free(signature); + os_free(hash); + wpabuf_free(sig); return signed3; } diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index c87cbcbe8..889d0ef0e 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -1090,6 +1090,18 @@ const struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_ec_key * struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, size_t len); +/** + * crypto_ec_key_sign_r_s - Sign a buffer with an EC key + * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen() + * @data: Data to sign + * @len: Length of @data buffer + * Returns: Buffer with r and s value concatenated in a buffer. Each value + * is in big endian byte order padded to the length of the prime defined the + * group of the key. + */ +struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, const u8 *data, + size_t len); + /** * crypto_ec_key_verify_signature - Verify signature * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen() @@ -1102,6 +1114,21 @@ struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *sig, size_t sig_len); +/** + * crypto_ec_key_verify_signature_r_s - Verify signature + * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen() + * @data: Data to signed + * @len: Length of @data buffer + * @r: Binary data, in big endian byte order, of the 'r' field of the ECDSA signature. + * @s: Binary data, in big endian byte order, of the 's' field of the ECDSA signature. + * @r_len: Length of @r buffer + * @s_len: Length of @s buffer + * Returns: 1 if signature is valid, 0 if signature is invalid and -1 on failure + */ +int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *r, size_t r_len, + const u8 *s, size_t s_len); + /** * crypto_ec_key_group - Get IANA group identifier for an EC key * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen() diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index bca512f6c..12b025593 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -88,6 +88,24 @@ static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) return NULL; return pkey->pkey.ec; } + + +static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + sig->r = r; + sig->s = s; + return 1; +} + + +static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, + const BIGNUM **ps) +{ + if (pr) + *pr = sig->r; + if (ps) + *ps = sig->s; +} #endif /* CONFIG_ECC */ #endif /* OpenSSL version < 1.1.0 */ @@ -2599,6 +2617,61 @@ struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, } +struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, const u8 *data, + size_t len) +{ + const EC_GROUP *group = NULL; + const EC_KEY *eckey = NULL; + BIGNUM *prime = NULL; + ECDSA_SIG *sig = NULL; + const BIGNUM *r, *s; + u8 *r_buf, *s_buf; + struct wpabuf *buf; + const unsigned char *p; + int prime_len; + + buf = crypto_ec_key_sign(key, data, len); + if (!buf) + return NULL; + + // Extract (r,s) from Ecdsa-Sig-Value + eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *)key); + if (!eckey) + goto fail; + group = EC_KEY_get0_group(eckey); + prime = BN_new(); + if (!prime || !group || + !EC_GROUP_get_curve_GFp(group, prime, NULL, NULL, NULL)) + goto fail; + prime_len = BN_num_bytes(prime); + + p = wpabuf_head(buf); + sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf)); + if (!sig) + goto fail; + ECDSA_SIG_get0(sig, &r, &s); + + // re-use wpabuf returned by crypto_ec_key_sign + buf->used = 0; + r_buf = wpabuf_put(buf, prime_len); + s_buf = wpabuf_put(buf, prime_len); + + if (!r_buf || !s_buf || + (crypto_bignum_to_bin((const struct crypto_bignum *)r, r_buf, prime_len, prime_len) < 0) || + (crypto_bignum_to_bin((const struct crypto_bignum *)s, s_buf, prime_len, prime_len) < 0)) + goto fail; + +out: + BN_free(prime); + ECDSA_SIG_free(sig); + return buf; +fail: + wpabuf_clear_free(buf); + buf = NULL; + goto out; +} + + int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *sig, size_t sig_len) { @@ -2620,6 +2693,39 @@ int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, return -1; } +int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *r, size_t r_len, + const u8 *s, size_t s_len) +{ + ECDSA_SIG *sig = NULL; + BIGNUM *r_bn = NULL, *s_bn = NULL; + unsigned char *der = NULL; + int der_len; + int ret = -1; + + r_bn = BN_bin2bn(r, r_len, NULL); + s_bn = BN_bin2bn(s, s_len, NULL); + sig = ECDSA_SIG_new(); + if (!r_bn || !s_bn || !sig || ECDSA_SIG_set0(sig, r_bn, s_bn) != 1) + goto fail; + r_bn = NULL; + s_bn = NULL; + + der_len = i2d_ECDSA_SIG(sig, &der); + if (der_len <= 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); + goto fail; + } + + ret = crypto_ec_key_verify_signature(key, data, len, der, der_len); + +fail: + OPENSSL_free(der); + BN_free(r_bn); + BN_free(s_bn); + ECDSA_SIG_free(sig); + return ret; +} int crypto_ec_key_group(struct crypto_ec_key *key) {