}
-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;
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)
#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;
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
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);
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;
}