Browse Source

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 <jouni@qca.qualcomm.com>
Jouni Malinen 7 years ago
parent
commit
606a8e8d57
1 changed files with 115 additions and 81 deletions
  1. 115 81
      src/common/dpp.c

+ 115 - 81
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;
 }