1 /* 2 * EAP-TEAP common helper functions (RFC 7170) 3 * Copyright (c) 2008-2019, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "crypto/sha1.h" 13 #include "crypto/sha256.h" 14 #include "crypto/sha384.h" 15 #include "crypto/tls.h" 16 #include "eap_defs.h" 17 #include "eap_teap_common.h" 18 19 20 void eap_teap_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len) 21 { 22 struct teap_tlv_hdr hdr; 23 24 hdr.tlv_type = host_to_be16(type); 25 hdr.length = host_to_be16(len); 26 wpabuf_put_data(buf, &hdr, sizeof(hdr)); 27 } 28 29 30 void eap_teap_put_tlv(struct wpabuf *buf, u16 type, const void *data, u16 len) 31 { 32 eap_teap_put_tlv_hdr(buf, type, len); 33 wpabuf_put_data(buf, data, len); 34 } 35 36 37 void eap_teap_put_tlv_buf(struct wpabuf *buf, u16 type, 38 const struct wpabuf *data) 39 { 40 eap_teap_put_tlv_hdr(buf, type, wpabuf_len(data)); 41 wpabuf_put_buf(buf, data); 42 } 43 44 45 struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf) 46 { 47 struct wpabuf *e; 48 49 if (!buf) 50 return NULL; 51 52 /* Encapsulate EAP packet in EAP-Payload TLV */ 53 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add EAP-Payload TLV"); 54 e = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + wpabuf_len(buf)); 55 if (!e) { 56 wpa_printf(MSG_ERROR, 57 "EAP-TEAP: Failed to allocate memory for TLV encapsulation"); 58 wpabuf_free(buf); 59 return NULL; 60 } 61 eap_teap_put_tlv_buf(e, TEAP_TLV_MANDATORY | TEAP_TLV_EAP_PAYLOAD, buf); 62 wpabuf_free(buf); 63 64 /* TODO: followed by optional TLVs associated with the EAP packet */ 65 66 return e; 67 } 68 69 70 static int eap_teap_tls_prf(const u8 *secret, size_t secret_len, 71 const char *label, const u8 *seed, size_t seed_len, 72 u8 *out, size_t outlen) 73 { 74 /* TODO: TLS-PRF for TLSv1.3 */ 75 return tls_prf_sha256(secret, secret_len, label, seed, seed_len, 76 out, outlen); 77 } 78 79 80 int eap_teap_derive_eap_msk(const u8 *simck, u8 *msk) 81 { 82 /* 83 * RFC 7170, Section 5.4: EAP Master Session Key Generation 84 * MSK = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64) 85 */ 86 87 if (eap_teap_tls_prf(simck, EAP_TEAP_SIMCK_LEN, 88 "Session Key Generating Function", (u8 *) "", 0, 89 msk, EAP_TEAP_KEY_LEN) < 0) 90 return -1; 91 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (MSK)", 92 msk, EAP_TEAP_KEY_LEN); 93 return 0; 94 } 95 96 97 int eap_teap_derive_eap_emsk(const u8 *simck, u8 *emsk) 98 { 99 /* 100 * RFC 7170, Section 5.4: EAP Master Session Key Generation 101 * EMSK = TLS-PRF(S-IMCK[j], 102 * "Extended Session Key Generating Function", 64) 103 */ 104 105 if (eap_teap_tls_prf(simck, EAP_TEAP_SIMCK_LEN, 106 "Extended Session Key Generating Function", 107 (u8 *) "", 0, emsk, EAP_EMSK_LEN) < 0) 108 return -1; 109 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (EMSK)", 110 emsk, EAP_EMSK_LEN); 111 return 0; 112 } 113 114 115 int eap_teap_derive_cmk_basic_pw_auth(const u8 *s_imck_msk, u8 *cmk) 116 { 117 u8 imsk[32], imck[EAP_TEAP_IMCK_LEN]; 118 int res; 119 120 /* FIX: The Basic-Password-Auth (i.e., no inner EAP) case is 121 * not fully defined in RFC 7170, so this CMK derivation may 122 * need to be changed if a fixed definition is eventually 123 * published. For now, derive CMK[0] based on S-IMCK[0] and 124 * IMSK of 32 octets of zeros. */ 125 os_memset(imsk, 0, 32); 126 res = eap_teap_tls_prf(s_imck_msk, EAP_TEAP_SIMCK_LEN, 127 "Inner Methods Compound Keys", 128 imsk, 32, imck, sizeof(imck)); 129 if (res < 0) 130 return -1; 131 os_memcpy(cmk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN); 132 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: CMK[no-inner-EAP]", 133 cmk, EAP_TEAP_CMK_LEN); 134 forced_memzero(imck, sizeof(imck)); 135 return 0; 136 } 137 138 139 int eap_teap_derive_imck(const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk, 140 const u8 *msk, size_t msk_len, 141 const u8 *emsk, size_t emsk_len, 142 u8 *s_imck_msk, u8 *cmk_msk, 143 u8 *s_imck_emsk, u8 *cmk_emsk) 144 { 145 u8 imsk[64], imck[EAP_TEAP_IMCK_LEN]; 146 int res; 147 148 /* 149 * RFC 7170, Section 5.2: 150 * IMSK = First 32 octets of TLS-PRF(EMSK, "TEAPbindkey@ietf.org" | 151 * "\0" | 64) 152 * (if EMSK is not available, MSK is used instead; if neither is 153 * available, IMSK is 32 octets of zeros; MSK is truncated to 32 octets 154 * or padded to 32 octets, if needed) 155 * (64 is encoded as a 2-octet field in network byte order) 156 * 157 * S-IMCK[0] = session_key_seed 158 * IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys", 159 * IMSK[j], 60) 160 * S-IMCK[j] = first 40 octets of IMCK[j] 161 * CMK[j] = last 20 octets of IMCK[j] 162 */ 163 164 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK[j]", msk, msk_len); 165 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK[j]", emsk, emsk_len); 166 167 if (emsk && emsk_len > 0) { 168 u8 context[3]; 169 170 context[0] = 0; 171 context[1] = 0; 172 context[2] = 64; 173 if (eap_teap_tls_prf(emsk, emsk_len, "TEAPbindkey@ietf.org", 174 context, sizeof(context), imsk, 64) < 0) 175 return -1; 176 177 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK", 178 imsk, 32); 179 180 res = eap_teap_tls_prf(prev_s_imck_emsk, EAP_TEAP_SIMCK_LEN, 181 "Inner Methods Compound Keys", 182 imsk, 32, imck, EAP_TEAP_IMCK_LEN); 183 forced_memzero(imsk, sizeof(imsk)); 184 if (res < 0) 185 return -1; 186 187 os_memcpy(s_imck_emsk, imck, EAP_TEAP_SIMCK_LEN); 188 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK S-IMCK[j]", 189 s_imck_emsk, EAP_TEAP_SIMCK_LEN); 190 os_memcpy(cmk_emsk, &imck[EAP_TEAP_SIMCK_LEN], 191 EAP_TEAP_CMK_LEN); 192 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK CMK[j]", 193 cmk_emsk, EAP_TEAP_CMK_LEN); 194 forced_memzero(imck, EAP_TEAP_IMCK_LEN); 195 } 196 197 if (msk && msk_len > 0) { 198 size_t copy_len = msk_len; 199 200 os_memset(imsk, 0, 32); /* zero pad, if needed */ 201 if (copy_len > 32) 202 copy_len = 32; 203 os_memcpy(imsk, msk, copy_len); 204 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from MSK", imsk, 32); 205 } else { 206 os_memset(imsk, 0, 32); 207 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32); 208 } 209 210 res = eap_teap_tls_prf(prev_s_imck_msk, EAP_TEAP_SIMCK_LEN, 211 "Inner Methods Compound Keys", 212 imsk, 32, imck, EAP_TEAP_IMCK_LEN); 213 forced_memzero(imsk, sizeof(imsk)); 214 if (res < 0) 215 return -1; 216 217 os_memcpy(s_imck_msk, imck, EAP_TEAP_SIMCK_LEN); 218 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK S-IMCK[j]", 219 s_imck_msk, EAP_TEAP_SIMCK_LEN); 220 os_memcpy(cmk_msk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN); 221 wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK CMK[j]", 222 cmk_msk, EAP_TEAP_CMK_LEN); 223 forced_memzero(imck, EAP_TEAP_IMCK_LEN); 224 225 return 0; 226 } 227 228 229 static int tls_cipher_suite_match(const u16 *list, size_t count, u16 cs) 230 { 231 size_t i; 232 233 for (i = 0; i < count; i++) { 234 if (list[i] == cs) 235 return 1; 236 } 237 238 return 0; 239 } 240 241 242 static int tls_cipher_suite_mac_sha1(u16 cs) 243 { 244 static const u16 sha1_cs[] = { 245 0x0005, 0x0007, 0x000a, 0x000d, 0x0010, 0x0013, 0x0016, 0x001b, 246 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 247 0x0037, 0x0038, 0x0039, 0x003a, 0x0041, 0x0042, 0x0043, 0x0044, 248 0x0045, 0x0046, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 249 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 250 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 251 0x009a, 0x009b, 252 0xc002, 0xc003, 0xc004, 0xc005, 0xc007, 0xc008, 0xc009, 0xc009, 253 0xc00a, 0xc00c, 0xc00d, 0xc00e, 0xc00f, 0xc011, 0xc012, 0xc013, 254 0xc014, 0xc016, 0xc017, 0xc018, 0xc019, 0xc01a, 0xc01b, 0xc01c, 255 0xc014, 0xc01e, 0xc01f, 0xc020, 0xc021, 0xc022, 0xc033, 0xc034, 256 0xc035, 0xc036 257 }; 258 259 return tls_cipher_suite_match(sha1_cs, ARRAY_SIZE(sha1_cs), cs); 260 } 261 262 263 static int tls_cipher_suite_mac_sha256(u16 cs) 264 { 265 static const u16 sha256_cs[] = { 266 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0067, 0x0068, 0x0069, 267 0x006a, 0x006b, 0x006c, 0x006d, 0x009c, 0x009e, 0x00a0, 0x00a2, 268 0x00a4, 0x00a6, 0x00a8, 0x00aa, 0x00ac, 0x00ae, 0x00b2, 0x00b6, 269 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bd, 0x00be, 0x00be, 270 0x00bf, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 271 0x1301, 0x1303, 0x1304, 0x1305, 272 0xc023, 0xc025, 0xc027, 0xc029, 0xc02b, 0xc02d, 0xc02f, 0xc031, 273 0xc037, 0xc03c, 0xc03e, 0xc040, 0xc040, 0xc042, 0xc044, 0xc046, 274 0xc048, 0xc04a, 0xc04c, 0xc04e, 0xc050, 0xc052, 0xc054, 0xc056, 275 0xc058, 0xc05a, 0xc05c, 0xc05e, 0xc060, 0xc062, 0xc064, 0xc066, 276 0xc068, 0xc06a, 0xc06c, 0xc06e, 0xc070, 0xc072, 0xc074, 0xc076, 277 0xc078, 0xc07a, 0xc07c, 0xc07e, 0xc080, 0xc082, 0xc084, 0xc086, 278 0xc088, 0xc08a, 0xc08c, 0xc08e, 0xc090, 0xc092, 0xc094, 0xc096, 279 0xc098, 0xc09a, 0xc0b0, 0xc0b2, 0xc0b4, 280 0xcca8, 0xcca9, 0xccaa, 0xccab, 0xccac, 0xccad, 0xccae, 281 0xd001, 0xd003, 0xd005 282 }; 283 284 return tls_cipher_suite_match(sha256_cs, ARRAY_SIZE(sha256_cs), cs); 285 } 286 287 288 static int tls_cipher_suite_mac_sha384(u16 cs) 289 { 290 static const u16 sha384_cs[] = { 291 0x009d, 0x009f, 0x00a1, 0x00a3, 0x00a5, 0x00a7, 0x00a9, 0x00ab, 292 0x00ad, 0x00af, 0x00b3, 0x00b7, 0x1302, 293 0xc024, 0xc026, 0xc028, 0xc02a, 0xc02c, 0xc02e, 0xc030, 0xc032, 294 0xc038, 0xc03d, 0xc03f, 0xc041, 0xc043, 0xc045, 0xc047, 0xc049, 295 0xc04b, 0xc04d, 0xc04f, 0xc051, 0xc053, 0xc055, 0xc057, 0xc059, 296 0xc05b, 0xc05d, 0xc05f, 0xc061, 0xc063, 0xc065, 0xc067, 0xc069, 297 0xc06b, 0xc06d, 0xc06f, 0xc071, 0xc073, 0xc075, 0xc077, 0xc079, 298 0xc07b, 0xc07d, 0xc07f, 0xc081, 0xc083, 0xc085, 0xc087, 0xc089, 299 0xc08b, 0xc08d, 0xc08f, 0xc091, 0xc093, 0xc095, 0xc097, 0xc099, 300 0xc09b, 0xc0b1, 0xc0b3, 0xc0b5, 301 0xd002 302 }; 303 304 return tls_cipher_suite_match(sha384_cs, ARRAY_SIZE(sha384_cs), cs); 305 } 306 307 308 static int eap_teap_tls_mac(u16 tls_cs, const u8 *cmk, size_t cmk_len, 309 const u8 *buffer, size_t buffer_len, 310 u8 *mac, size_t mac_len) 311 { 312 int res; 313 u8 tmp[48]; 314 315 os_memset(tmp, 0, sizeof(tmp)); 316 os_memset(mac, 0, mac_len); 317 318 if (tls_cipher_suite_mac_sha1(tls_cs)) { 319 wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA1"); 320 res = hmac_sha1(cmk, cmk_len, buffer, buffer_len, tmp); 321 } else if (tls_cipher_suite_mac_sha256(tls_cs)) { 322 wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA256"); 323 res = hmac_sha256(cmk, cmk_len, buffer, buffer_len, tmp); 324 } else if (tls_cipher_suite_mac_sha384(tls_cs)) { 325 wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA384"); 326 res = hmac_sha384(cmk, cmk_len, buffer, buffer_len, tmp); 327 } else { 328 wpa_printf(MSG_INFO, 329 "EAP-TEAP: Unsupported TLS cipher suite 0x%04x", 330 tls_cs); 331 res = -1; 332 } 333 if (res < 0) 334 return res; 335 336 /* FIX: RFC 7170 does not describe how to handle truncation of the 337 * Compound MAC or if the fields are supposed to be of variable length 338 * based on the negotiated TLS cipher suite (they are defined as having 339 * fixed size of 20 octets in the TLV description) */ 340 if (mac_len > sizeof(tmp)) 341 mac_len = sizeof(tmp); 342 os_memcpy(mac, tmp, mac_len); 343 return 0; 344 } 345 346 347 int eap_teap_compound_mac(u16 tls_cs, const struct teap_tlv_crypto_binding *cb, 348 const struct wpabuf *server_outer_tlvs, 349 const struct wpabuf *peer_outer_tlvs, 350 const u8 *cmk, u8 *compound_mac) 351 { 352 u8 *pos, *buffer; 353 size_t bind_len, buffer_len; 354 struct teap_tlv_crypto_binding *tmp_cb; 355 int res; 356 357 /* RFC 7170, Section 5.3 */ 358 bind_len = sizeof(struct teap_tlv_hdr) + be_to_host16(cb->length); 359 buffer_len = bind_len + 1; 360 if (server_outer_tlvs) 361 buffer_len += wpabuf_len(server_outer_tlvs); 362 if (peer_outer_tlvs) 363 buffer_len += wpabuf_len(peer_outer_tlvs); 364 buffer = os_malloc(buffer_len); 365 if (!buffer) 366 return -1; 367 368 pos = buffer; 369 /* 1. The entire Crypto-Binding TLV attribute with both the EMSK and MSK 370 * Compound MAC fields zeroed out. */ 371 os_memcpy(pos, cb, bind_len); 372 pos += bind_len; 373 tmp_cb = (struct teap_tlv_crypto_binding *) buffer; 374 os_memset(tmp_cb->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN); 375 os_memset(tmp_cb->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN); 376 377 /* 2. The EAP Type sent by the other party in the first TEAP message. */ 378 /* This is supposed to be the EAP Type sent by the other party in the 379 * first TEAP message, but since we cannot get here without having 380 * successfully negotiated use of TEAP, this can only be the fixed EAP 381 * Type of TEAP. */ 382 *pos++ = EAP_TYPE_TEAP; 383 384 /* 3. All the Outer TLVs from the first TEAP message sent by EAP server 385 * to peer. */ 386 if (server_outer_tlvs) { 387 os_memcpy(pos, wpabuf_head(server_outer_tlvs), 388 wpabuf_len(server_outer_tlvs)); 389 pos += wpabuf_len(server_outer_tlvs); 390 } 391 392 /* 4. All the Outer TLVs from the first TEAP message sent by the peer to 393 * the EAP server. */ 394 if (peer_outer_tlvs) { 395 os_memcpy(pos, wpabuf_head(peer_outer_tlvs), 396 wpabuf_len(peer_outer_tlvs)); 397 pos += wpabuf_len(peer_outer_tlvs); 398 } 399 400 buffer_len = pos - buffer; 401 402 wpa_hexdump_key(MSG_MSGDUMP, 403 "EAP-TEAP: CMK for Compound MAC calculation", 404 cmk, EAP_TEAP_CMK_LEN); 405 wpa_hexdump(MSG_MSGDUMP, 406 "EAP-TEAP: BUFFER for Compound MAC calculation", 407 buffer, buffer_len); 408 res = eap_teap_tls_mac(tls_cs, cmk, EAP_TEAP_CMK_LEN, 409 buffer, buffer_len, 410 compound_mac, EAP_TEAP_COMPOUND_MAC_LEN); 411 os_free(buffer); 412 413 return res; 414 } 415 416 417 int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv, 418 int tlv_type, u8 *pos, size_t len) 419 { 420 switch (tlv_type) { 421 case TEAP_TLV_RESULT: 422 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Result TLV", pos, len); 423 if (tlv->result) { 424 wpa_printf(MSG_INFO, 425 "EAP-TEAP: More than one Result TLV in the message"); 426 tlv->result = TEAP_STATUS_FAILURE; 427 return -2; 428 } 429 if (len < 2) { 430 wpa_printf(MSG_INFO, "EAP-TEAP: Too short Result TLV"); 431 tlv->result = TEAP_STATUS_FAILURE; 432 break; 433 } 434 tlv->result = WPA_GET_BE16(pos); 435 if (tlv->result != TEAP_STATUS_SUCCESS && 436 tlv->result != TEAP_STATUS_FAILURE) { 437 wpa_printf(MSG_INFO, "EAP-TEAP: Unknown Result %d", 438 tlv->result); 439 tlv->result = TEAP_STATUS_FAILURE; 440 } 441 wpa_printf(MSG_DEBUG, "EAP-TEAP: Result: %s", 442 tlv->result == TEAP_STATUS_SUCCESS ? 443 "Success" : "Failure"); 444 break; 445 case TEAP_TLV_NAK: 446 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: NAK TLV", pos, len); 447 if (len < 6) { 448 wpa_printf(MSG_INFO, "EAP-TEAP: Too short NAK TLV"); 449 tlv->result = TEAP_STATUS_FAILURE; 450 break; 451 } 452 tlv->nak = pos; 453 tlv->nak_len = len; 454 break; 455 case TEAP_TLV_REQUEST_ACTION: 456 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Request-Action TLV", 457 pos, len); 458 if (tlv->request_action) { 459 wpa_printf(MSG_INFO, 460 "EAP-TEAP: More than one Request-Action TLV in the message"); 461 tlv->iresult = TEAP_STATUS_FAILURE; 462 return -2; 463 } 464 if (len < 2) { 465 wpa_printf(MSG_INFO, 466 "EAP-TEAP: Too short Request-Action TLV"); 467 tlv->iresult = TEAP_STATUS_FAILURE; 468 break; 469 } 470 tlv->request_action_status = pos[0]; 471 tlv->request_action = pos[1]; 472 wpa_printf(MSG_DEBUG, 473 "EAP-TEAP: Request-Action: Status=%u Action=%u", 474 tlv->request_action_status, tlv->request_action); 475 break; 476 case TEAP_TLV_EAP_PAYLOAD: 477 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EAP-Payload TLV", 478 pos, len); 479 if (tlv->eap_payload_tlv) { 480 wpa_printf(MSG_INFO, 481 "EAP-TEAP: More than one EAP-Payload TLV in the message"); 482 tlv->iresult = TEAP_STATUS_FAILURE; 483 return -2; 484 } 485 tlv->eap_payload_tlv = pos; 486 tlv->eap_payload_tlv_len = len; 487 break; 488 case TEAP_TLV_INTERMEDIATE_RESULT: 489 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Intermediate-Result TLV", 490 pos, len); 491 if (len < 2) { 492 wpa_printf(MSG_INFO, 493 "EAP-TEAP: Too short Intermediate-Result TLV"); 494 tlv->iresult = TEAP_STATUS_FAILURE; 495 break; 496 } 497 if (tlv->iresult) { 498 wpa_printf(MSG_INFO, 499 "EAP-TEAP: More than one Intermediate-Result TLV in the message"); 500 tlv->iresult = TEAP_STATUS_FAILURE; 501 return -2; 502 } 503 tlv->iresult = WPA_GET_BE16(pos); 504 if (tlv->iresult != TEAP_STATUS_SUCCESS && 505 tlv->iresult != TEAP_STATUS_FAILURE) { 506 wpa_printf(MSG_INFO, 507 "EAP-TEAP: Unknown Intermediate Result %d", 508 tlv->iresult); 509 tlv->iresult = TEAP_STATUS_FAILURE; 510 } 511 wpa_printf(MSG_DEBUG, "EAP-TEAP: Intermediate Result: %s", 512 tlv->iresult == TEAP_STATUS_SUCCESS ? 513 "Success" : "Failure"); 514 break; 515 case TEAP_TLV_PAC: 516 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: PAC TLV", pos, len); 517 if (tlv->pac) { 518 wpa_printf(MSG_INFO, 519 "EAP-TEAP: More than one PAC TLV in the message"); 520 tlv->iresult = TEAP_STATUS_FAILURE; 521 return -2; 522 } 523 tlv->pac = pos; 524 tlv->pac_len = len; 525 break; 526 case TEAP_TLV_CRYPTO_BINDING: 527 wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Crypto-Binding TLV", 528 pos, len); 529 if (tlv->crypto_binding) { 530 wpa_printf(MSG_INFO, 531 "EAP-TEAP: More than one Crypto-Binding TLV in the message"); 532 tlv->iresult = TEAP_STATUS_FAILURE; 533 return -2; 534 } 535 tlv->crypto_binding_len = sizeof(struct teap_tlv_hdr) + len; 536 if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) { 537 wpa_printf(MSG_INFO, 538 "EAP-TEAP: Too short Crypto-Binding TLV"); 539 tlv->iresult = TEAP_STATUS_FAILURE; 540 return -2; 541 } 542 tlv->crypto_binding = (struct teap_tlv_crypto_binding *) 543 (pos - sizeof(struct teap_tlv_hdr)); 544 break; 545 case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ: 546 wpa_hexdump_ascii(MSG_MSGDUMP, 547 "EAP-TEAP: Basic-Password-Auth-Req TLV", 548 pos, len); 549 if (tlv->basic_auth_req) { 550 wpa_printf(MSG_INFO, 551 "EAP-TEAP: More than one Basic-Password-Auth-Req TLV in the message"); 552 tlv->iresult = TEAP_STATUS_FAILURE; 553 return -2; 554 } 555 tlv->basic_auth_req = pos; 556 tlv->basic_auth_req_len = len; 557 break; 558 case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP: 559 wpa_hexdump_ascii(MSG_MSGDUMP, 560 "EAP-TEAP: Basic-Password-Auth-Resp TLV", 561 pos, len); 562 if (tlv->basic_auth_resp) { 563 wpa_printf(MSG_INFO, 564 "EAP-TEAP: More than one Basic-Password-Auth-Resp TLV in the message"); 565 tlv->iresult = TEAP_STATUS_FAILURE; 566 return -2; 567 } 568 tlv->basic_auth_resp = pos; 569 tlv->basic_auth_resp_len = len; 570 break; 571 default: 572 /* Unknown TLV */ 573 return -1; 574 } 575 576 return 0; 577 } 578 579 580 const char * eap_teap_tlv_type_str(enum teap_tlv_types type) 581 { 582 switch (type) { 583 case TEAP_TLV_AUTHORITY_ID: 584 return "Authority-ID"; 585 case TEAP_TLV_IDENTITY_TYPE: 586 return "Identity-Type"; 587 case TEAP_TLV_RESULT: 588 return "Result"; 589 case TEAP_TLV_NAK: 590 return "NAK"; 591 case TEAP_TLV_ERROR: 592 return "Error"; 593 case TEAP_TLV_CHANNEL_BINDING: 594 return "Channel-Binding"; 595 case TEAP_TLV_VENDOR_SPECIFIC: 596 return "Vendor-Specific"; 597 case TEAP_TLV_REQUEST_ACTION: 598 return "Request-Action"; 599 case TEAP_TLV_EAP_PAYLOAD: 600 return "EAP-Payload"; 601 case TEAP_TLV_INTERMEDIATE_RESULT: 602 return "Intermediate-Result"; 603 case TEAP_TLV_PAC: 604 return "PAC"; 605 case TEAP_TLV_CRYPTO_BINDING: 606 return "Crypto-Binding"; 607 case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ: 608 return "Basic-Password-Auth-Req"; 609 case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP: 610 return "Basic-Password-Auth-Resp"; 611 case TEAP_TLV_PKCS7: 612 return "PKCS#7"; 613 case TEAP_TLV_PKCS10: 614 return "PKCS#10"; 615 case TEAP_TLV_TRUSTED_SERVER_ROOT: 616 return "Trusted-Server-Root"; 617 } 618 619 return "?"; 620 } 621 622 623 struct wpabuf * eap_teap_tlv_result(int status, int intermediate) 624 { 625 struct wpabuf *buf; 626 struct teap_tlv_result *result; 627 628 if (status != TEAP_STATUS_FAILURE && status != TEAP_STATUS_SUCCESS) 629 return NULL; 630 631 buf = wpabuf_alloc(sizeof(*result)); 632 if (!buf) 633 return NULL; 634 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add %sResult TLV(status=%s)", 635 intermediate ? "Intermediate-" : "", 636 status == TEAP_STATUS_SUCCESS ? "Success" : "Failure"); 637 result = wpabuf_put(buf, sizeof(*result)); 638 result->tlv_type = host_to_be16(TEAP_TLV_MANDATORY | 639 (intermediate ? 640 TEAP_TLV_INTERMEDIATE_RESULT : 641 TEAP_TLV_RESULT)); 642 result->length = host_to_be16(2); 643 result->status = host_to_be16(status); 644 return buf; 645 } 646 647 648 struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error) 649 { 650 struct wpabuf *buf; 651 652 buf = wpabuf_alloc(4 + 4); 653 if (!buf) 654 return NULL; 655 wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Error TLV(Error Code=%d)", 656 error); 657 wpabuf_put_be16(buf, TEAP_TLV_MANDATORY | TEAP_TLV_ERROR); 658 wpabuf_put_be16(buf, 4); 659 wpabuf_put_be32(buf, error); 660 return buf; 661 } 662 663 664 int eap_teap_allowed_anon_prov_phase2_method(u8 type) 665 { 666 /* RFC 7170, Section 3.8.3: MUST provide mutual authentication, 667 * provide key generation, and be resistant to dictionary attack. 668 * Section 3.8 also mentions requirement for using EMSK Compound MAC. */ 669 return type == EAP_TYPE_PWD || type == EAP_TYPE_EKE; 670 } 671 672 673 int eap_teap_allowed_anon_prov_cipher_suite(u16 cs) 674 { 675 /* RFC 7170, Section 3.8.3: anonymous ciphersuites MAY be supported as 676 * long as the TLS pre-master secret is generated form contribution from 677 * both peers. Accept the recommended TLS_DH_anon_WITH_AES_128_CBC_SHA 678 * cipher suite and other ciphersuites that use DH in some form, have 679 * SHA-1 or stronger MAC function, and use reasonable strong cipher. */ 680 static const u16 ok_cs[] = { 681 /* DH-anon */ 682 0x0034, 0x003a, 0x006c, 0x006d, 0x00a6, 0x00a7, 683 /* DHE-RSA */ 684 0x0033, 0x0039, 0x0067, 0x006b, 0x009e, 0x009f, 685 /* ECDH-anon */ 686 0xc018, 0xc019, 687 /* ECDH-RSA */ 688 0xc003, 0xc00f, 0xc029, 0xc02a, 0xc031, 0xc032, 689 /* ECDH-ECDSA */ 690 0xc004, 0xc005, 0xc025, 0xc026, 0xc02d, 0xc02e, 691 /* ECDHE-RSA */ 692 0xc013, 0xc014, 0xc027, 0xc028, 0xc02f, 0xc030, 693 /* ECDHE-ECDSA */ 694 0xc009, 0xc00a, 0xc023, 0xc024, 0xc02b, 0xc02c, 695 }; 696 697 return tls_cipher_suite_match(ok_cs, ARRAY_SIZE(ok_cs), cs); 698 } 699