1 /* 2 * EAP peer method: EAP-PSK (RFC 4764) 3 * Copyright (c) 2004-2007, Jouni Malinen <j (at) w1.fi> 4 * 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. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 * 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. 16 */ 17 18 #include "includes.h" 19 20 #include "common.h" 21 #include "eap_i.h" 22 #include "config_ssid.h" 23 #include "md5.h" 24 #include "aes_wrap.h" 25 #include "eap_psk_common.h" 26 27 28 struct eap_psk_data { 29 enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; 30 u8 rand_p[EAP_PSK_RAND_LEN]; 31 u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; 32 u8 *id_s, *id_p; 33 size_t id_s_len, id_p_len; 34 u8 msk[EAP_MSK_LEN]; 35 u8 emsk[EAP_EMSK_LEN]; 36 }; 37 38 39 static void * eap_psk_init(struct eap_sm *sm) 40 { 41 struct wpa_ssid *config = eap_get_config(sm); 42 struct eap_psk_data *data; 43 44 if (config == NULL || !config->eappsk) { 45 wpa_printf(MSG_INFO, "EAP-PSK: pre-shared key not configured"); 46 return NULL; 47 } 48 49 data = os_zalloc(sizeof(*data)); 50 if (data == NULL) 51 return NULL; 52 eap_psk_key_setup(config->eappsk, data->ak, data->kdk); 53 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 54 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 55 data->state = PSK_INIT; 56 57 if (config->nai) { 58 data->id_p = os_malloc(config->nai_len); 59 if (data->id_p) 60 os_memcpy(data->id_p, config->nai, config->nai_len); 61 data->id_p_len = config->nai_len; 62 } 63 if (data->id_p == NULL) { 64 wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); 65 os_free(data); 66 return NULL; 67 } 68 69 return data; 70 } 71 72 73 static void eap_psk_deinit(struct eap_sm *sm, void *priv) 74 { 75 struct eap_psk_data *data = priv; 76 os_free(data->id_s); 77 os_free(data->id_p); 78 os_free(data); 79 } 80 81 82 static u8 * eap_psk_process_1(struct eap_psk_data *data, 83 struct eap_method_ret *ret, 84 const u8 *reqData, size_t reqDataLen, 85 size_t *respDataLen) 86 { 87 const struct eap_psk_hdr_1 *hdr1; 88 struct eap_psk_hdr_2 *hdr2; 89 u8 *resp, *buf, *pos; 90 size_t buflen; 91 92 wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); 93 94 hdr1 = (const struct eap_psk_hdr_1 *) reqData; 95 if (reqDataLen < sizeof(*hdr1) || 96 be_to_host16(hdr1->length) < sizeof(*hdr1) || 97 be_to_host16(hdr1->length) > reqDataLen) { 98 wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " 99 "length (%lu %d; expected %lu or more)", 100 (unsigned long) reqDataLen, 101 be_to_host16(hdr1->length), 102 (unsigned long) sizeof(*hdr1)); 103 ret->ignore = TRUE; 104 return NULL; 105 } 106 wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); 107 if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) { 108 wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", 109 EAP_PSK_FLAGS_GET_T(hdr1->flags)); 110 ret->methodState = METHOD_DONE; 111 ret->decision = DECISION_FAIL; 112 return NULL; 113 } 114 wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s, 115 EAP_PSK_RAND_LEN); 116 os_free(data->id_s); 117 data->id_s_len = be_to_host16(hdr1->length) - sizeof(*hdr1); 118 data->id_s = os_malloc(data->id_s_len); 119 if (data->id_s == NULL) { 120 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " 121 "ID_S (len=%lu)", (unsigned long) data->id_s_len); 122 ret->ignore = TRUE; 123 return NULL; 124 } 125 os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); 126 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", 127 data->id_s, data->id_s_len); 128 129 if (hostapd_get_rand(data->rand_p, EAP_PSK_RAND_LEN)) { 130 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 131 ret->ignore = TRUE; 132 return NULL; 133 } 134 135 *respDataLen = sizeof(*hdr2) + data->id_p_len; 136 resp = os_malloc(*respDataLen); 137 if (resp == NULL) 138 return NULL; 139 hdr2 = (struct eap_psk_hdr_2 *) resp; 140 hdr2->code = EAP_CODE_RESPONSE; 141 hdr2->identifier = hdr1->identifier; 142 hdr2->length = host_to_be16(*respDataLen); 143 hdr2->type = EAP_TYPE_PSK; 144 hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */ 145 os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); 146 os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); 147 os_memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len); 148 /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 149 buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; 150 buf = os_malloc(buflen); 151 if (buf == NULL) { 152 os_free(resp); 153 return NULL; 154 } 155 os_memcpy(buf, data->id_p, data->id_p_len); 156 pos = buf + data->id_p_len; 157 os_memcpy(pos, data->id_s, data->id_s_len); 158 pos += data->id_s_len; 159 os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN); 160 pos += EAP_PSK_RAND_LEN; 161 os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 162 omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p); 163 os_free(buf); 164 wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, 165 EAP_PSK_RAND_LEN); 166 wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); 167 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", 168 (u8 *) (hdr2 + 1), data->id_p_len); 169 170 data->state = PSK_MAC_SENT; 171 172 return resp; 173 } 174 175 176 static u8 * eap_psk_process_3(struct eap_psk_data *data, 177 struct eap_method_ret *ret, 178 const u8 *reqData, size_t reqDataLen, 179 size_t *respDataLen) 180 { 181 const struct eap_psk_hdr_3 *hdr3; 182 struct eap_psk_hdr_4 *hdr4; 183 u8 *resp, *buf, *rpchannel, nonce[16], *decrypted; 184 const u8 *pchannel, *tag, *msg; 185 u8 mac[EAP_PSK_MAC_LEN]; 186 size_t buflen, left, data_len; 187 int failed = 0; 188 189 wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); 190 191 hdr3 = (const struct eap_psk_hdr_3 *) reqData; 192 left = be_to_host16(hdr3->length); 193 if (left < sizeof(*hdr3) || reqDataLen < left) { 194 wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " 195 "length (%lu %d; expected %lu)", 196 (unsigned long) reqDataLen, 197 be_to_host16(hdr3->length), 198 (unsigned long) sizeof(*hdr3)); 199 ret->ignore = TRUE; 200 return NULL; 201 } 202 left -= sizeof(*hdr3); 203 pchannel = (const u8 *) (hdr3 + 1); 204 wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); 205 if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) { 206 wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", 207 EAP_PSK_FLAGS_GET_T(hdr3->flags)); 208 ret->methodState = METHOD_DONE; 209 ret->decision = DECISION_FAIL; 210 return NULL; 211 } 212 wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, 213 EAP_PSK_RAND_LEN); 214 wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); 215 wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); 216 217 if (left < 4 + 16 + 1) { 218 wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 219 "third message (len=%lu, expected 21)", 220 (unsigned long) left); 221 ret->ignore = TRUE; 222 return NULL; 223 } 224 225 /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 226 buflen = data->id_s_len + EAP_PSK_RAND_LEN; 227 buf = os_malloc(buflen); 228 if (buf == NULL) 229 return NULL; 230 os_memcpy(buf, data->id_s, data->id_s_len); 231 os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); 232 omac1_aes_128(data->ak, buf, buflen, mac); 233 os_free(buf); 234 if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { 235 wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " 236 "message"); 237 ret->methodState = METHOD_DONE; 238 ret->decision = DECISION_FAIL; 239 return NULL; 240 } 241 wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); 242 243 eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, 244 data->msk, data->emsk); 245 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 246 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 247 wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 248 249 os_memset(nonce, 0, 12); 250 os_memcpy(nonce + 12, pchannel, 4); 251 pchannel += 4; 252 left -= 4; 253 254 tag = pchannel; 255 pchannel += 16; 256 left -= 16; 257 258 msg = pchannel; 259 260 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", 261 nonce, sizeof(nonce)); 262 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", reqData, 5); 263 wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); 264 265 decrypted = os_malloc(left); 266 if (decrypted == NULL) { 267 ret->methodState = METHOD_DONE; 268 ret->decision = DECISION_FAIL; 269 return NULL; 270 } 271 os_memcpy(decrypted, msg, left); 272 273 if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 274 reqData, 22, decrypted, left, tag)) { 275 wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 276 os_free(decrypted); 277 return NULL; 278 } 279 wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 280 decrypted, left); 281 282 /* Verify R flag */ 283 switch (decrypted[0] >> 6) { 284 case EAP_PSK_R_FLAG_CONT: 285 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 286 failed = 1; 287 break; 288 case EAP_PSK_R_FLAG_DONE_SUCCESS: 289 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 290 break; 291 case EAP_PSK_R_FLAG_DONE_FAILURE: 292 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 293 wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " 294 "authentication"); 295 failed = 1; 296 break; 297 } 298 299 *respDataLen = sizeof(*hdr4) + 4 + 16 + 1; 300 resp = os_malloc(*respDataLen + 1); 301 if (resp == NULL) { 302 os_free(decrypted); 303 return NULL; 304 } 305 hdr4 = (struct eap_psk_hdr_4 *) resp; 306 hdr4->code = EAP_CODE_RESPONSE; 307 hdr4->identifier = hdr3->identifier; 308 hdr4->length = host_to_be16(*respDataLen); 309 hdr4->type = EAP_TYPE_PSK; 310 hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ 311 os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); 312 rpchannel = (u8 *) (hdr4 + 1); 313 314 /* nonce++ */ 315 inc_byte_array(nonce, sizeof(nonce)); 316 os_memcpy(rpchannel, nonce + 12, 4); 317 318 data_len = 1; 319 if (decrypted[0] & EAP_PSK_E_FLAG) { 320 wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag"); 321 failed = 1; 322 rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) | 323 EAP_PSK_E_FLAG; 324 if (left > 1) { 325 /* Add empty EXT_Payload with same EXT_Type */ 326 (*respDataLen)++; 327 hdr4->length = host_to_be16(*respDataLen); 328 rpchannel[4 + 16 + 1] = decrypted[1]; 329 data_len++; 330 } 331 } else if (failed) 332 rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6; 333 else 334 rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 335 336 wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", 337 rpchannel + 4 + 16, data_len); 338 aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 22, 339 rpchannel + 4 + 16, data_len, rpchannel + 4); 340 wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", 341 rpchannel, 4 + 16 + data_len); 342 343 wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", 344 failed ? "un" : ""); 345 data->state = PSK_DONE; 346 ret->methodState = METHOD_DONE; 347 ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; 348 349 os_free(decrypted); 350 351 return resp; 352 } 353 354 355 static u8 * eap_psk_process(struct eap_sm *sm, void *priv, 356 struct eap_method_ret *ret, 357 const u8 *reqData, size_t reqDataLen, 358 size_t *respDataLen) 359 { 360 struct eap_psk_data *data = priv; 361 const u8 *pos; 362 u8 *resp = NULL; 363 size_t len; 364 365 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, 366 reqData, reqDataLen, &len); 367 if (pos == NULL) { 368 ret->ignore = TRUE; 369 return NULL; 370 } 371 len += sizeof(struct eap_hdr) + 1; 372 373 ret->ignore = FALSE; 374 ret->methodState = METHOD_MAY_CONT; 375 ret->decision = DECISION_FAIL; 376 ret->allowNotifications = TRUE; 377 378 switch (data->state) { 379 case PSK_INIT: 380 resp = eap_psk_process_1(data, ret, reqData, len, 381 respDataLen); 382 break; 383 case PSK_MAC_SENT: 384 resp = eap_psk_process_3(data, ret, reqData, len, 385 respDataLen); 386 break; 387 case PSK_DONE: 388 wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " 389 "unexpected message"); 390 ret->ignore = TRUE; 391 return NULL; 392 } 393 394 if (ret->methodState == METHOD_DONE) { 395 ret->allowNotifications = FALSE; 396 } 397 398 return resp; 399 } 400 401 402 static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) 403 { 404 struct eap_psk_data *data = priv; 405 return data->state == PSK_DONE; 406 } 407 408 409 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 410 { 411 struct eap_psk_data *data = priv; 412 u8 *key; 413 414 if (data->state != PSK_DONE) 415 return NULL; 416 417 key = os_malloc(EAP_MSK_LEN); 418 if (key == NULL) 419 return NULL; 420 421 *len = EAP_MSK_LEN; 422 os_memcpy(key, data->msk, EAP_MSK_LEN); 423 424 return key; 425 } 426 427 428 static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 429 { 430 struct eap_psk_data *data = priv; 431 u8 *key; 432 433 if (data->state != PSK_DONE) 434 return NULL; 435 436 key = os_malloc(EAP_EMSK_LEN); 437 if (key == NULL) 438 return NULL; 439 440 *len = EAP_EMSK_LEN; 441 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 442 443 return key; 444 } 445 446 447 int eap_peer_psk_register(void) 448 { 449 struct eap_method *eap; 450 int ret; 451 452 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 453 EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 454 if (eap == NULL) 455 return -1; 456 457 eap->init = eap_psk_init; 458 eap->deinit = eap_psk_deinit; 459 eap->process = eap_psk_process; 460 eap->isKeyAvailable = eap_psk_isKeyAvailable; 461 eap->getKey = eap_psk_getKey; 462 eap->get_emsk = eap_psk_get_emsk; 463 464 ret = eap_peer_method_register(eap); 465 if (ret) 466 eap_peer_method_free(eap); 467 return ret; 468 } 469