}
+static int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer,
+ u8 *secret, size_t *secret_len)
+{
+ EVP_PKEY_CTX *ctx;
+ int ret = -1;
+
+ ERR_clear_error();
+ *secret_len = 0;
+
+ ctx = EVP_PKEY_CTX_new(own, NULL);
+ if (!ctx) {
+ wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+
+ if (EVP_PKEY_derive_init(ctx) != 1) {
+ wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) {
+ wpa_printf(MSG_ERROR,
+ "DPP: EVP_PKEY_derive_set_peet failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) {
+ wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+ if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
+ u8 buf[200];
+ int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG;
+
+ /* It looks like OpenSSL can return unexpectedly large buffer
+ * need for shared secret from EVP_PKEY_derive(NULL) in some
+ * cases. For example, group 19 has shown cases where secret_len
+ * is set to 72 even though the actual length ends up being
+ * updated to 32 when EVP_PKEY_derive() is called with a buffer
+ * for the value. Work around this by trying to fetch the value
+ * and continue if it is within supported range even when the
+ * initial buffer need is claimed to be larger. */
+ wpa_printf(level,
+ "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
+ (int) *secret_len);
+ if (*secret_len > 200)
+ goto fail;
+ if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) {
+ wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+ if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) {
+ wpa_printf(MSG_ERROR,
+ "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()",
+ (int) *secret_len);
+ goto fail;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change",
+ buf, *secret_len);
+ os_memcpy(secret, buf, *secret_len);
+ forced_memzero(buf, sizeof(buf));
+ goto done;
+ }
+
+ if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) {
+ wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ goto fail;
+ }
+
+done:
+ ret = 0;
+
+fail:
+ EVP_PKEY_CTX_free(ctx);
+ return ret;
+}
+
+
static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt)
{
wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt);
{
struct dpp_authentication *auth;
size_t nonce_len;
- EVP_PKEY_CTX *ctx = NULL;
size_t secret_len;
struct wpabuf *pi = NULL;
const u8 *r_pubkey_hash, *i_pubkey_hash;
goto fail;
/* ECDH: M = pI * BR */
- ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, auth->peer_bi->pubkey) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
- secret_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey,
+ auth->Mx, &secret_len) < 0)
goto fail;
- }
auth->secret_len = secret_len;
- EVP_PKEY_CTX_free(ctx);
- ctx = NULL;
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
auth->Mx, auth->secret_len);
out:
wpabuf_free(pi);
- EVP_PKEY_CTX_free(ctx);
return auth;
fail:
dpp_auth_deinit(auth);
static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
{
size_t nonce_len;
- EVP_PKEY_CTX *ctx = NULL;
size_t secret_len;
struct wpabuf *msg, *pr = NULL;
u8 r_auth[4 + DPP_MAX_HASH_LEN];
goto fail;
/* ECDH: N = pR * PI */
- ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, auth->peer_protocol_key) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
- secret_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key,
+ auth->Nx, &secret_len) < 0)
goto fail;
- }
- EVP_PKEY_CTX_free(ctx);
- ctx = NULL;
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
auth->Nx, auth->secret_len);
}
dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
- ctx = EVP_PKEY_CTX_new(own_bi->pubkey, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pi) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
- secret_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
- dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
+ if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0)
goto fail;
- }
auth->secret_len = secret_len;
- EVP_PKEY_CTX_free(ctx);
- ctx = NULL;
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
auth->Mx, auth->secret_len);
const u8 *attr_start, size_t attr_len)
{
EVP_PKEY *pr;
- EVP_PKEY_CTX *ctx = NULL;
size_t secret_len;
const u8 *addr[2];
size_t len[2];
}
dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
- ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pr) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
- secret_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) {
dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
goto fail;
}
- EVP_PKEY_CTX_free(ctx);
- ctx = NULL;
EVP_PKEY_free(auth->peer_protocol_key);
auth->peer_protocol_key = pr;
pr = NULL;
bin_clear_free(unwrapped, unwrapped_len);
bin_clear_free(unwrapped2, unwrapped2_len);
EVP_PKEY_free(pr);
- EVP_PKEY_CTX_free(ctx);
return NULL;
}
const char *pos, *end;
unsigned char *own_conn = NULL;
size_t own_conn_len;
- EVP_PKEY_CTX *ctx = NULL;
size_t Nx_len;
u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
}
/* ECDH: N = nk * PK */
- ctx = EVP_PKEY_CTX_new(own_key, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, peer_key) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Nx_len) != 1 ||
- Nx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Nx, &Nx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(own_key, peer_key, Nx, &Nx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
Nx, Nx_len);
if (ret != DPP_STATUS_OK)
os_memset(intro, 0, sizeof(*intro));
os_memset(Nx, 0, sizeof(Nx));
- EVP_PKEY_CTX_free(ctx);
os_free(own_conn);
os_free(signed_connector);
os_free(info.payload);
u8 Kx[DPP_MAX_SHARED_SECRET_LEN];
size_t Kx_len;
int res;
- EVP_PKEY_CTX *ctx = NULL;
if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
goto fail;
/* K = y * X' */
- ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
- Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
Kx, Kx_len);
pkex->exchange_done = 1;
out:
- EVP_PKEY_CTX_free(ctx);
BN_CTX_free(bnctx);
EC_POINT_free(Qi);
EC_POINT_free(Qr);
const struct dpp_curve_params *curve = pkex->own_bi->curve;
EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
BIGNUM *Nx = NULL, *Ny = NULL;
- EVP_PKEY_CTX *ctx = NULL;
EC_KEY *Y_ec = NULL;
size_t Jx_len, Kx_len;
u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
if (!pkex->y ||
EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
goto fail;
- ctx = EVP_PKEY_CTX_new(pkex->own_bi->pubkey, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pkex->y) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Jx_len) != 1 ||
- Jx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Jx, &Jx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
Jx, Jx_len);
wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
/* K = x * Y’ */
- EVP_PKEY_CTX_free(ctx);
- ctx = EVP_PKEY_CTX_new(pkex->x, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pkex->y) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
- Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
Kx, Kx_len);
BN_free(Nx);
BN_free(Ny);
EC_KEY_free(Y_ec);
- EVP_PKEY_CTX_free(ctx);
BN_CTX_free(bnctx);
EC_GROUP_free(group);
return msg;
const u8 *buf, size_t buflen)
{
const struct dpp_curve_params *curve = pkex->own_bi->curve;
- EVP_PKEY_CTX *ctx = NULL;
size_t Jx_len, Lx_len;
u8 Jx[DPP_MAX_SHARED_SECRET_LEN];
u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
pkex->peer_bootstrap_key);
/* ECDH: J' = y * A' */
- ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pkex->peer_bootstrap_key) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Jx_len) != 1 ||
- Jx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Jx, &Jx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
Jx, Jx_len);
wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
/* ECDH: L = b * X' */
- EVP_PKEY_CTX_free(ctx);
- ctx = EVP_PKEY_CTX_new(pkex->own_bi->pubkey, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Lx_len) != 1 ||
- Lx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Lx, &Lx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
Lx, Lx_len);
goto fail;
out:
- EVP_PKEY_CTX_free(ctx);
os_free(unwrapped);
wpabuf_free(A_pub);
wpabuf_free(B_pub);
u8 v[DPP_MAX_HASH_LEN];
size_t Lx_len;
u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
- EVP_PKEY_CTX *ctx = NULL;
struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
#ifdef CONFIG_TESTING_OPTIONS
pkex->peer_bootstrap_key);
/* ECDH: L' = x * B' */
- ctx = EVP_PKEY_CTX_new(pkex->x, NULL);
- if (!ctx ||
- EVP_PKEY_derive_init(ctx) != 1 ||
- EVP_PKEY_derive_set_peer(ctx, pkex->peer_bootstrap_key) != 1 ||
- EVP_PKEY_derive(ctx, NULL, &Lx_len) != 1 ||
- Lx_len > DPP_MAX_SHARED_SECRET_LEN ||
- EVP_PKEY_derive(ctx, Lx, &Lx_len) != 1) {
- wpa_printf(MSG_ERROR,
- "DPP: Failed to derive ECDH shared secret: %s",
- ERR_error_string(ERR_get_error(), NULL));
+ if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0)
goto fail;
- }
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
Lx, Lx_len);
wpabuf_free(B_pub);
wpabuf_free(X_pub);
wpabuf_free(Y_pub);
- EVP_PKEY_CTX_free(ctx);
os_free(unwrapped);
return ret;
fail: