From: Jouni Malinen Date: Sun, 22 Oct 2017 14:08:25 +0000 (+0300) Subject: DPP: Move Authentication Request building into a separate function X-Git-Tag: hostap_2_7~960 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=606a8e8d5736962f616b4bc55b1ae75b725bdcfa;p=thirdparty%2Fhostap.git DPP: Move Authentication Request building into a separate function This cleans up dpp_auth_init() a bit by separating initialization steps for a DPP authentication session from the code needed to build the frame. In addition, this makes it easier to remove some of the attributes for protocol testing purposes. Signed-off-by: Jouni Malinen --- diff --git a/src/common/dpp.c b/src/common/dpp.c index b15b172ed..0d5c561ed 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1339,16 +1339,13 @@ static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, } -struct dpp_authentication * dpp_auth_init(void *msg_ctx, - struct dpp_bootstrap_info *peer_bi, - struct dpp_bootstrap_info *own_bi, - int configurator) +static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, + const struct wpabuf *pi, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash) { - struct dpp_authentication *auth; - size_t nonce_len; - EVP_PKEY_CTX *ctx = NULL; - size_t secret_len; - struct wpabuf *msg, *pi = NULL; + struct wpabuf *msg; u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; u8 *pos; @@ -1356,57 +1353,8 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, size_t len[2], siv_len, attr_len; u8 *attr_start, *attr_end; - auth = os_zalloc(sizeof(*auth)); - if (!auth) - return NULL; - auth->msg_ctx = msg_ctx; - auth->initiator = 1; - auth->configurator = configurator; - auth->peer_bi = peer_bi; - auth->own_bi = own_bi; - auth->curve = peer_bi->curve; - - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->i_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); - - auth->own_protocol_key = dpp_gen_keypair(auth->curve); - if (!auth->own_protocol_key) - goto fail; - - pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (!pi) - 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)); - 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); - - if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, - auth->curve->hash_len) < 0) - goto fail; - /* Build DPP Authentication Request frame attributes */ - attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) + + attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) + 4 + sizeof(wrapped_data); #ifdef CONFIG_TESTING_OPTIONS if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) @@ -1414,33 +1362,34 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, #endif /* CONFIG_TESTING_OPTIONS */ msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); if (!msg) - goto fail; - auth->req_msg = msg; + return NULL; attr_start = wpabuf_put(msg, 0); /* Responder Bootstrapping Key Hash */ - wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH); - wpabuf_put_le16(msg, SHA256_MAC_LEN); - wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + if (r_pubkey_hash) { + wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, r_pubkey_hash, SHA256_MAC_LEN); + } /* Initiator Bootstrapping Key Hash */ - wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); - wpabuf_put_le16(msg, SHA256_MAC_LEN); - if (auth->own_bi) - wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN); - else - os_memset(wpabuf_put(msg, SHA256_MAC_LEN), 0, SHA256_MAC_LEN); + if (i_pubkey_hash) { + wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, i_pubkey_hash, SHA256_MAC_LEN); + } /* Initiator Protocol Key */ - wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); - wpabuf_put_le16(msg, wpabuf_len(pi)); - wpabuf_put_buf(msg, pi); - wpabuf_free(pi); - pi = NULL; + if (pi) { + wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pi)); + wpabuf_put_buf(msg, pi); + } /* Wrapped data ({I-nonce, I-capabilities}k1) */ pos = clear; + /* I-nonce */ WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); pos += 2; @@ -1448,12 +1397,13 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, pos += 2; os_memcpy(pos, auth->i_nonce, nonce_len); pos += nonce_len; + /* I-capabilities */ WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES); pos += 2; WPA_PUT_LE16(pos, 1); pos += 2; - auth->i_capab = configurator ? DPP_CAPAB_CONFIGURATOR : + auth->i_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR : DPP_CAPAB_ENROLLEE; *pos++ = auth->i_capab; #ifdef CONFIG_TESTING_OPTIONS @@ -1478,8 +1428,10 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, siv_len = pos - clear; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, - 2, addr, len, wrapped_data) < 0) - goto fail; + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } siv_len += AES_BLOCK_SIZE; wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", wrapped_data, siv_len); @@ -1499,12 +1451,94 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, wpa_hexdump_buf(MSG_DEBUG, "DPP: Authentication Request frame attributes", msg); - return auth; -fail: + return msg; +} + + +struct dpp_authentication * dpp_auth_init(void *msg_ctx, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + int configurator) +{ + struct dpp_authentication *auth; + size_t nonce_len; + EVP_PKEY_CTX *ctx = NULL; + size_t secret_len; + struct wpabuf *pi = NULL; + u8 zero[SHA256_MAC_LEN]; + const u8 *r_pubkey_hash, *i_pubkey_hash; + + auth = os_zalloc(sizeof(*auth)); + if (!auth) + return NULL; + auth->msg_ctx = msg_ctx; + auth->initiator = 1; + auth->configurator = configurator; + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = peer_bi->curve; + + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); + + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + if (!auth->own_protocol_key) + goto fail; + + pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pi) + 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)); + 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); + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + + if (auth->own_bi) { + i_pubkey_hash = auth->own_bi->pubkey_hash; + } else { + os_memset(zero, 0, SHA256_MAC_LEN); + i_pubkey_hash = zero; + } + + auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, + i_pubkey_hash); + if (!auth->req_msg) + goto fail; + +out: wpabuf_free(pi); EVP_PKEY_CTX_free(ctx); + return auth; +fail: dpp_auth_deinit(auth); - return NULL; + auth = NULL; + goto out; }