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