2 * hostapd / EAP-PSK (draft-bersani-eap-psk-09.txt) server
3 * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
14 * Note: EAP-PSK is an EAP authentication method and as such, completely
15 * different from WPA-PSK. This file is not needed for WPA-PSK functionality.
21 #include <netinet/in.h>
27 #include "eap_psk_common.h"
31 enum { PSK_1
, PSK_3
, SUCCESS
, FAILURE
} state
;
32 u8 rand_s
[EAP_PSK_RAND_LEN
];
33 u8 rand_p
[EAP_PSK_RAND_LEN
];
35 size_t id_p_len
, id_s_len
;
36 u8 ak
[EAP_PSK_AK_LEN
], kdk
[EAP_PSK_KDK_LEN
], tek
[EAP_PSK_TEK_LEN
];
37 u8 msk
[EAP_PSK_MSK_LEN
];
41 static void * eap_psk_init(struct eap_sm
*sm
)
43 struct eap_psk_data
*data
;
45 data
= malloc(sizeof(*data
));
48 memset(data
, 0, sizeof(*data
));
50 data
->id_s
= "hostapd";
57 static void eap_psk_reset(struct eap_sm
*sm
, void *priv
)
59 struct eap_psk_data
*data
= priv
;
65 static u8
* eap_psk_build_1(struct eap_sm
*sm
, struct eap_psk_data
*data
,
66 int id
, size_t *reqDataLen
)
68 struct eap_psk_hdr_1
*req
;
70 wpa_printf(MSG_DEBUG
, "EAP-PSK: PSK-1 (sending)");
72 if (hostapd_get_rand(data
->rand_s
, EAP_PSK_RAND_LEN
)) {
73 wpa_printf(MSG_ERROR
, "EAP-PSK: Failed to get random data");
74 data
->state
= FAILURE
;
77 wpa_hexdump(MSG_MSGDUMP
, "EAP-PSK: RAND_S (server rand)",
78 data
->rand_s
, EAP_PSK_RAND_LEN
);
80 *reqDataLen
= sizeof(*req
) + data
->id_s_len
;
81 req
= malloc(*reqDataLen
);
83 wpa_printf(MSG_ERROR
, "EAP-PSK: Failed to allocate memory "
85 data
->state
= FAILURE
;
89 req
->code
= EAP_CODE_REQUEST
;
91 req
->length
= htons(*reqDataLen
);
92 req
->type
= EAP_TYPE_PSK
;
93 req
->flags
= 0; /* T=0 */
94 memcpy(req
->rand_s
, data
->rand_s
, EAP_PSK_RAND_LEN
);
95 memcpy((u8
*) (req
+ 1), data
->id_s
, data
->id_s_len
);
101 static u8
* eap_psk_build_3(struct eap_sm
*sm
, struct eap_psk_data
*data
,
102 int id
, size_t *reqDataLen
)
104 struct eap_psk_hdr_3
*req
;
105 u8
*buf
, *pchannel
, nonce
[16];
108 wpa_printf(MSG_DEBUG
, "EAP-PSK: PSK-3 (sending)");
110 *reqDataLen
= sizeof(*req
) + 4 + 16 + 1;
111 req
= malloc(*reqDataLen
);
113 wpa_printf(MSG_ERROR
, "EAP-PSK: Failed to allocate memory "
115 data
->state
= FAILURE
;
119 req
->code
= EAP_CODE_REQUEST
;
120 req
->identifier
= id
;
121 req
->length
= htons(*reqDataLen
);
122 req
->type
= EAP_TYPE_PSK
;
123 req
->flags
= 2; /* T=2 */
124 memcpy(req
->rand_s
, data
->rand_s
, EAP_PSK_RAND_LEN
);
126 /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
127 buflen
= data
->id_s_len
+ EAP_PSK_RAND_LEN
;
128 buf
= malloc(buflen
);
130 data
->state
= FAILURE
;
133 memcpy(buf
, data
->id_s
, data
->id_s_len
);
134 memcpy(buf
+ data
->id_s_len
, data
->rand_p
, EAP_PSK_RAND_LEN
);
135 omac1_aes_128(data
->ak
, buf
, buflen
, req
->mac_s
);
138 eap_psk_derive_keys(data
->kdk
, data
->rand_p
, data
->tek
, data
->msk
);
139 wpa_hexdump_key(MSG_DEBUG
, "EAP-PSK: TEK", data
->tek
, EAP_PSK_TEK_LEN
);
140 wpa_hexdump_key(MSG_DEBUG
, "EAP-PSK: MSK", data
->msk
, EAP_PSK_MSK_LEN
);
142 memset(nonce
, 0, sizeof(nonce
));
143 pchannel
= (u8
*) (req
+ 1);
144 memcpy(pchannel
, nonce
+ 12, 4);
145 memset(pchannel
+ 4, 0, 16); /* Tag */
146 pchannel
[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS
<< 6;
147 wpa_hexdump(MSG_DEBUG
, "EAP-PSK: PCHANNEL (plaintext)",
148 pchannel
, 4 + 16 + 1);
149 aes_128_eax_encrypt(data
->tek
, nonce
, sizeof(nonce
), (u8
*) req
, 22,
150 pchannel
+ 4 + 16, 1, pchannel
+ 4);
151 wpa_hexdump(MSG_DEBUG
, "EAP-PSK: PCHANNEL (encrypted)",
152 pchannel
, 4 + 16 + 1);
158 static u8
* eap_psk_buildReq(struct eap_sm
*sm
, void *priv
, int id
,
161 struct eap_psk_data
*data
= priv
;
163 switch (data
->state
) {
165 return eap_psk_build_1(sm
, data
, id
, reqDataLen
);
167 return eap_psk_build_3(sm
, data
, id
, reqDataLen
);
169 wpa_printf(MSG_DEBUG
, "EAP-PSK: Unknown state %d in buildReq",
177 static Boolean
eap_psk_check(struct eap_sm
*sm
, void *priv
,
178 u8
*respData
, size_t respDataLen
)
180 struct eap_psk_data
*data
= priv
;
181 struct eap_psk_hdr
*resp
;
185 resp
= (struct eap_psk_hdr
*) respData
;
186 if (respDataLen
< sizeof(*resp
) || resp
->type
!= EAP_TYPE_PSK
||
187 (len
= ntohs(resp
->length
)) > respDataLen
||
188 len
< sizeof(*resp
)) {
189 wpa_printf(MSG_INFO
, "EAP-PSK: Invalid frame");
192 t
= resp
->flags
& 0x03;
194 wpa_printf(MSG_DEBUG
, "EAP-PSK: received frame: T=%d", t
);
196 if (data
->state
== PSK_1
&& t
!= 1) {
197 wpa_printf(MSG_DEBUG
, "EAP-PSK: Expected PSK-2 - "
202 if (data
->state
== PSK_3
&& t
!= 3) {
203 wpa_printf(MSG_DEBUG
, "EAP-PSK: Expected PSK-4 - "
208 if ((t
== 1 && len
< sizeof(struct eap_psk_hdr_2
)) ||
209 (t
== 3 && len
< sizeof(struct eap_psk_hdr_4
))) {
210 wpa_printf(MSG_DEBUG
, "EAP-PSK: Too short frame");
218 static void eap_psk_process_2(struct eap_sm
*sm
,
219 struct eap_psk_data
*data
,
220 u8
*respData
, size_t respDataLen
)
222 struct eap_psk_hdr_2
*resp
;
223 u8
*pos
, mac
[EAP_PSK_MAC_LEN
], *buf
;
224 size_t len
, left
, buflen
;
227 if (data
->state
!= PSK_1
)
230 wpa_printf(MSG_DEBUG
, "EAP-PSK: Received PSK-2");
232 resp
= (struct eap_psk_hdr_2
*) respData
;
233 len
= ntohs(resp
->length
);
234 pos
= (u8
*) (resp
+ 1);
235 left
= len
- sizeof(*resp
);
238 data
->id_p
= malloc(left
);
239 if (data
->id_p
== NULL
) {
240 wpa_printf(MSG_INFO
, "EAP-PSK: Failed to allocate memory for "
244 memcpy(data
->id_p
, pos
, left
);
245 data
->id_p_len
= left
;
246 wpa_hexdump_ascii(MSG_MSGDUMP
, "EAP-PSK: ID_P",
247 data
->id_p
, data
->id_p_len
);
249 if (eap_user_get(sm
, data
->id_p
, data
->id_p_len
, 0) < 0) {
250 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-PSK: unknown ID_P",
251 data
->id_p
, data
->id_p_len
);
252 data
->state
= FAILURE
;
257 i
< EAP_MAX_METHODS
&& sm
->user
->methods
[i
] != EAP_TYPE_NONE
;
259 if (sm
->user
->methods
[i
] == EAP_TYPE_PSK
)
263 if (sm
->user
->methods
[i
] != EAP_TYPE_PSK
) {
264 wpa_hexdump_ascii(MSG_DEBUG
,
265 "EAP-PSK: EAP-PSK not enabled for ID_P",
266 data
->id_p
, data
->id_p_len
);
267 data
->state
= FAILURE
;
271 if (sm
->user
->password
== NULL
||
272 sm
->user
->password_len
!= EAP_PSK_PSK_LEN
) {
273 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-PSK: invalid password in "
274 "user database for ID_P",
275 data
->id_p
, data
->id_p_len
);
276 data
->state
= FAILURE
;
279 eap_psk_key_setup(sm
->user
->password
, data
->ak
, data
->kdk
);
280 wpa_hexdump_key(MSG_DEBUG
, "EAP-PSK: AK", data
->ak
, EAP_PSK_AK_LEN
);
281 wpa_hexdump_key(MSG_DEBUG
, "EAP-PSK: KDK", data
->kdk
, EAP_PSK_KDK_LEN
);
283 wpa_hexdump(MSG_MSGDUMP
, "EAP-PSK: RAND_P (client rand)",
284 resp
->rand_p
, EAP_PSK_RAND_LEN
);
285 memcpy(data
->rand_p
, resp
->rand_p
, EAP_PSK_RAND_LEN
);
287 /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
288 buflen
= data
->id_p_len
+ data
->id_s_len
+ 2 * EAP_PSK_RAND_LEN
;
289 buf
= malloc(buflen
);
291 data
->state
= FAILURE
;
294 memcpy(buf
, data
->id_p
, data
->id_p_len
);
295 pos
= buf
+ data
->id_p_len
;
296 memcpy(pos
, data
->id_s
, data
->id_s_len
);
297 pos
+= data
->id_s_len
;
298 memcpy(pos
, data
->rand_s
, EAP_PSK_RAND_LEN
);
299 pos
+= EAP_PSK_RAND_LEN
;
300 memcpy(pos
, data
->rand_p
, EAP_PSK_RAND_LEN
);
301 omac1_aes_128(data
->ak
, buf
, buflen
, mac
);
303 wpa_hexdump(MSG_DEBUG
, "EAP-PSK: MAC_P", resp
->mac_p
, EAP_PSK_MAC_LEN
);
304 if (memcmp(mac
, resp
->mac_p
, EAP_PSK_MAC_LEN
) != 0) {
305 wpa_printf(MSG_INFO
, "EAP-PSK: Invalid MAC_P");
306 wpa_hexdump(MSG_MSGDUMP
, "EAP-PSK: Expected MAC_P",
307 mac
, EAP_PSK_MAC_LEN
);
308 data
->state
= FAILURE
;
316 static void eap_psk_process_4(struct eap_sm
*sm
,
317 struct eap_psk_data
*data
,
318 u8
*respData
, size_t respDataLen
)
320 struct eap_psk_hdr_4
*resp
;
321 u8
*pos
, *decrypted
, nonce
[16], *tag
;
324 if (data
->state
!= PSK_3
)
327 wpa_printf(MSG_DEBUG
, "EAP-PSK: Received PSK-4");
329 resp
= (struct eap_psk_hdr_4
*) respData
;
330 pos
= (u8
*) (resp
+ 1);
331 left
= ntohs(resp
->length
) - sizeof(*resp
);
333 wpa_hexdump(MSG_MSGDUMP
, "EAP-PSK: Encrypted PCHANNEL", pos
, left
);
335 if (left
< 4 + 16 + 1) {
336 wpa_printf(MSG_INFO
, "EAP-PSK: Too short PCHANNEL data in "
337 "PSK-4 (len=%lu, expected 21)",
338 (unsigned long) left
);
342 if (pos
[0] == 0 && pos
[1] == 0 && pos
[2] == 0 && pos
[3] == 0) {
343 wpa_printf(MSG_DEBUG
, "EAP-PSK: Nonce did not increase");
347 memset(nonce
, 0, 12);
348 memcpy(nonce
+ 12, pos
, 4);
355 decrypted
= malloc(left
);
356 if (decrypted
== NULL
)
358 memcpy(decrypted
, pos
, left
);
360 if (aes_128_eax_decrypt(data
->tek
, nonce
, sizeof(nonce
),
361 respData
, 22, decrypted
, left
, tag
)) {
362 wpa_printf(MSG_WARNING
, "EAP-PSK: PCHANNEL decryption failed");
364 data
->state
= FAILURE
;
367 wpa_hexdump(MSG_DEBUG
, "EAP-PSK: Decrypted PCHANNEL message",
371 switch (decrypted
[0] >> 6) {
372 case EAP_PSK_R_FLAG_CONT
:
373 wpa_printf(MSG_DEBUG
, "EAP-PSK: R flag - CONT - unsupported");
374 data
->state
= FAILURE
;
376 case EAP_PSK_R_FLAG_DONE_SUCCESS
:
377 wpa_printf(MSG_DEBUG
, "EAP-PSK: R flag - DONE_SUCCESS");
378 data
->state
= SUCCESS
;
380 case EAP_PSK_R_FLAG_DONE_FAILURE
:
381 wpa_printf(MSG_DEBUG
, "EAP-PSK: R flag - DONE_FAILURE");
382 data
->state
= FAILURE
;
389 static void eap_psk_process(struct eap_sm
*sm
, void *priv
,
390 u8
*respData
, size_t respDataLen
)
392 struct eap_psk_data
*data
= priv
;
393 struct eap_psk_hdr
*resp
;
395 if (sm
->user
== NULL
|| sm
->user
->password
== NULL
) {
396 wpa_printf(MSG_INFO
, "EAP-PSK: Password not configured");
397 data
->state
= FAILURE
;
401 resp
= (struct eap_psk_hdr
*) respData
;
403 switch (resp
->flags
& 0x03) {
405 eap_psk_process_2(sm
, data
, respData
, respDataLen
);
408 eap_psk_process_4(sm
, data
, respData
, respDataLen
);
414 static Boolean
eap_psk_isDone(struct eap_sm
*sm
, void *priv
)
416 struct eap_psk_data
*data
= priv
;
417 return data
->state
== SUCCESS
|| data
->state
== FAILURE
;
421 static u8
* eap_psk_getKey(struct eap_sm
*sm
, void *priv
, size_t *len
)
423 struct eap_psk_data
*data
= priv
;
426 if (data
->state
!= SUCCESS
)
429 key
= malloc(EAP_PSK_MSK_LEN
);
432 memcpy(key
, data
->msk
, EAP_PSK_MSK_LEN
);
433 *len
= EAP_PSK_MSK_LEN
;
439 static Boolean
eap_psk_isSuccess(struct eap_sm
*sm
, void *priv
)
441 struct eap_psk_data
*data
= priv
;
442 return data
->state
== SUCCESS
;
446 const struct eap_method eap_method_psk
=
448 .method
= EAP_TYPE_PSK
,
450 .init
= eap_psk_init
,
451 .reset
= eap_psk_reset
,
452 .buildReq
= eap_psk_buildReq
,
453 .check
= eap_psk_check
,
454 .process
= eap_psk_process
,
455 .isDone
= eap_psk_isDone
,
456 .getKey
= eap_psk_getKey
,
457 .isSuccess
= eap_psk_isSuccess
,