Move SAE comeback token functionality into a separate file
This is helpful in being able to get the functionality needed for SAE into a separate library (libpasn.so) without needing all of the ieee802_11.c functionality. Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
parent
1711fe9121
commit
975b7a02cb
7 changed files with 165 additions and 119 deletions
|
@ -1036,6 +1036,7 @@ endif
|
||||||
ifdef NEED_AP_MLME
|
ifdef NEED_AP_MLME
|
||||||
OBJS += src/ap/wmm.c
|
OBJS += src/ap/wmm.c
|
||||||
OBJS += src/ap/ap_list.c
|
OBJS += src/ap/ap_list.c
|
||||||
|
OBJS += src/ap/comeback_token.c
|
||||||
OBJS += src/ap/ieee802_11.c
|
OBJS += src/ap/ieee802_11.c
|
||||||
OBJS += src/ap/hw_features.c
|
OBJS += src/ap/hw_features.c
|
||||||
OBJS += src/ap/dfs.c
|
OBJS += src/ap/dfs.c
|
||||||
|
|
|
@ -1182,6 +1182,7 @@ endif
|
||||||
ifdef NEED_AP_MLME
|
ifdef NEED_AP_MLME
|
||||||
OBJS += ../src/ap/wmm.o
|
OBJS += ../src/ap/wmm.o
|
||||||
OBJS += ../src/ap/ap_list.o
|
OBJS += ../src/ap/ap_list.o
|
||||||
|
OBJS += ../src/ap/comeback_token.o
|
||||||
OBJS += ../src/ap/ieee802_11.o
|
OBJS += ../src/ap/ieee802_11.o
|
||||||
OBJS += ../src/ap/hw_features.o
|
OBJS += ../src/ap/hw_features.o
|
||||||
OBJS += ../src/ap/dfs.o
|
OBJS += ../src/ap/dfs.o
|
||||||
|
|
139
src/ap/comeback_token.c
Normal file
139
src/ap/comeback_token.c
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* hostapd / Comeback token mechanism for SAE
|
||||||
|
* Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "hostapd.h"
|
||||||
|
#include "crypto/sha256.h"
|
||||||
|
#include "crypto/random.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
|
#include "comeback_token.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CONFIG_SAE) || defined(CONFIG_PASN)
|
||||||
|
|
||||||
|
static int comeback_token_hash(const u8 *comeback_key, const u8 *addr, u8 *idx)
|
||||||
|
{
|
||||||
|
u8 hash[SHA256_MAC_LEN];
|
||||||
|
|
||||||
|
if (hmac_sha256(comeback_key, COMEBACK_KEY_SIZE,
|
||||||
|
addr, ETH_ALEN, hash) < 0)
|
||||||
|
return -1;
|
||||||
|
*idx = hash[0];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int check_comeback_token(const u8 *comeback_key,
|
||||||
|
u16 *comeback_pending_idx, const u8 *addr,
|
||||||
|
const u8 *token, size_t token_len)
|
||||||
|
{
|
||||||
|
u8 mac[SHA256_MAC_LEN];
|
||||||
|
const u8 *addrs[2];
|
||||||
|
size_t len[2];
|
||||||
|
u16 token_idx;
|
||||||
|
u8 idx;
|
||||||
|
|
||||||
|
if (token_len != SHA256_MAC_LEN ||
|
||||||
|
comeback_token_hash(comeback_key, addr, &idx) < 0)
|
||||||
|
return -1;
|
||||||
|
token_idx = comeback_pending_idx[idx];
|
||||||
|
if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Comeback: Invalid anti-clogging token from "
|
||||||
|
MACSTR " - token_idx 0x%04x, expected 0x%04x",
|
||||||
|
MAC2STR(addr), WPA_GET_BE16(token), token_idx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs[0] = addr;
|
||||||
|
len[0] = ETH_ALEN;
|
||||||
|
addrs[1] = token;
|
||||||
|
len[1] = 2;
|
||||||
|
if (hmac_sha256_vector(comeback_key, COMEBACK_KEY_SIZE,
|
||||||
|
2, addrs, len, mac) < 0 ||
|
||||||
|
os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
comeback_pending_idx[idx] = 0; /* invalidate used token */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf *
|
||||||
|
auth_build_token_req(struct os_reltime *last_comeback_key_update,
|
||||||
|
u8 *comeback_key, u16 comeback_idx,
|
||||||
|
u16 *comeback_pending_idx, size_t idx_len,
|
||||||
|
int group, const u8 *addr, int h2e)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
u8 *token;
|
||||||
|
struct os_reltime now;
|
||||||
|
u8 idx[2];
|
||||||
|
const u8 *addrs[2];
|
||||||
|
size_t len[2];
|
||||||
|
u8 p_idx;
|
||||||
|
u16 token_idx;
|
||||||
|
|
||||||
|
os_get_reltime(&now);
|
||||||
|
if (!os_reltime_initialized(last_comeback_key_update) ||
|
||||||
|
os_reltime_expired(&now, last_comeback_key_update, 60) ||
|
||||||
|
comeback_idx == 0xffff) {
|
||||||
|
if (random_get_bytes(comeback_key, COMEBACK_KEY_SIZE) < 0)
|
||||||
|
return NULL;
|
||||||
|
wpa_hexdump(MSG_DEBUG, "Comeback: Updated token key",
|
||||||
|
comeback_key, COMEBACK_KEY_SIZE);
|
||||||
|
*last_comeback_key_update = now;
|
||||||
|
comeback_idx = 0;
|
||||||
|
os_memset(comeback_pending_idx, 0, idx_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(sizeof(le16) + 3 + SHA256_MAC_LEN);
|
||||||
|
if (buf == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (group)
|
||||||
|
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
|
||||||
|
|
||||||
|
if (h2e) {
|
||||||
|
/* Encapsulate Anti-clogging Token field in a container IE */
|
||||||
|
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
|
||||||
|
wpabuf_put_u8(buf, 1 + SHA256_MAC_LEN);
|
||||||
|
wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comeback_token_hash(comeback_key, addr, &p_idx) < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
token_idx = comeback_pending_idx[p_idx];
|
||||||
|
if (!token_idx) {
|
||||||
|
comeback_idx++;
|
||||||
|
token_idx = comeback_idx;
|
||||||
|
comeback_pending_idx[p_idx] = token_idx;
|
||||||
|
}
|
||||||
|
WPA_PUT_BE16(idx, token_idx);
|
||||||
|
token = wpabuf_put(buf, SHA256_MAC_LEN);
|
||||||
|
addrs[0] = addr;
|
||||||
|
len[0] = ETH_ALEN;
|
||||||
|
addrs[1] = idx;
|
||||||
|
len[1] = sizeof(idx);
|
||||||
|
if (hmac_sha256_vector(comeback_key, COMEBACK_KEY_SIZE,
|
||||||
|
2, addrs, len, token) < 0) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
WPA_PUT_BE16(token, token_idx);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(CONFIG_SAE) || defined(CONFIG_PASN) */
|
21
src/ap/comeback_token.h
Normal file
21
src/ap/comeback_token.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* hostapd / Comeback token mechanism for SAE
|
||||||
|
* Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
|
||||||
|
*
|
||||||
|
* This software may be distributed under the terms of the BSD license.
|
||||||
|
* See README for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMEBACK_TOKEN_H
|
||||||
|
#define COMEBACK_TOKEN_H
|
||||||
|
|
||||||
|
int check_comeback_token(const u8 *comeback_key,
|
||||||
|
u16 *comeback_pending_idx, const u8 *addr,
|
||||||
|
const u8 *token, size_t token_len);
|
||||||
|
struct wpabuf *
|
||||||
|
auth_build_token_req(struct os_reltime *last_comeback_key_update,
|
||||||
|
u8 *comeback_key, u16 comeback_idx,
|
||||||
|
u16 *comeback_pending_idx, size_t idx_len,
|
||||||
|
int group, const u8 *addr, int h2e);
|
||||||
|
|
||||||
|
#endif /* COMEBACK_TOKEN_H */
|
|
@ -55,6 +55,7 @@
|
||||||
#include "fils_hlp.h"
|
#include "fils_hlp.h"
|
||||||
#include "dpp_hostapd.h"
|
#include "dpp_hostapd.h"
|
||||||
#include "gas_query_ap.h"
|
#include "gas_query_ap.h"
|
||||||
|
#include "comeback_token.h"
|
||||||
#include "pasn/pasn_common.h"
|
#include "pasn/pasn_common.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -739,125 +740,6 @@ static int use_anti_clogging(struct hostapd_data *hapd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int comeback_token_hash(const u8 *comeback_key, const u8 *addr, u8 *idx)
|
|
||||||
{
|
|
||||||
u8 hash[SHA256_MAC_LEN];
|
|
||||||
|
|
||||||
if (hmac_sha256(comeback_key, COMEBACK_KEY_SIZE,
|
|
||||||
addr, ETH_ALEN, hash) < 0)
|
|
||||||
return -1;
|
|
||||||
*idx = hash[0];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int check_comeback_token(const u8 *comeback_key,
|
|
||||||
u16 *comeback_pending_idx, const u8 *addr,
|
|
||||||
const u8 *token, size_t token_len)
|
|
||||||
{
|
|
||||||
u8 mac[SHA256_MAC_LEN];
|
|
||||||
const u8 *addrs[2];
|
|
||||||
size_t len[2];
|
|
||||||
u16 token_idx;
|
|
||||||
u8 idx;
|
|
||||||
|
|
||||||
if (token_len != SHA256_MAC_LEN ||
|
|
||||||
comeback_token_hash(comeback_key, addr, &idx) < 0)
|
|
||||||
return -1;
|
|
||||||
token_idx = comeback_pending_idx[idx];
|
|
||||||
if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
|
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"Comeback: Invalid anti-clogging token from "
|
|
||||||
MACSTR " - token_idx 0x%04x, expected 0x%04x",
|
|
||||||
MAC2STR(addr), WPA_GET_BE16(token), token_idx);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs[0] = addr;
|
|
||||||
len[0] = ETH_ALEN;
|
|
||||||
addrs[1] = token;
|
|
||||||
len[1] = 2;
|
|
||||||
if (hmac_sha256_vector(comeback_key, COMEBACK_KEY_SIZE,
|
|
||||||
2, addrs, len, mac) < 0 ||
|
|
||||||
os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
comeback_pending_idx[idx] = 0; /* invalidate used token */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct wpabuf *
|
|
||||||
auth_build_token_req(struct os_reltime *last_comeback_key_update,
|
|
||||||
u8 *comeback_key, u16 comeback_idx,
|
|
||||||
u16 *comeback_pending_idx, size_t idx_len,
|
|
||||||
int group, const u8 *addr, int h2e)
|
|
||||||
{
|
|
||||||
struct wpabuf *buf;
|
|
||||||
u8 *token;
|
|
||||||
struct os_reltime now;
|
|
||||||
u8 idx[2];
|
|
||||||
const u8 *addrs[2];
|
|
||||||
size_t len[2];
|
|
||||||
u8 p_idx;
|
|
||||||
u16 token_idx;
|
|
||||||
|
|
||||||
os_get_reltime(&now);
|
|
||||||
if (!os_reltime_initialized(last_comeback_key_update) ||
|
|
||||||
os_reltime_expired(&now, last_comeback_key_update, 60) ||
|
|
||||||
comeback_idx == 0xffff) {
|
|
||||||
if (random_get_bytes(comeback_key, COMEBACK_KEY_SIZE) < 0)
|
|
||||||
return NULL;
|
|
||||||
wpa_hexdump(MSG_DEBUG, "Comeback: Updated token key",
|
|
||||||
comeback_key, COMEBACK_KEY_SIZE);
|
|
||||||
*last_comeback_key_update = now;
|
|
||||||
comeback_idx = 0;
|
|
||||||
os_memset(comeback_pending_idx, 0, idx_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = wpabuf_alloc(sizeof(le16) + 3 + SHA256_MAC_LEN);
|
|
||||||
if (buf == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (group)
|
|
||||||
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
|
|
||||||
|
|
||||||
if (h2e) {
|
|
||||||
/* Encapsulate Anti-clogging Token field in a container IE */
|
|
||||||
wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
|
|
||||||
wpabuf_put_u8(buf, 1 + SHA256_MAC_LEN);
|
|
||||||
wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (comeback_token_hash(comeback_key, addr, &p_idx) < 0) {
|
|
||||||
wpabuf_free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
token_idx = comeback_pending_idx[p_idx];
|
|
||||||
if (!token_idx) {
|
|
||||||
comeback_idx++;
|
|
||||||
token_idx = comeback_idx;
|
|
||||||
comeback_pending_idx[p_idx] = token_idx;
|
|
||||||
}
|
|
||||||
WPA_PUT_BE16(idx, token_idx);
|
|
||||||
token = wpabuf_put(buf, SHA256_MAC_LEN);
|
|
||||||
addrs[0] = addr;
|
|
||||||
len[0] = ETH_ALEN;
|
|
||||||
addrs[1] = idx;
|
|
||||||
len[1] = sizeof(idx);
|
|
||||||
if (hmac_sha256_vector(comeback_key, COMEBACK_KEY_SIZE,
|
|
||||||
2, addrs, len, token) < 0) {
|
|
||||||
wpabuf_free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
WPA_PUT_BE16(token, token_idx);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* defined(CONFIG_SAE) || defined(CONFIG_PASN) */
|
#endif /* defined(CONFIG_SAE) || defined(CONFIG_PASN) */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -948,6 +948,7 @@ endif
|
||||||
ifdef NEED_AP_MLME
|
ifdef NEED_AP_MLME
|
||||||
OBJS += src/ap/wmm.c
|
OBJS += src/ap/wmm.c
|
||||||
OBJS += src/ap/ap_list.c
|
OBJS += src/ap/ap_list.c
|
||||||
|
OBJS += src/ap/comeback_token.c
|
||||||
OBJS += src/ap/ieee802_11.c
|
OBJS += src/ap/ieee802_11.c
|
||||||
OBJS += src/ap/hw_features.c
|
OBJS += src/ap/hw_features.c
|
||||||
OBJS += src/ap/dfs.c
|
OBJS += src/ap/dfs.c
|
||||||
|
|
|
@ -983,6 +983,7 @@ endif
|
||||||
ifdef NEED_AP_MLME
|
ifdef NEED_AP_MLME
|
||||||
OBJS += ../src/ap/wmm.o
|
OBJS += ../src/ap/wmm.o
|
||||||
OBJS += ../src/ap/ap_list.o
|
OBJS += ../src/ap/ap_list.o
|
||||||
|
OBJS += ../src/ap/comeback_token.o
|
||||||
OBJS += ../src/ap/ieee802_11.o
|
OBJS += ../src/ap/ieee802_11.o
|
||||||
OBJS += ../src/ap/hw_features.o
|
OBJS += ../src/ap/hw_features.o
|
||||||
OBJS += ../src/ap/dfs.o
|
OBJS += ../src/ap/dfs.o
|
||||||
|
|
Loading…
Reference in a new issue