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