|
@@ -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;
|
|
|
}
|
|
|
|
|
|
|