[PATCH 14/21] dpp: Update connector signing to use crypto.h
Cedric Izoard
cedric.izoard at ceva-dsp.com
Mon Jun 28 09:25:31 PDT 2021
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 <cedric.izoard at ceva-dsp.com>
---
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)
{
--
2.17.0
More information about the Hostap
mailing list