8f8473cebb
Only one peer-commit-scalar value was stored for a specific STA (i.e., one per MAC address) and that value got replaced when the next SAE Authentication exchange was started. This ended up breaking the check against re-use of peer-commit-scalar from an Accepted instance when anti-clogging token was requested. The first SAE commit message (the one without anti-clogging token) ended up overwriting the cached peer-commit-scalar value while leaving that instance in Accepted state. The second SAE commit message (with anti-clogging token) added ended up getting rejected if it used the same value again (and re-use is expected in this particular case where the value was not used in Accepted instance). Fix this by using a separate pointer for storing the peer-commit-scalar value that was used in an Accepted instance. There is no need to allocate memory for two values, i.e., it is sufficient to maintain separate pointers to the value and move the stored value to the special Accepted state pointer when moving to the Accepted state. This fixes issues where a peer STA ends up running back-to-back SAE authentication within couple of seconds, i.e., without hostapd timing out the STA entry for a case where anti-clogging token is required. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
111 lines
3.5 KiB
C
111 lines
3.5 KiB
C
/*
|
|
* Simultaneous authentication of equals
|
|
* Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
|
|
*
|
|
* This software may be distributed under the terms of the BSD license.
|
|
* See README for more details.
|
|
*/
|
|
|
|
#ifndef SAE_H
|
|
#define SAE_H
|
|
|
|
#define SAE_KCK_LEN 32
|
|
#define SAE_PMK_LEN 32
|
|
#define SAE_PMKID_LEN 16
|
|
#define SAE_MAX_PRIME_LEN 512
|
|
#define SAE_MAX_ECC_PRIME_LEN 66
|
|
#define SAE_MAX_HASH_LEN 64
|
|
#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN + 255)
|
|
#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_HASH_LEN)
|
|
|
|
/* Special value returned by sae_parse_commit() */
|
|
#define SAE_SILENTLY_DISCARD 65535
|
|
|
|
struct sae_temporary_data {
|
|
u8 kck[SAE_MAX_HASH_LEN];
|
|
size_t kck_len;
|
|
struct crypto_bignum *own_commit_scalar;
|
|
struct crypto_bignum *own_commit_element_ffc;
|
|
struct crypto_ec_point *own_commit_element_ecc;
|
|
struct crypto_bignum *peer_commit_element_ffc;
|
|
struct crypto_ec_point *peer_commit_element_ecc;
|
|
struct crypto_ec_point *pwe_ecc;
|
|
struct crypto_bignum *pwe_ffc;
|
|
struct crypto_bignum *sae_rand;
|
|
struct crypto_ec *ec;
|
|
int prime_len;
|
|
int order_len;
|
|
const struct dh_group *dh;
|
|
const struct crypto_bignum *prime;
|
|
const struct crypto_bignum *order;
|
|
struct crypto_bignum *prime_buf;
|
|
struct crypto_bignum *order_buf;
|
|
struct wpabuf *anti_clogging_token;
|
|
char *pw_id;
|
|
int vlan_id;
|
|
u8 bssid[ETH_ALEN];
|
|
struct wpabuf *own_rejected_groups;
|
|
struct wpabuf *peer_rejected_groups;
|
|
unsigned int h2e:1;
|
|
unsigned int own_addr_higher:1;
|
|
};
|
|
|
|
struct sae_pt {
|
|
struct sae_pt *next;
|
|
int group;
|
|
struct crypto_ec *ec;
|
|
struct crypto_ec_point *ecc_pt;
|
|
|
|
const struct dh_group *dh;
|
|
struct crypto_bignum *ffc_pt;
|
|
};
|
|
|
|
enum sae_state {
|
|
SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED
|
|
};
|
|
|
|
struct sae_data {
|
|
enum sae_state state;
|
|
u16 send_confirm;
|
|
u8 pmk[SAE_PMK_LEN];
|
|
u8 pmkid[SAE_PMKID_LEN];
|
|
struct crypto_bignum *peer_commit_scalar;
|
|
struct crypto_bignum *peer_commit_scalar_accepted;
|
|
int group;
|
|
unsigned int sync; /* protocol instance variable: Sync */
|
|
u16 rc; /* protocol instance variable: Rc (received send-confirm) */
|
|
struct sae_temporary_data *tmp;
|
|
};
|
|
|
|
int sae_set_group(struct sae_data *sae, int group);
|
|
void sae_clear_temp_data(struct sae_data *sae);
|
|
void sae_clear_data(struct sae_data *sae);
|
|
|
|
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
|
const u8 *password, size_t password_len,
|
|
const char *identifier, struct sae_data *sae);
|
|
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
|
const u8 *addr1, const u8 *addr2,
|
|
int *rejected_groups);
|
|
int sae_process_commit(struct sae_data *sae);
|
|
void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
|
|
const struct wpabuf *token, const char *identifier);
|
|
u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
|
|
const u8 **token, size_t *token_len, int *allowed_groups,
|
|
int h2e);
|
|
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
|
|
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
|
|
u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
|
|
const char * sae_state_txt(enum sae_state state);
|
|
struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len,
|
|
const u8 *password, size_t password_len,
|
|
const char *identifier);
|
|
struct crypto_ec_point *
|
|
sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt,
|
|
const u8 *addr1, const u8 *addr2);
|
|
struct crypto_bignum *
|
|
sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt,
|
|
const u8 *addr1, const u8 *addr2);
|
|
void sae_deinit_pt(struct sae_pt *pt);
|
|
|
|
#endif /* SAE_H */
|