mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-25 16:58:41 -05:00
DPP: Move PKEX z derivation on Responder to earlier phase
K and z can be derived already based on information available at the time the PKEX Exchange Request is being processed, so move these there from the PKEX Commit-Reveal Request processing since that matches the DPP tech spec description close and allows PKEX exchange to be aborted earlier if anything unexpected happens. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
578c9ea1ab
commit
d05c82c4d0
183
src/common/dpp.c
183
src/common/dpp.c
@ -5752,6 +5752,65 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
||||||
|
const u8 *Mx, size_t Mx_len,
|
||||||
|
const u8 *Nx, size_t Nx_len,
|
||||||
|
const char *code,
|
||||||
|
const u8 *Kx, size_t Kx_len,
|
||||||
|
u8 *z, unsigned int hash_len)
|
||||||
|
{
|
||||||
|
u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
|
||||||
|
int res;
|
||||||
|
u8 *info, *pos;
|
||||||
|
size_t info_len;
|
||||||
|
|
||||||
|
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* HKDF-Extract(<>, IKM=K.x) */
|
||||||
|
os_memset(salt, 0, hash_len);
|
||||||
|
if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
|
||||||
|
return -1;
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
|
||||||
|
prk, hash_len);
|
||||||
|
info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
|
||||||
|
info = os_malloc(info_len);
|
||||||
|
if (!info)
|
||||||
|
return -1;
|
||||||
|
pos = info;
|
||||||
|
os_memcpy(pos, mac_init, ETH_ALEN);
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
os_memcpy(pos, mac_resp, ETH_ALEN);
|
||||||
|
pos += ETH_ALEN;
|
||||||
|
os_memcpy(pos, Mx, Mx_len);
|
||||||
|
pos += Mx_len;
|
||||||
|
os_memcpy(pos, Nx, Nx_len);
|
||||||
|
pos += Nx_len;
|
||||||
|
os_memcpy(pos, code, os_strlen(code));
|
||||||
|
|
||||||
|
/* HKDF-Expand(PRK, info, L) */
|
||||||
|
if (hash_len == 32)
|
||||||
|
res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
|
||||||
|
z, hash_len);
|
||||||
|
else if (hash_len == 48)
|
||||||
|
res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
|
||||||
|
z, hash_len);
|
||||||
|
else if (hash_len == 64)
|
||||||
|
res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
|
||||||
|
z, hash_len);
|
||||||
|
else
|
||||||
|
res = -1;
|
||||||
|
os_free(info);
|
||||||
|
os_memset(prk, 0, hash_len);
|
||||||
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
|
||||||
|
z, hash_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
||||||
struct dpp_bootstrap_info *bi,
|
struct dpp_bootstrap_info *bi,
|
||||||
const u8 *own_mac,
|
const u8 *own_mac,
|
||||||
@ -5772,6 +5831,10 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
EC_KEY *Y_ec = NULL, *X_ec = NULL;;
|
EC_KEY *Y_ec = NULL, *X_ec = NULL;;
|
||||||
const EC_POINT *Y_point;
|
const EC_POINT *Y_point;
|
||||||
BIGNUM *Nx = NULL, *Ny = NULL;
|
BIGNUM *Nx = NULL, *Ny = NULL;
|
||||||
|
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) {
|
if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) {
|
||||||
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL
|
||||||
@ -5914,9 +5977,37 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
|
|||||||
if (!pkex->exchange_resp)
|
if (!pkex->exchange_resp)
|
||||||
goto 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));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
|
||||||
|
Kx, Kx_len);
|
||||||
|
|
||||||
|
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
||||||
|
*/
|
||||||
|
res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
|
||||||
|
pkex->Mx, curve->prime_len,
|
||||||
|
pkex->Nx, curve->prime_len, pkex->code,
|
||||||
|
Kx, Kx_len, pkex->z, curve->hash_len);
|
||||||
|
os_memset(Kx, 0, Kx_len);
|
||||||
|
if (res < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
pkex->exchange_done = 1;
|
pkex->exchange_done = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
BN_CTX_free(bnctx);
|
BN_CTX_free(bnctx);
|
||||||
EC_POINT_free(Qi);
|
EC_POINT_free(Qi);
|
||||||
EC_POINT_free(Qr);
|
EC_POINT_free(Qr);
|
||||||
@ -5938,65 +6029,6 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
|
|
||||||
const u8 *Mx, size_t Mx_len,
|
|
||||||
const u8 *Nx, size_t Nx_len,
|
|
||||||
const char *code,
|
|
||||||
const u8 *Kx, size_t Kx_len,
|
|
||||||
u8 *z, unsigned int hash_len)
|
|
||||||
{
|
|
||||||
u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
|
|
||||||
int res;
|
|
||||||
u8 *info, *pos;
|
|
||||||
size_t info_len;
|
|
||||||
|
|
||||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* HKDF-Extract(<>, IKM=K.x) */
|
|
||||||
os_memset(salt, 0, hash_len);
|
|
||||||
if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
|
|
||||||
return -1;
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
|
|
||||||
prk, hash_len);
|
|
||||||
info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
|
|
||||||
info = os_malloc(info_len);
|
|
||||||
if (!info)
|
|
||||||
return -1;
|
|
||||||
pos = info;
|
|
||||||
os_memcpy(pos, mac_init, ETH_ALEN);
|
|
||||||
pos += ETH_ALEN;
|
|
||||||
os_memcpy(pos, mac_resp, ETH_ALEN);
|
|
||||||
pos += ETH_ALEN;
|
|
||||||
os_memcpy(pos, Mx, Mx_len);
|
|
||||||
pos += Mx_len;
|
|
||||||
os_memcpy(pos, Nx, Nx_len);
|
|
||||||
pos += Nx_len;
|
|
||||||
os_memcpy(pos, code, os_strlen(code));
|
|
||||||
|
|
||||||
/* HKDF-Expand(PRK, info, L) */
|
|
||||||
if (hash_len == 32)
|
|
||||||
res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
|
|
||||||
z, hash_len);
|
|
||||||
else if (hash_len == 48)
|
|
||||||
res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
|
|
||||||
z, hash_len);
|
|
||||||
else if (hash_len == 64)
|
|
||||||
res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
|
|
||||||
z, hash_len);
|
|
||||||
else
|
|
||||||
res = -1;
|
|
||||||
os_free(info);
|
|
||||||
os_memset(prk, 0, hash_len);
|
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
|
|
||||||
z, hash_len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct wpabuf *
|
static struct wpabuf *
|
||||||
dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex,
|
dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex,
|
||||||
const struct wpabuf *A_pub, const u8 *u)
|
const struct wpabuf *A_pub, const u8 *u)
|
||||||
@ -6394,8 +6426,8 @@ struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
|||||||
{
|
{
|
||||||
const struct dpp_curve_params *curve = pkex->own_bi->curve;
|
const struct dpp_curve_params *curve = pkex->own_bi->curve;
|
||||||
EVP_PKEY_CTX *ctx = NULL;
|
EVP_PKEY_CTX *ctx = NULL;
|
||||||
size_t Jx_len, Kx_len, Lx_len;
|
size_t Jx_len, Lx_len;
|
||||||
u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
|
u8 Jx[DPP_MAX_SHARED_SECRET_LEN];
|
||||||
u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
|
u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
|
||||||
const u8 *wrapped_data, *b_key, *peer_u;
|
const u8 *wrapped_data, *b_key, *peer_u;
|
||||||
u16 wrapped_data_len, b_key_len, peer_u_len = 0;
|
u16 wrapped_data_len, b_key_len, peer_u_len = 0;
|
||||||
@ -6407,39 +6439,11 @@ struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
|||||||
struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
|
struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
|
||||||
struct wpabuf *B_pub = NULL;
|
struct wpabuf *B_pub = NULL;
|
||||||
u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
|
u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
|
||||||
int res;
|
|
||||||
|
|
||||||
if (!pkex->exchange_done || pkex->failed ||
|
if (!pkex->exchange_done || pkex->failed ||
|
||||||
pkex->t >= PKEX_COUNTER_T_LIMIT)
|
pkex->t >= PKEX_COUNTER_T_LIMIT)
|
||||||
goto 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));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
|
|
||||||
Kx, Kx_len);
|
|
||||||
|
|
||||||
/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
|
|
||||||
*/
|
|
||||||
res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
|
|
||||||
pkex->Mx, curve->prime_len,
|
|
||||||
pkex->Nx, curve->prime_len, pkex->code,
|
|
||||||
Kx, Kx_len, pkex->z, curve->hash_len);
|
|
||||||
os_memset(Kx, 0, Kx_len);
|
|
||||||
if (res < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
|
wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
|
||||||
&wrapped_data_len);
|
&wrapped_data_len);
|
||||||
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
||||||
@ -6496,7 +6500,6 @@ struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
|
|||||||
pkex->peer_bootstrap_key);
|
pkex->peer_bootstrap_key);
|
||||||
|
|
||||||
/* ECDH: J' = y * A' */
|
/* ECDH: J' = y * A' */
|
||||||
EVP_PKEY_CTX_free(ctx);
|
|
||||||
ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
|
ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
|
||||||
if (!ctx ||
|
if (!ctx ||
|
||||||
EVP_PKEY_derive_init(ctx) != 1 ||
|
EVP_PKEY_derive_init(ctx) != 1 ||
|
||||||
|
Loading…
Reference in New Issue
Block a user