Parallelize in_ifaddrhead operation
[dragonfly.git] / contrib / hostapd-0.5.8 / eap_psk.c
blob7408a522e328e0701afcb9ac68287f56af71f5d8
1 /*
2 * hostapd / EAP-PSK (RFC 4764) server
3 * Copyright (c) 2005-2007, Jouni Malinen <j@w1.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
10 * license.
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.
18 #include "includes.h"
20 #include "hostapd.h"
21 #include "common.h"
22 #include "eap_i.h"
23 #include "aes_wrap.h"
24 #include "eap_psk_common.h"
27 struct eap_psk_data {
28 enum { PSK_1, PSK_3, SUCCESS, FAILURE } state;
29 u8 rand_s[EAP_PSK_RAND_LEN];
30 u8 rand_p[EAP_PSK_RAND_LEN];
31 u8 *id_p, *id_s;
32 size_t id_p_len, id_s_len;
33 u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
34 u8 msk[EAP_MSK_LEN];
35 u8 emsk[EAP_EMSK_LEN];
39 static void * eap_psk_init(struct eap_sm *sm)
41 struct eap_psk_data *data;
43 data = wpa_zalloc(sizeof(*data));
44 if (data == NULL)
45 return NULL;
46 data->state = PSK_1;
47 data->id_s = (u8 *) "hostapd";
48 data->id_s_len = 7;
50 return data;
54 static void eap_psk_reset(struct eap_sm *sm, void *priv)
56 struct eap_psk_data *data = priv;
57 free(data->id_p);
58 free(data);
62 static u8 * eap_psk_build_1(struct eap_sm *sm, struct eap_psk_data *data,
63 int id, size_t *reqDataLen)
65 struct eap_psk_hdr_1 *req;
67 wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)");
69 if (hostapd_get_rand(data->rand_s, EAP_PSK_RAND_LEN)) {
70 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
71 data->state = FAILURE;
72 return NULL;
74 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)",
75 data->rand_s, EAP_PSK_RAND_LEN);
77 *reqDataLen = sizeof(*req) + data->id_s_len;
78 req = malloc(*reqDataLen);
79 if (req == NULL) {
80 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
81 "request");
82 data->state = FAILURE;
83 return NULL;
86 req->code = EAP_CODE_REQUEST;
87 req->identifier = id;
88 req->length = htons(*reqDataLen);
89 req->type = EAP_TYPE_PSK;
90 req->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */
91 memcpy(req->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
92 memcpy((u8 *) (req + 1), data->id_s, data->id_s_len);
94 return (u8 *) req;
98 static u8 * eap_psk_build_3(struct eap_sm *sm, struct eap_psk_data *data,
99 int id, size_t *reqDataLen)
101 struct eap_psk_hdr_3 *req;
102 u8 *buf, *pchannel, nonce[16];
103 size_t buflen;
105 wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)");
107 *reqDataLen = sizeof(*req) + 4 + 16 + 1;
108 req = malloc(*reqDataLen);
109 if (req == NULL) {
110 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
111 "request");
112 data->state = FAILURE;
113 return NULL;
116 req->code = EAP_CODE_REQUEST;
117 req->identifier = id;
118 req->length = htons(*reqDataLen);
119 req->type = EAP_TYPE_PSK;
120 req->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */
121 memcpy(req->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
123 /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
124 buflen = data->id_s_len + EAP_PSK_RAND_LEN;
125 buf = malloc(buflen);
126 if (buf == NULL) {
127 free(req);
128 data->state = FAILURE;
129 return NULL;
131 memcpy(buf, data->id_s, data->id_s_len);
132 memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
133 omac1_aes_128(data->ak, buf, buflen, req->mac_s);
134 free(buf);
136 eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk,
137 data->emsk);
138 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
139 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
140 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_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);
154 return (u8 *) req;
158 static u8 * eap_psk_buildReq(struct eap_sm *sm, void *priv, int id,
159 size_t *reqDataLen)
161 struct eap_psk_data *data = priv;
163 switch (data->state) {
164 case PSK_1:
165 return eap_psk_build_1(sm, data, id, reqDataLen);
166 case PSK_3:
167 return eap_psk_build_3(sm, data, id, reqDataLen);
168 default:
169 wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq",
170 data->state);
171 break;
173 return NULL;
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;
182 size_t len;
183 u8 t;
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");
190 return TRUE;
192 t = EAP_PSK_FLAGS_GET_T(resp->flags);
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 - "
198 "ignore T=%d", t);
199 return TRUE;
202 if (data->state == PSK_3 && t != 3) {
203 wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - "
204 "ignore T=%d", t);
205 return TRUE;
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");
211 return TRUE;
214 return FALSE;
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;
225 int i;
227 if (data->state != PSK_1)
228 return;
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);
237 free(data->id_p);
238 data->id_p = malloc(left);
239 if (data->id_p == NULL) {
240 wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for "
241 "ID_P");
242 return;
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;
253 return;
256 for (i = 0;
257 i < EAP_MAX_METHODS &&
258 (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
259 sm->user->methods[i].method != EAP_TYPE_NONE);
260 i++) {
261 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
262 sm->user->methods[i].method == EAP_TYPE_PSK)
263 break;
266 if (i >= EAP_MAX_METHODS ||
267 sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
268 sm->user->methods[i].method != EAP_TYPE_PSK) {
269 wpa_hexdump_ascii(MSG_DEBUG,
270 "EAP-PSK: EAP-PSK not enabled for ID_P",
271 data->id_p, data->id_p_len);
272 data->state = FAILURE;
273 return;
276 if (sm->user->password == NULL ||
277 sm->user->password_len != EAP_PSK_PSK_LEN) {
278 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in "
279 "user database for ID_P",
280 data->id_p, data->id_p_len);
281 data->state = FAILURE;
282 return;
284 eap_psk_key_setup(sm->user->password, data->ak, data->kdk);
285 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
286 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
288 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)",
289 resp->rand_p, EAP_PSK_RAND_LEN);
290 memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN);
292 /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
293 buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
294 buf = malloc(buflen);
295 if (buf == NULL) {
296 data->state = FAILURE;
297 return;
299 memcpy(buf, data->id_p, data->id_p_len);
300 pos = buf + data->id_p_len;
301 memcpy(pos, data->id_s, data->id_s_len);
302 pos += data->id_s_len;
303 memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN);
304 pos += EAP_PSK_RAND_LEN;
305 memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
306 omac1_aes_128(data->ak, buf, buflen, mac);
307 free(buf);
308 wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN);
309 if (memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
310 wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P");
311 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P",
312 mac, EAP_PSK_MAC_LEN);
313 data->state = FAILURE;
314 return;
317 data->state = PSK_3;
321 static void eap_psk_process_4(struct eap_sm *sm,
322 struct eap_psk_data *data,
323 u8 *respData, size_t respDataLen)
325 struct eap_psk_hdr_4 *resp;
326 u8 *pos, *decrypted, nonce[16], *tag;
327 size_t left;
329 if (data->state != PSK_3)
330 return;
332 wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4");
334 resp = (struct eap_psk_hdr_4 *) respData;
335 pos = (u8 *) (resp + 1);
336 left = ntohs(resp->length) - sizeof(*resp);
338 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left);
340 if (left < 4 + 16 + 1) {
341 wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in "
342 "PSK-4 (len=%lu, expected 21)",
343 (unsigned long) left);
344 return;
347 if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) {
348 wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase");
349 return;
352 memset(nonce, 0, 12);
353 memcpy(nonce + 12, pos, 4);
354 pos += 4;
355 left -= 4;
356 tag = pos;
357 pos += 16;
358 left -= 16;
360 decrypted = malloc(left);
361 if (decrypted == NULL)
362 return;
363 memcpy(decrypted, pos, left);
365 if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
366 respData, 22, decrypted, left, tag)) {
367 wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
368 free(decrypted);
369 data->state = FAILURE;
370 return;
372 wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
373 decrypted, left);
375 /* Verify R flag */
376 switch (decrypted[0] >> 6) {
377 case EAP_PSK_R_FLAG_CONT:
378 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported");
379 data->state = FAILURE;
380 break;
381 case EAP_PSK_R_FLAG_DONE_SUCCESS:
382 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS");
383 data->state = SUCCESS;
384 break;
385 case EAP_PSK_R_FLAG_DONE_FAILURE:
386 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE");
387 data->state = FAILURE;
388 break;
390 free(decrypted);
394 static void eap_psk_process(struct eap_sm *sm, void *priv,
395 u8 *respData, size_t respDataLen)
397 struct eap_psk_data *data = priv;
398 struct eap_psk_hdr *resp;
400 if (sm->user == NULL || sm->user->password == NULL) {
401 wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not "
402 "configured");
403 data->state = FAILURE;
404 return;
407 resp = (struct eap_psk_hdr *) respData;
409 switch (EAP_PSK_FLAGS_GET_T(resp->flags)) {
410 case 1:
411 eap_psk_process_2(sm, data, respData, respDataLen);
412 break;
413 case 3:
414 eap_psk_process_4(sm, data, respData, respDataLen);
415 break;
420 static Boolean eap_psk_isDone(struct eap_sm *sm, void *priv)
422 struct eap_psk_data *data = priv;
423 return data->state == SUCCESS || data->state == FAILURE;
427 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
429 struct eap_psk_data *data = priv;
430 u8 *key;
432 if (data->state != SUCCESS)
433 return NULL;
435 key = malloc(EAP_MSK_LEN);
436 if (key == NULL)
437 return NULL;
438 memcpy(key, data->msk, EAP_MSK_LEN);
439 *len = EAP_MSK_LEN;
441 return key;
445 static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
447 struct eap_psk_data *data = priv;
448 u8 *key;
450 if (data->state != SUCCESS)
451 return NULL;
453 key = malloc(EAP_EMSK_LEN);
454 if (key == NULL)
455 return NULL;
456 memcpy(key, data->emsk, EAP_EMSK_LEN);
457 *len = EAP_EMSK_LEN;
459 return key;
463 static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv)
465 struct eap_psk_data *data = priv;
466 return data->state == SUCCESS;
470 int eap_server_psk_register(void)
472 struct eap_method *eap;
473 int ret;
475 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
476 EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
477 if (eap == NULL)
478 return -1;
480 eap->init = eap_psk_init;
481 eap->reset = eap_psk_reset;
482 eap->buildReq = eap_psk_buildReq;
483 eap->check = eap_psk_check;
484 eap->process = eap_psk_process;
485 eap->isDone = eap_psk_isDone;
486 eap->getKey = eap_psk_getKey;
487 eap->isSuccess = eap_psk_isSuccess;
488 eap->get_emsk = eap_psk_get_emsk;
490 ret = eap_server_method_register(eap);
491 if (ret)
492 eap_server_method_free(eap);
493 return ret;