]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/eap_common/eap_teap_common.c
MFV r346563:
[FreeBSD/FreeBSD.git] / contrib / wpa / src / eap_common / eap_teap_common.c
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 }