OpenSSL: Implement crypto_ecdh routines without EC_KEY for OpenSSL 3.0
OpenSSL 3.0 has deprecated the low-level EC_KEY functionality, so use the EVP API (EVP_EC_gen() and EV_PKEY_derive()) for the crypto_ecdh wrappers. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
fc96f6802e
commit
b062507670
1 changed files with 120 additions and 1 deletions
|
@ -122,7 +122,9 @@ static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
|
||||||
#endif /* OpenSSL version < 1.1.0 */
|
#endif /* OpenSSL version < 1.1.0 */
|
||||||
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10101000L
|
#if OPENSSL_VERSION_NUMBER < 0x10101000L || \
|
||||||
|
(defined(LIBRESSL_VERSION_NUMBER) && \
|
||||||
|
LIBRESSL_VERSION_NUMBER < 0x30400000L)
|
||||||
|
|
||||||
static int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
|
static int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
|
||||||
const EC_POINT *point, BIGNUM *x,
|
const EC_POINT *point, BIGNUM *x,
|
||||||
|
@ -2570,6 +2572,33 @@ struct crypto_ecdh {
|
||||||
|
|
||||||
struct crypto_ecdh * crypto_ecdh_init(int group)
|
struct crypto_ecdh * crypto_ecdh_init(int group)
|
||||||
{
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
struct crypto_ecdh *ecdh;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
ecdh = os_zalloc(sizeof(*ecdh));
|
||||||
|
if (!ecdh)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ecdh->ec = crypto_ec_init(group);
|
||||||
|
if (!ecdh->ec)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
name = OSSL_EC_curve_nid2name(ecdh->ec->nid);
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ecdh->pkey = EVP_EC_gen(name);
|
||||||
|
if (!ecdh->pkey)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ecdh;
|
||||||
|
fail:
|
||||||
|
crypto_ecdh_deinit(ecdh);
|
||||||
|
ecdh = NULL;
|
||||||
|
goto done;
|
||||||
|
#else /* OpenSSL version >= 3.0 */
|
||||||
struct crypto_ecdh *ecdh;
|
struct crypto_ecdh *ecdh;
|
||||||
EVP_PKEY *params = NULL;
|
EVP_PKEY *params = NULL;
|
||||||
EC_KEY *ec_params = NULL;
|
EC_KEY *ec_params = NULL;
|
||||||
|
@ -2624,11 +2653,32 @@ fail:
|
||||||
crypto_ecdh_deinit(ecdh);
|
crypto_ecdh_deinit(ecdh);
|
||||||
ecdh = NULL;
|
ecdh = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
|
#endif /* OpenSSL version >= 3.0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
|
struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
|
||||||
{
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
struct crypto_ecdh *ecdh;
|
||||||
|
|
||||||
|
ecdh = os_zalloc(sizeof(*ecdh));
|
||||||
|
if (!ecdh)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ecdh->ec = crypto_ec_init(group);
|
||||||
|
if (!ecdh->ec)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ecdh->pkey = EVP_PKEY_dup((EVP_PKEY *) own_key);
|
||||||
|
if (!ecdh->pkey)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return ecdh;
|
||||||
|
fail:
|
||||||
|
crypto_ecdh_deinit(ecdh);
|
||||||
|
return NULL;
|
||||||
|
#else /* OpenSSL version >= 3.0 */
|
||||||
struct crypto_ecdh *ecdh;
|
struct crypto_ecdh *ecdh;
|
||||||
|
|
||||||
ecdh = os_zalloc(sizeof(*ecdh));
|
ecdh = os_zalloc(sizeof(*ecdh));
|
||||||
|
@ -2650,11 +2700,34 @@ struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key)
|
||||||
fail:
|
fail:
|
||||||
crypto_ecdh_deinit(ecdh);
|
crypto_ecdh_deinit(ecdh);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#endif /* OpenSSL version >= 3.0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
|
struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
|
||||||
{
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
struct wpabuf *buf = NULL;
|
||||||
|
unsigned char *pub;
|
||||||
|
size_t len, exp_len;
|
||||||
|
|
||||||
|
len = EVP_PKEY_get1_encoded_public_key(ecdh->pkey, &pub);
|
||||||
|
if (len == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Encoded using SECG SEC 1, Sec. 2.3.4 format */
|
||||||
|
exp_len = 1 + 2 * crypto_ec_prime_len(ecdh->ec);
|
||||||
|
if (len != exp_len) {
|
||||||
|
wpa_printf(MSG_ERROR,
|
||||||
|
"OpenSSL:%s: Unexpected encoded public key length %zu (expected %zu)",
|
||||||
|
__func__, len, exp_len);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
buf = wpabuf_alloc_copy(pub + 1, inc_y ? len - 1 : len / 2);
|
||||||
|
fail:
|
||||||
|
OPENSSL_free(pub);
|
||||||
|
return buf;
|
||||||
|
#else /* OpenSSL version >= 3.0 */
|
||||||
struct wpabuf *buf = NULL;
|
struct wpabuf *buf = NULL;
|
||||||
EC_KEY *eckey;
|
EC_KEY *eckey;
|
||||||
const EC_POINT *pubkey;
|
const EC_POINT *pubkey;
|
||||||
|
@ -2710,12 +2783,57 @@ fail:
|
||||||
wpabuf_free(buf);
|
wpabuf_free(buf);
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
|
#endif /* OpenSSL version >= 3.0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
|
struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
|
||||||
const u8 *key, size_t len)
|
const u8 *key, size_t len)
|
||||||
{
|
{
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
|
EVP_PKEY *peerkey = EVP_PKEY_new();
|
||||||
|
EVP_PKEY_CTX *ctx;
|
||||||
|
size_t res_len;
|
||||||
|
struct wpabuf *res = NULL;
|
||||||
|
u8 *peer;
|
||||||
|
|
||||||
|
/* Encode using SECG SEC 1, Sec. 2.3.4 format */
|
||||||
|
peer = os_malloc(1 + len);
|
||||||
|
if (!peer)
|
||||||
|
return NULL;
|
||||||
|
peer[0] = inc_y ? 0x04 : 0x02;
|
||||||
|
os_memcpy(peer + 1, key, len);
|
||||||
|
|
||||||
|
if (!peerkey ||
|
||||||
|
EVP_PKEY_copy_parameters(peerkey, ecdh->pkey) != 1 ||
|
||||||
|
EVP_PKEY_set1_encoded_public_key(peerkey, peer, 1 + len) != 1) {
|
||||||
|
wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_set1_encoded_public_key failed: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
EVP_PKEY_free(peerkey);
|
||||||
|
os_free(peer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
os_free(peer);
|
||||||
|
|
||||||
|
ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL);
|
||||||
|
if (!ctx ||
|
||||||
|
EVP_PKEY_derive_init(ctx) != 1 ||
|
||||||
|
EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 ||
|
||||||
|
EVP_PKEY_derive(ctx, NULL, &res_len) != 1 ||
|
||||||
|
!(res = wpabuf_alloc(res_len)) ||
|
||||||
|
EVP_PKEY_derive(ctx, wpabuf_mhead(res), &res_len) != 1) {
|
||||||
|
wpa_printf(MSG_INFO, "OpenSSL: EVP_PKEY_derive failed: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
wpabuf_free(res);
|
||||||
|
res = NULL;
|
||||||
|
} else {
|
||||||
|
wpabuf_put(res, res_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY_free(peerkey);
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return res;
|
||||||
|
#else /* OpenSSL version >= 3.0 */
|
||||||
BIGNUM *x, *y = NULL;
|
BIGNUM *x, *y = NULL;
|
||||||
EVP_PKEY_CTX *ctx = NULL;
|
EVP_PKEY_CTX *ctx = NULL;
|
||||||
EVP_PKEY *peerkey = NULL;
|
EVP_PKEY *peerkey = NULL;
|
||||||
|
@ -2804,6 +2922,7 @@ fail:
|
||||||
wpabuf_free(secret);
|
wpabuf_free(secret);
|
||||||
secret = NULL;
|
secret = NULL;
|
||||||
goto done;
|
goto done;
|
||||||
|
#endif /* OpenSSL version >= 3.0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue