aboutsummaryrefslogtreecommitdiff
path: root/src/common/sae.h
blob: c446da3964a7b1dd2618a3f1501992ac03353e61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * 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_PMK_LEN_MAX 64
#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)
#ifdef CONFIG_SAE_PK
#define SAE_CONFIRM_MAX_LEN ((2 + SAE_MAX_HASH_LEN) + 1500)
#else /* CONFIG_SAE_PK */
#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_HASH_LEN)
#endif /* CONFIG_SAE_PK */
#define SAE_PK_M_LEN 16

/* Special value returned by sae_parse_commit() */
#define SAE_SILENTLY_DISCARD 65535

struct sae_pk {
	struct wpabuf *m;
	struct crypto_ec_key *key;
	int group;
	struct wpabuf *pubkey; /* DER encoded subjectPublicKey */
#ifdef CONFIG_TESTING_OPTIONS
	struct crypto_ec_key *sign_key_override;
#endif /* CONFIG_TESTING_OPTIONS */
};


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 own_addr_higher:1;

#ifdef CONFIG_SAE_PK
	u8 kek[SAE_MAX_HASH_LEN];
	size_t kek_len;
	const struct sae_pk *ap_pk;
	u8 own_addr[ETH_ALEN];
	u8 peer_addr[ETH_ALEN];
	u8 fingerprint[SAE_MAX_HASH_LEN];
	size_t fingerprint_bytes;
	size_t fingerprint_bits;
	size_t lambda;
	unsigned int sec;
	u8 ssid[32];
	size_t ssid_len;
#ifdef CONFIG_TESTING_OPTIONS
	bool omit_pk_elem;
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_SAE_PK */
};

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;
#ifdef CONFIG_SAE_PK
	u8 ssid[32];
	size_t ssid_len;
#endif /* CONFIG_SAE_PK */
};

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_MAX];
	size_t pmk_len;
	int akmp; /* WPA_KEY_MGMT_* used in key derivation */
	u32 own_akm_suite_selector;
	u32 peer_akm_suite_selector;
	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) */
	unsigned int h2e:1;
	unsigned int pk:1;
	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,
		       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, const struct sae_pk *pk);
int sae_process_commit(struct sae_data *sae);
int 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, int *ie_offset);
int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len,
		      int *ie_offset);
u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
const char * sae_state_txt(enum sae_state state);
size_t sae_ecc_prime_len_2_hash_len(size_t prime_len);
size_t sae_ffc_prime_len_2_hash_len(size_t prime_len);
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);

/* sae_pk.c */
#ifdef CONFIG_SAE_PK
bool sae_pk_valid_password(const char *pw);
#else /* CONFIG_SAE_PK */
static inline bool sae_pk_valid_password(const char *pw)
{
	return false;
}
#endif /* CONFIG_SAE_PK */
char * sae_pk_base32_encode(const u8 *src, size_t len_bits);
u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len);
int sae_pk_set_password(struct sae_data *sae, const char *password);
void sae_deinit_pk(struct sae_pk *pk);
struct sae_pk * sae_parse_pk(const char *val);
int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf);
int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len);
int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash);
u32 sae_pk_get_be19(const u8 *buf);
void sae_pk_buf_shift_left_19(u8 *buf, size_t len);

#endif /* SAE_H */