[PATCH v2 09/33] FT: new rrb message format
M. Braun
michael-dev at fami-braun.de
Sat Sep 24 14:07:53 PDT 2016
From: Michael Braun <michael-dev at fami-braun.de>
Convert FT RRB into new TLV based format.
Encryption is unchanged.
Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
src/ap/wpa_auth.h | 113 ++++----
src/ap/wpa_auth_ft.c | 736 ++++++++++++++++++++++++++++++++++++---------------
src/ap/wpa_auth_i.h | 2 +-
3 files changed, 567 insertions(+), 284 deletions(-)
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 0e5ad1a..83fc305 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -38,76 +38,63 @@ struct ft_rrb_frame {
#define FT_PACKET_REQUEST 0
#define FT_PACKET_RESPONSE 1
/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */
-#define FT_PACKET_R0KH_R1KH_PULL 200
-#define FT_PACKET_R0KH_R1KH_RESP 201
-#define FT_PACKET_R0KH_R1KH_PUSH 202
-
-#define FT_R0KH_R1KH_PULL_NONCE_LEN 16
-#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
- FT_R0KH_ID_MAX_LEN + 1 + \
- WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
- ETH_ALEN)
-#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
-
-struct ft_r0kh_r1kh_pull_frame {
- u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
- u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */
- le16 data_length; /* little endian length of data (44) */
- u8 ap_address[ETH_ALEN];
+/* 200, 201 und 202 are reserved by old protocol version */
+#define FT_PACKET_R0KH_R1KH_PULL 203
+#define FT_PACKET_R0KH_R1KH_RESP 204
+#define FT_PACKET_R0KH_R1KH_PUSH 205
+
+
+/* new packet format */
+
+/* packet layout
+ * | struct ft_rrb_frame | multiple of of struct ft_rrbv1_tlv |
+ * | padding for encryption (blocksize) | 8 byte extra for keywrap |
+ * where
+ * packet_type = FT_PACKET_R0KH_R1KH*
+ * action_length = size of all struct ft_rrbv1_tlv (without final padding)
+ * (aka plaintext length)
+ * encryption: covers everything after struct ft_rrb_frame
+ */
- u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
- u8 r0kh_id[FT_R0KH_ID_MAX_LEN];
- u8 r0kh_id_len;
- u8 pmk_r0_name[WPA_PMK_NAME_LEN];
- u8 r1kh_id[FT_R1KH_ID_LEN];
- u8 s1kh_id[ETH_ALEN];
- u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */
- u8 key_wrap_extra[8];
-} STRUCT_PACKED;
+#define FT_RRB_NONCE_LEN 16
-#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
- FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \
- WPA_PMK_NAME_LEN + 2)
-#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8)
-struct ft_r0kh_r1kh_resp_frame {
- u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
- u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
- le16 data_length; /* little endian length of data (78) */
- u8 ap_address[ETH_ALEN];
+#define FT_RRB_LAST_EMPTY 0 /* placeholder */
- u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
- u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */
- u8 s1kh_id[ETH_ALEN]; /* copied from pull */
- u8 pmk_r1[PMK_LEN];
- u8 pmk_r1_name[WPA_PMK_NAME_LEN];
- le16 pairwise; /* zero if no entry found */
- u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
- u8 key_wrap_extra[8];
-} STRUCT_PACKED;
+#define FT_RRB_NONCE 1 /* size FT_RRB_NONCE_LEN */
+#define FT_RRB_TIMESTAMP 2 /* le32 unix seconds */
-#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \
- WPA_PMK_NAME_LEN + PMK_LEN + \
- WPA_PMK_NAME_LEN + 2)
-#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8)
-struct ft_r0kh_r1kh_push_frame {
- u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
- u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
- le16 data_length; /* little endian length of data (82) */
- u8 ap_address[ETH_ALEN];
+#define FT_RRB_R0KH_ID 3 /* FT_R0KH_ID_MAX_LEN */
+#define FT_RRB_R1KH_ID 4 /* FT_R1KH_ID_LEN */
+#define FT_RRB_S1KH_ID 5 /* ETH_ALEN */
+
+#define FT_RRB_PMK_R0_NAME 6 /* WPA_PMK_NAME_LEN */
+#define FT_RRB_PMK_R0 7 /* PMK_LEN */
+#define FT_RRB_PMK_R1_NAME 8 /* WPA_PMK_NAME_LEN */
+#define FT_RRB_PMK_R1 9 /* PMK_LEN */
- /* Encrypted with AES key-wrap */
- u8 timestamp[4]; /* current time in seconds since unix epoch, little
- * endian */
- u8 r1kh_id[FT_R1KH_ID_LEN];
- u8 s1kh_id[ETH_ALEN];
- u8 pmk_r0_name[WPA_PMK_NAME_LEN];
- u8 pmk_r1[PMK_LEN];
- u8 pmk_r1_name[WPA_PMK_NAME_LEN];
- le16 pairwise;
- u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */
- u8 key_wrap_extra[8];
+#define FT_RRB_PAIRWISE 10 /* le16 */
+
+struct ft_rrbv1_tlv {
+ le16 type;
+ le16 len;
+ /* followed by data of length len */
} STRUCT_PACKED;
+/* session TLVs:
+ * required: [PMK_R1, PMK_R1_NAME, PAIRWISE]
+ *
+ * pull frame TLVs:
+ * required: NONCE, R0KH_ID, PMK_R0_NAME, R1KH_ID, S1KH_ID
+ *
+ * response frame TLVs:
+ * required: NONCE, R1KH_ID, S1KH_ID,
+ * optional: all session-TLVs
+ *
+ * push frame TLVs:
+ * required: TIMESTAMP, R1KH_ID, S1KH_ID, PMK_R0_NAME,
+ * session-TLVs
+ */
+
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 0c92d40..5abe412 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -32,6 +32,232 @@ static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx);
static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx);
+/**
+ * decrypt message
+ * @data full packet
+ * @kek encryption key
+ * @plain pointer to store pointer for plaintext
+ * (only action_length many bytes)
+ * needs to be freed by caller if not null
+ * will only be returned on success
+ * @return 0 on success, -1 on error
+ */
+
+static int wpa_ft_rrb_decrypt(const u8 *kek, size_t kek_len,
+ const u8 *data, const size_t data_len,
+ u8 **plain, size_t *plain_size)
+{
+ struct ft_rrb_frame *f;
+ size_t alen, blen, clen;
+ const u8 *crypt;
+
+ *plain = NULL;
+
+ if (data_len < sizeof(*f))
+ return -1;
+
+ f = (struct ft_rrb_frame *) data;
+
+ alen = le_to_host16(f->action_length); /* plaintext length */
+ blen = alen + ((8 - (alen % 8)) % 8); /* round up to full block size */
+ clen = blen + 8; /* extra space for keywrap */
+
+ /* ciphertext (packet) long enough for given plaintext length? */
+ if (data_len - sizeof(*f) < clen)
+ return -1;
+ crypt = data + sizeof(*f);
+
+ *plain = os_zalloc(blen);
+ if (!*plain)
+ return -1;
+
+ if (!aes_unwrap(kek, kek_len, blen / 8, crypt, *plain)) {
+ *plain_size = alen;
+ return 0;
+ }
+
+ os_free(*plain);
+ *plain = NULL;
+
+ return -1;
+}
+
+
+/* get first tlv record in packet matching type
+ * @data (decrypted) packet
+ * @return 0 on success else -1
+ */
+static int wpa_ft_rrb_get_tlv(const u8 *plain, const size_t plain_len,
+ int type, size_t *tlv_len, const u8 **tlv_data)
+{
+ struct ft_rrbv1_tlv *f;
+ size_t left;
+ le16 type16;
+ size_t len;
+
+ left = plain_len;
+ type16 = host_to_le16(type);
+
+ while (left >= sizeof(*f)) {
+ f = (struct ft_rrbv1_tlv *) plain;
+
+ left -= sizeof(*f);
+ plain += sizeof(*f);
+ len = le_to_host16(f->len);
+
+ if (left < len)
+ return -1;
+
+ if (f->type == type16) {
+ *tlv_len = len;
+ *tlv_data = plain;
+ return 0;
+ }
+
+ left -= len;
+ plain += len;
+ }
+
+ return -1;
+}
+
+
+/**
+ * encrypt message
+ * @frame ft_rrb_frame
+ * @kek encryption key
+ * @plain pointer to store pointer for plaintext
+ * (only action_length many bytes)
+ * needs to be freed by caller if not null
+ * will only be returned on success
+ * @return 0 on success, -1 on error
+ */
+
+struct tlv_list {
+ int type;
+ int len;
+ const u8 *data;
+};
+
+static inline size_t wpa_ft_tlv_len(const struct tlv_list *tlvs)
+{
+ size_t tlv_len = 0;
+ int i;
+
+ if (!tlvs)
+ return 0;
+
+ for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) {
+ tlv_len += sizeof(struct ft_rrbv1_tlv);
+ tlv_len += tlvs[i].len;
+ }
+
+ return tlv_len;
+}
+
+static inline size_t wpa_ft_tlv_lin(const struct tlv_list *tlvs, u8 *start,
+ u8 *endpos)
+{
+ int i;
+ size_t tlv_len;
+ struct ft_rrbv1_tlv *hdr;
+ u8 *pos = start;
+
+ if (!tlvs)
+ return 0;
+
+ tlv_len = 0;
+ pos = start + tlv_len;
+ for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) {
+ tlv_len += sizeof(*hdr);
+ if (start + tlv_len > endpos)
+ return tlv_len;
+ hdr = (struct ft_rrbv1_tlv *) pos;
+ hdr->type = host_to_le16(tlvs[i].type);
+ hdr->len = host_to_le16(tlvs[i].len);
+ pos = start + tlv_len;
+
+ tlv_len += tlvs[i].len;
+ if (start + tlv_len > endpos)
+ return tlv_len;
+ os_memcpy(pos, tlvs[i].data, tlvs[i].len);
+ pos = start + tlv_len;
+ }
+
+ return tlv_len;
+}
+
+static int wpa_ft_rrb_build(const u8 *kek, size_t kek_len,
+ const struct ft_rrb_frame *frame,
+ const struct tlv_list *tlvs1,
+ const struct tlv_list *tlvs2,
+ u8 **packet, size_t *packet_len)
+{
+ u8 *plain, *pos, *crypt, *endpos;
+ struct ft_rrb_frame *f2;
+ size_t tlv_len, pad_len;
+
+ *packet = NULL;
+ *packet_len = 0;
+
+ tlv_len = 0;
+ tlv_len += wpa_ft_tlv_len(tlvs1);
+ tlv_len += wpa_ft_tlv_len(tlvs2);
+ pad_len = (8 - (tlv_len % 8)) % 8;
+
+ plain = os_zalloc(tlv_len + pad_len);
+ if (plain == NULL)
+ return -1;
+
+ pos = plain;
+ endpos = plain + tlv_len;
+ pos += wpa_ft_tlv_lin(tlvs1, pos, endpos);
+ pos += wpa_ft_tlv_lin(tlvs2, pos, endpos);
+
+ /* sanity check */
+ if (pos != endpos) {
+ wpa_printf(MSG_ERROR, "FT: length error building RRB");
+ os_free(plain);
+ return -1;
+ }
+
+ *packet_len = sizeof(*frame) + tlv_len + pad_len + 8;
+ *packet = os_zalloc(*packet_len);
+ if (*packet == NULL) {
+ *packet_len = 0;
+ os_free(plain);
+ return -1;
+ }
+
+ f2 = (struct ft_rrb_frame *) *packet;
+ os_memcpy(*packet, frame, sizeof(*frame));
+ f2->action_length = host_to_le16(tlv_len);
+
+ crypt = *packet + sizeof(*frame);
+
+ if (!aes_wrap(kek, kek_len, (tlv_len + 7) / 8, plain, crypt)) {
+ os_free(plain);
+ return 0;
+ }
+
+ os_free(plain);
+ os_free(*packet);
+ *packet = NULL;
+ return -1;
+}
+
+
+#define RRB_GET(type, field, txt, checklength) do { \
+ if (wpa_ft_rrb_get_tlv(plain, plain_len, type, \
+ &f_##field##_len, &f_##field) < 0 || \
+ (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
+ wpa_printf(MSG_DEBUG, "FT: Missing " #field " in PMK-R1 " \
+ "%s from " MACSTR, txt, MAC2STR(src_addr)); \
+ goto out; \
+ } \
+} while (0)
+
+
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
const u8 *data, size_t data_len)
{
@@ -241,7 +467,7 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
const u8 *spa, const u8 *pmk_r0_name,
- u8 *pmk_r0, int *pairwise)
+ const struct wpa_ft_pmk_r0_sa **r0_out)
{
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
struct wpa_ft_pmk_r0_sa *r0;
@@ -251,15 +477,14 @@ static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
WPA_PMK_NAME_LEN) == 0) {
- os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);
- if (pairwise)
- *pairwise = r0->pairwise;
+ *r0_out = r0;
return 0;
}
r0 = r0->next;
}
+ *r0_out = NULL;
return -1;
}
@@ -391,7 +616,8 @@ static void wpa_ft_rrb_del_r1kh(void *eloop_ctx, void *timeout_ctx)
static void wpa_ft_rrb_add_r1kh(struct wpa_authenticator *wpa_auth,
struct ft_remote_r1kh *r1kh_wildcard,
- const u8 *src_addr, u8 *r1kh_id, int timeout)
+ const u8 *src_addr, const u8 *r1kh_id,
+ int timeout)
{
struct ft_remote_r1kh *r1kh;
@@ -454,7 +680,9 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
const u8 *pmk_r0_name)
{
struct ft_remote_r0kh *r0kh, *r0kh_wildcard = NULL;
- struct ft_r0kh_r1kh_pull_frame frame, f;
+ struct ft_rrb_frame req_hdr;
+ u8 *packet = NULL;
+ size_t packet_len;
int tsecs, tusecs, first;
struct wpabuf *ft_pending_req_ies;
@@ -494,36 +722,36 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
"address " MACSTR, MAC2STR(r0kh->addr));
- os_memset(&frame, 0, sizeof(frame));
- frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
- frame.packet_type = FT_PACKET_R0KH_R1KH_PULL;
- frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN);
- os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN);
-
- /* aes_wrap() does not support inplace encryption, so use a temporary
- * buffer for the data. */
- if (first) {
- if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) {
- wpa_printf(MSG_DEBUG, "FT: Failed to get random data "
- "for nonce");
- return -1;
- }
- os_memcpy(sm->ft_pending_pull_nonce, f.nonce,
- FT_R0KH_R1KH_PULL_NONCE_LEN);
- } else
- os_memcpy(f.nonce, sm->ft_pending_pull_nonce,
- FT_R0KH_R1KH_PULL_NONCE_LEN);
- os_memcpy(f.r0kh_id, sm->r0kh_id, FT_R0KH_ID_MAX_LEN);
- f.r0kh_id_len = sm->r0kh_id_len;
- os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
- os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
- os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
- os_memset(f.pad, 0, sizeof(f.pad));
-
- if (aes_wrap(r0kh->key, sizeof(r0kh->key),
- (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
- f.nonce, frame.nonce) < 0)
+ os_memset(&req_hdr, 0, sizeof(req_hdr));
+ req_hdr.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
+ req_hdr.packet_type = FT_PACKET_R0KH_R1KH_PULL;
+ os_memcpy(req_hdr.ap_address, sm->wpa_auth->addr, ETH_ALEN);
+
+ if (first &&
+ random_get_bytes(sm->ft_pending_pull_nonce, FT_RRB_NONCE_LEN) < 0) {
+ wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
+ "nonce");
+ return -1;
+ }
+
+ struct tlv_list req_tlv[] = {
+ { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN,
+ .data = sm->ft_pending_pull_nonce },
+ { .type = FT_RRB_R0KH_ID, .len = sm->r0kh_id_len,
+ .data = sm->r0kh_id },
+ { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN,
+ .data = pmk_r0_name },
+ { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
+ .data = sm->wpa_auth->conf.r1_key_holder },
+ { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN,
+ .data = sm->addr },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (wpa_ft_rrb_build(r0kh->key, sizeof(r0kh->key), &req_hdr,
+ req_tlv, NULL, &packet, &packet_len) < 0) {
return -1;
+ }
ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
wpabuf_free(sm->ft_pending_req_ies);
@@ -535,7 +763,10 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
tusecs = (sm->wpa_auth->conf.rkh_pull_timeout % 1000) * 1000;
eloop_register_timeout(tsecs, tusecs, wpa_ft_expire_pull, sm, NULL);
- wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
+ wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, packet, packet_len);
+
+ os_free(packet);
+ packet = NULL;
return 0;
}
@@ -1587,23 +1818,65 @@ static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
}
+static int wpa_ft_rrb_build_r0(const u8 *kek, size_t kek_len,
+ const struct ft_rrb_frame *frame,
+ const struct tlv_list *tlvs,
+ const struct wpa_ft_pmk_r0_sa *pmk_r0,
+ const u8 *r1kh_id, const u8 *s1kh_id,
+ u8 **packet, size_t *packet_len)
+{
+ u8 pmk_r1[PMK_LEN];
+ u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+ u8 f_pairwise[sizeof(le16)];
+ int ret;
+
+ if (!pmk_r0)
+ return wpa_ft_rrb_build(kek, kek_len, frame, tlvs, NULL,
+ packet, packet_len);
+
+ wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh_id,
+ s1kh_id, pmk_r1, pmk_r1_name);
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
+ WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise);
+
+ struct tlv_list sess_tlv[] = {
+ { .type = FT_RRB_PMK_R1, .len = sizeof(pmk_r1),
+ .data = pmk_r1 },
+ { .type = FT_RRB_PMK_R1_NAME, .len = sizeof(pmk_r1_name),
+ .data = pmk_r1_name },
+ { .type = FT_RRB_PAIRWISE, .len = sizeof(f_pairwise),
+ .data = f_pairwise },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ ret = wpa_ft_rrb_build(kek, kek_len, frame, tlvs, sess_tlv,
+ packet, packet_len);
+
+ os_memset(pmk_r1, 0, sizeof(pmk_r1));
+
+ return ret;
+
+}
+
static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
const u8 *data, size_t data_len)
{
- struct ft_r0kh_r1kh_pull_frame f;
- const u8 *crypt;
- u8 *plain;
+ u8 *plain, *packet = NULL;
+ size_t plain_len, packet_len;
struct ft_remote_r1kh *r1kh, *r1kh_wildcard = NULL;
- struct ft_r0kh_r1kh_resp_frame resp, r;
- u8 pmk_r0[PMK_LEN];
- int pairwise;
-
- wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull");
+ struct ft_rrb_frame resp_hdr;
+ int ret;
+ const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id, *f_s1kh_id, *f_pmk_r0_name;
+ size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len, f_s1kh_id_len;
+ size_t f_pmk_r0_name_len;
+ struct tlv_list *sess_tlv = NULL;
+ const struct wpa_ft_pmk_r0_sa *r0;
- if (data_len < sizeof(f))
- return -1;
+ wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull request");
+ /* get key and decrypt */
if (!wpa_auth->conf.r1kh_list)
return -1;
r1kh = *wpa_auth->conf.r1kh_list;
@@ -1626,71 +1899,68 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
return -1;
}
- crypt = data + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce);
- os_memset(&f, 0, sizeof(f));
- plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce);
- /* aes_unwrap() does not support inplace decryption, so use a temporary
- * buffer for the data. */
- if (aes_unwrap(r1kh->key, sizeof(r1kh->key),
- (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
- crypt, plain) < 0) {
+ if (wpa_ft_rrb_decrypt(r1kh->key, sizeof(r1kh->key),
+ data, data_len, &plain, &plain_len) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
"request from " MACSTR, MAC2STR(src_addr));
return -1;
}
- if (f.r0kh_id_len != wpa_auth->conf.r0_key_holder_len ||
- os_memcmp_const(f.r0kh_id, wpa_auth->conf.r0_key_holder,
- f.r0kh_id_len) != 0)
- return -1;
+ RRB_GET(FT_RRB_R0KH_ID, r0kh_id, "pull request", -1);
+ if (f_r0kh_id_len != wpa_auth->conf.r0_key_holder_len ||
+ os_memcmp_const(f_r0kh_id, wpa_auth->conf.r0_key_holder,
+ f_r0kh_id_len) != 0)
+ goto out;
+ RRB_GET(FT_RRB_NONCE, nonce, "pull request", FT_RRB_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
- f.nonce, sizeof(f.nonce));
+ f_nonce, f_nonce_len);
+
+ RRB_GET(FT_RRB_PMK_R0_NAME, pmk_r0_name, "pull request",
+ WPA_PMK_NAME_LEN);
wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
- f.pmk_r0_name, WPA_PMK_NAME_LEN);
+ f_pmk_r0_name, f_pmk_r0_name_len);
+
+ RRB_GET(FT_RRB_R1KH_ID, r1kh_id, "pull request", FT_R1KH_ID_LEN);
+ RRB_GET(FT_RRB_S1KH_ID, s1kh_id, "pull request", ETH_ALEN);
wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
- MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
+ MACSTR, MAC2STR(f_r1kh_id), MAC2STR(f_s1kh_id));
if (r1kh == r1kh_wildcard && wpa_auth->conf.rkh_pos_timeout)
wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard, src_addr,
- f.r1kh_id, wpa_auth->conf.rkh_pos_timeout);
-
- os_memset(&resp, 0, sizeof(resp));
- resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
- resp.packet_type = FT_PACKET_R0KH_R1KH_RESP;
- resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN);
- os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN);
-
- /* aes_wrap() does not support inplace encryption, so use a temporary
- * buffer for the data. */
- os_memcpy(r.nonce, f.nonce, sizeof(f.nonce));
- os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN);
- os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN);
- if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0,
- &pairwise) < 0) {
- wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for "
- "PMK-R1 pull");
- r.pairwise = 0;
- } else {
- wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id,
- r.pmk_r1, r.pmk_r1_name);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
- WPA_PMK_NAME_LEN);
- r.pairwise = host_to_le16(pairwise);
- }
- os_memset(r.pad, 0, sizeof(r.pad));
-
- if (aes_wrap(r1kh->key, sizeof(r1kh->key),
- (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
- r.nonce, resp.nonce) < 0) {
- os_memset(pmk_r0, 0, PMK_LEN);
- return -1;
- }
+ f_r1kh_id, wpa_auth->conf.rkh_pos_timeout);
- os_memset(pmk_r0, 0, PMK_LEN);
+ os_memset(&resp_hdr, 0, sizeof(resp_hdr));
+ resp_hdr.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
+ resp_hdr.packet_type = FT_PACKET_R0KH_R1KH_RESP;
+ os_memcpy(resp_hdr.ap_address, wpa_auth->addr, ETH_ALEN);
- wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp));
+ struct tlv_list resp_tlv[] = {
+ { .type = FT_RRB_NONCE, .len = f_nonce_len,
+ .data = f_nonce },
+ { .type = FT_RRB_R1KH_ID, .len = f_r1kh_id_len,
+ .data = f_r1kh_id },
+ { .type = FT_RRB_S1KH_ID, .len = f_s1kh_id_len,
+ .data = f_s1kh_id },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (wpa_ft_fetch_pmk_r0(wpa_auth, f_s1kh_id, f_pmk_r0_name, &r0) < 0)
+ wpa_printf(MSG_DEBUG, "FT: No matching PMK-R0-Name found for "
+ "PMK-R1 pull request");
+
+ ret = wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), &resp_hdr,
+ resp_tlv, r0, f_r1kh_id, f_s1kh_id,
+ &packet, &packet_len);
+
+ if (!ret)
+ wpa_ft_rrb_send(wpa_auth, src_addr, packet, packet_len);
+
+out:
+
+ os_free(plain); plain = NULL;
+ os_free(packet); packet = NULL;
+ os_free(sess_tlv); sess_tlv = NULL;
return 0;
}
@@ -1730,20 +2000,21 @@ static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx)
struct ft_pull_resp_cb_ctx {
- struct ft_r0kh_r1kh_resp_frame *frame;
+ const u8 *s1kh_id;
+ const u8 *nonce;
+ int nak;
struct ft_remote_r0kh *r0kh_wildcard;
- u8 src_addr[ETH_ALEN];
+ const u8 *src_addr;
};
static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
{
struct ft_pull_resp_cb_ctx *info = ctx;
- struct ft_r0kh_r1kh_resp_frame *frame = info->frame;
- if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0)
+ if (os_memcmp(info->s1kh_id, sm->addr, ETH_ALEN) != 0)
return 0;
- if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce,
- FT_R0KH_R1KH_PULL_NONCE_LEN) != 0)
+ if (os_memcmp(info->nonce, sm->ft_pending_pull_nonce,
+ FT_RRB_NONCE_LEN) != 0)
return 0;
if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
return 0;
@@ -1751,7 +2022,7 @@ static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for "
MACSTR " - process from timeout", MAC2STR(sm->addr));
- if (frame->pairwise == 0)
+ if (info->nak)
sm->ft_pending_pull_left_retries = 0;
eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
eloop_cancel_timeout(ft_pull_resp_cb_finish, sm, NULL);
@@ -1768,24 +2039,78 @@ static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
}
+/* @returns 0 on success
+ * -1 on error
+ * -2 if FR_RRB_PAIRWISE is missing
+ */
+static int wpa_ft_rrb_rx_r1(struct wpa_authenticator *wpa_auth,
+ const u8 *src_addr,
+ const u8 *plain, size_t plain_len,
+ const char *msgtype)
+{
+ const u8 *f_r1kh_id, *f_s1kh_id;
+ const u8 *f_pmk_r1_name, *f_pairwise, *f_pmk_r1;
+ size_t f_r1kh_id_len, f_s1kh_id_len;
+ size_t f_pmk_r1_name_len, f_pairwise_len, f_pmk_r1_len;
+ int pairwise;
+ int ret = -1;
+
+ RRB_GET(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN);
+ if (os_memcmp_const(f_r1kh_id, wpa_auth->conf.r1_key_holder,
+ FT_R1KH_ID_LEN) != 0) {
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 %s did not use a matching "
+ "R1KH-ID", msgtype);
+ goto out;
+ }
+
+
+ RRB_GET(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN);
+ RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "FT: PMK-R1 %s", msgtype);
+ wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR " S1KH-ID=" MACSTR,
+ MAC2STR(f_r1kh_id), MAC2STR(f_s1kh_id));
+
+ ret = -2;
+ RRB_GET(FT_RRB_PAIRWISE, pairwise, msgtype, sizeof(le16));
+
+ ret = -1;
+ RRB_GET(FT_RRB_PMK_R1_NAME, pmk_r1_name, msgtype, WPA_PMK_NAME_LEN);
+ RRB_GET(FT_RRB_PMK_R1, pmk_r1, msgtype, PMK_LEN);
+
+ wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f_pmk_r1, PMK_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
+ f_pmk_r1_name, WPA_PMK_NAME_LEN);
+
+ pairwise = WPA_GET_LE16(f_pairwise);
+
+ if (wpa_ft_store_pmk_r1(wpa_auth, f_s1kh_id, f_pmk_r1, f_pmk_r1_name,
+ pairwise) < 0)
+ return -1;
+
+ ret = 0;
+
+out:
+ return ret;
+
+}
+
static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
const u8 *data, size_t data_len)
{
- struct ft_r0kh_r1kh_resp_frame f;
- const u8 *crypt;
u8 *plain;
+ size_t plain_len;
struct ft_remote_r0kh *r0kh, *r0kh_wildcard = NULL;
- int pairwise, res;
+ int ret, nak;
struct ft_pull_resp_cb_ctx ctx;
+ const u8 *f_nonce, *f_s1kh_id;
+ size_t f_nonce_len, f_s1kh_id_len;
wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
- if (data_len < sizeof(f))
- return -1;
-
if (!wpa_auth->conf.r0kh_list)
return -1;
+
r0kh = *wpa_auth->conf.r0kh_list;
while (r0kh) {
if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
@@ -1805,59 +2130,50 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
return -1;
}
- crypt = data + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce);
- os_memset(&f, 0, sizeof(f));
- plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce);
- /* aes_unwrap() does not support inplace decryption, so use a temporary
- * buffer for the data. */
- if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
- (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
- crypt, plain) < 0) {
+ if (wpa_ft_rrb_decrypt(r0kh->key, sizeof(r0kh->key),
+ data, data_len, &plain, &plain_len) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
"response from " MACSTR, MAC2STR(src_addr));
return -1;
}
- if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
- FT_R1KH_ID_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a "
- "matching R1KH-ID");
- return -1;
- }
+ RRB_GET(FT_RRB_NONCE, nonce, "pull response", FT_RRB_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", f_nonce, f_nonce_len);
- pairwise = le_to_host16(f.pairwise);
- if (f.pairwise == 0) {
- res = 0;
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
- f.nonce, sizeof(f.nonce));
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
- " S1KH-ID=" MACSTR " NACK",
- MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
- } else {
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
- f.nonce, sizeof(f.nonce));
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
- " S1KH-ID=" MACSTR " pairwise=0x%x",
- MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
- f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
- f.pmk_r1_name, WPA_PMK_NAME_LEN);
+ RRB_GET(FT_RRB_S1KH_ID, s1kh_id, "pull response", ETH_ALEN);
- res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1,
- f.pmk_r1_name, pairwise);
- }
+ ret = wpa_ft_rrb_rx_r1(wpa_auth, src_addr, plain, plain_len,
+ "pull response");
+
+ if (ret == -1)
+ goto out;
+
+ if (ret == -2) {
+ ret = 0;
+ nak = 1;
+ } else
+ nak = 0;
wpa_printf(MSG_DEBUG, "FT: Look for pending pull request");
- ctx.frame = &f;
- os_memcpy(ctx.src_addr, src_addr, ETH_ALEN);
+ os_memset(&ctx, 0, sizeof(ctx));
+
+ ctx.s1kh_id = f_s1kh_id;
+ ctx.nonce = f_nonce;
+ ctx.nak = nak;
+ ctx.src_addr = src_addr;
ctx.r0kh_wildcard = (r0kh == r0kh_wildcard) ? r0kh_wildcard : NULL;
wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &ctx);
- os_memset(f.pmk_r1, 0, PMK_LEN);
- return res ? 0 : -1;
+out:
+ if (plain) {
+ os_memset(plain, 0, plain_len);
+ os_free(plain);
+ plain = NULL;
+ }
+
+ return ret;
}
@@ -1865,19 +2181,17 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
const u8 *src_addr,
const u8 *data, size_t data_len)
{
- struct ft_r0kh_r1kh_push_frame f;
- const u8 *crypt;
+ int ret = -1;
u8 *plain;
+ size_t plain_len;
struct ft_remote_r0kh *r0kh, *r0kh_wildcard = NULL;
struct os_time now;
os_time_t tsend;
- int pairwise;
+ const u8 *f_timestamp;
+ size_t f_timestamp_len;
wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push");
- if (data_len < sizeof(f))
- return -1;
-
if (!wpa_auth->conf.r0kh_list)
return -1;
r0kh = *wpa_auth->conf.r0kh_list;
@@ -1899,53 +2213,36 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
return -1;
}
- crypt = data + offsetof(struct ft_r0kh_r1kh_push_frame, timestamp);
- os_memset(&f, 0, sizeof(f));
- plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame,
- timestamp);
- /* aes_unwrap() does not support inplace decryption, so use a temporary
- * buffer for the data. */
- if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
- (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
- crypt, plain) < 0) {
+ if (wpa_ft_rrb_decrypt(r0kh->key, sizeof(r0kh->key),
+ data, data_len, &plain, &plain_len) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from "
MACSTR, MAC2STR(src_addr));
return -1;
}
+ RRB_GET(FT_RRB_TIMESTAMP, timestamp, "push", sizeof(le32));
os_get_time(&now);
- tsend = WPA_GET_LE32(f.timestamp);
+ tsend = WPA_GET_LE32(f_timestamp);
if ((now.sec > tsend && now.sec - tsend > 60) ||
(now.sec < tsend && tsend - now.sec > 60)) {
wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid "
"timestamp: sender time %d own time %d\n",
(int) tsend, (int) now.sec);
- return -1;
+ goto out;
}
- if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
- FT_R1KH_ID_LEN) != 0) {
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching "
- "R1KH-ID (received " MACSTR " own " MACSTR ")",
- MAC2STR(f.r1kh_id),
- MAC2STR(wpa_auth->conf.r1_key_holder));
- return -1;
- }
+ if (wpa_ft_rrb_rx_r1(wpa_auth, src_addr, plain, plain_len,
+ "push") < 0)
+ goto out;
- pairwise = le_to_host16(f.pairwise);
- wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID="
- MACSTR " pairwise=0x%x",
- MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1",
- f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name",
- f.pmk_r1_name, WPA_PMK_NAME_LEN);
+ ret = 0;
+out:
- wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
- pairwise);
- os_memset(f.pmk_r1, 0, PMK_LEN);
+ os_memset(plain, 0, plain_len);
+ os_free(plain);
+ plain = NULL;
- return 0;
+ return ret;
}
@@ -2077,44 +2374,43 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
struct wpa_ft_pmk_r0_sa *pmk_r0,
struct ft_remote_r1kh *r1kh,
- const u8 *s1kh_id, int pairwise)
+ const u8 *s1kh_id)
{
- struct ft_r0kh_r1kh_push_frame frame, f;
+ struct ft_rrb_frame push_hdr;
struct os_time now;
- const u8 *plain;
- u8 *crypt;
-
- os_memset(&frame, 0, sizeof(frame));
- frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
- frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH;
- frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN);
- os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);
-
- /* aes_wrap() does not support inplace encryption, so use a temporary
- * buffer for the data. */
- os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN);
- os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
- os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN);
- wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id,
- s1kh_id, f.pmk_r1, f.pmk_r1_name);
- wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id));
- wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN);
- wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name,
- WPA_PMK_NAME_LEN);
+ u8 *packet;
+ size_t packet_len;
+ u8 f_timestamp[sizeof(le32)];
+
+ os_memset(&push_hdr, 0, sizeof(push_hdr));
+ push_hdr.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
+ push_hdr.packet_type = FT_PACKET_R0KH_R1KH_PUSH;
+ os_memcpy(push_hdr.ap_address, wpa_auth->addr, ETH_ALEN);
+
os_get_time(&now);
- WPA_PUT_LE32(f.timestamp, now.sec);
- f.pairwise = host_to_le16(pairwise);
- os_memset(f.pad, 0, sizeof(f.pad));
- plain = ((const u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame,
- timestamp);
- crypt = ((u8 *) &frame) + offsetof(struct ft_r0kh_r1kh_push_frame,
- timestamp);
- if (aes_wrap(r1kh->key, sizeof(r1kh->key),
- (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
- plain, crypt) < 0)
+ WPA_PUT_LE32(f_timestamp, now.sec);
+
+ struct tlv_list push_tlv[] = {
+ { .type = FT_RRB_TIMESTAMP, .len = sizeof(f_timestamp),
+ .data = f_timestamp },
+ { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
+ .data = r1kh->id },
+ { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN,
+ .data = s1kh_id },
+ { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN,
+ .data = pmk_r0->pmk_r0_name },
+ { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
+ };
+
+ if (wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), &push_hdr,
+ push_tlv, pmk_r0, r1kh->id, s1kh_id,
+ &packet, &packet_len) < 0)
return;
- wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame));
+ wpa_ft_rrb_send(wpa_auth, r1kh->addr, packet, packet_len);
+
+ os_free(packet);
+ packet = NULL;
}
@@ -2146,7 +2442,7 @@ void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
if (is_zero_ether_addr(r1kh->addr) ||
is_zero_ether_addr(r1kh->id))
continue;
- wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise);
+ wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr);
}
}
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index c634c32..eb5d03e 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -128,7 +128,7 @@ struct wpa_state_machine {
const u8 *ies, size_t ies_len);
void *ft_pending_cb_ctx;
struct wpabuf *ft_pending_req_ies;
- u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN];
+ u8 ft_pending_pull_nonce[FT_RRB_NONCE_LEN];
u8 ft_pending_auth_transaction;
u8 ft_pending_current_ap[ETH_ALEN];
int ft_pending_pull_left_retries;
--
2.1.4
More information about the Hostap
mailing list