From d05c82c4d04da04653a03599aa161dd51c91fff7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Nov 2017 19:24:41 +0200 Subject: [PATCH] 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 --- src/common/dpp.c | 183 ++++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 90 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 4cbaacad9..fffd5a624 100644 --- a/src/common/dpp.c +++ b/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_bootstrap_info *bi, 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;; const EC_POINT *Y_point; 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) { 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) 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; out: + EVP_PKEY_CTX_free(ctx); BN_CTX_free(bnctx); EC_POINT_free(Qi); 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 * dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex, 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; EVP_PKEY_CTX *ctx = NULL; - size_t Jx_len, Kx_len, Lx_len; - u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN]; + size_t Jx_len, Lx_len; + u8 Jx[DPP_MAX_SHARED_SECRET_LEN]; u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; const u8 *wrapped_data, *b_key, *peer_u; 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 *B_pub = NULL; u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN]; - int res; if (!pkex->exchange_done || pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT) 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_len); 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); /* ECDH: J' = y * A' */ - EVP_PKEY_CTX_free(ctx); ctx = EVP_PKEY_CTX_new(pkex->y, NULL); if (!ctx || EVP_PKEY_derive_init(ctx) != 1 ||