Updated to hostap_2_6
[mech_eap.git] / libeap / tests / hwsim / test_eap_proto.py
1 # EAP protocol tests
2 # Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import binascii
8 import hashlib
9 import hmac
10 import logging
11 logger = logging.getLogger()
12 import os
13 import select
14 import struct
15 import threading
16 import time
17
18 import hostapd
19 from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
20 from test_ap_eap import check_eap_capa, check_hlr_auc_gw_support, int_eap_server_params
21 from test_erp import check_erp_capa
22
23 try:
24     import OpenSSL
25     openssl_imported = True
26 except ImportError:
27     openssl_imported = False
28
29 EAP_CODE_REQUEST = 1
30 EAP_CODE_RESPONSE = 2
31 EAP_CODE_SUCCESS = 3
32 EAP_CODE_FAILURE = 4
33 EAP_CODE_INITIATE = 5
34 EAP_CODE_FINISH = 6
35
36 EAP_TYPE_IDENTITY = 1
37 EAP_TYPE_NOTIFICATION = 2
38 EAP_TYPE_NAK = 3
39 EAP_TYPE_MD5 = 4
40 EAP_TYPE_OTP = 5
41 EAP_TYPE_GTC = 6
42 EAP_TYPE_TLS = 13
43 EAP_TYPE_LEAP = 17
44 EAP_TYPE_SIM = 18
45 EAP_TYPE_TTLS = 21
46 EAP_TYPE_AKA = 23
47 EAP_TYPE_PEAP = 25
48 EAP_TYPE_MSCHAPV2 = 26
49 EAP_TYPE_TLV = 33
50 EAP_TYPE_TNC = 38
51 EAP_TYPE_FAST = 43
52 EAP_TYPE_PAX = 46
53 EAP_TYPE_PSK = 47
54 EAP_TYPE_SAKE = 48
55 EAP_TYPE_IKEV2 = 49
56 EAP_TYPE_AKA_PRIME = 50
57 EAP_TYPE_GPSK = 51
58 EAP_TYPE_PWD = 52
59 EAP_TYPE_EKE = 53
60 EAP_TYPE_EXPANDED = 254
61
62 # Type field in EAP-Initiate and EAP-Finish messages
63 EAP_ERP_TYPE_REAUTH_START = 1
64 EAP_ERP_TYPE_REAUTH = 2
65
66 EAP_ERP_TLV_KEYNAME_NAI = 1
67 EAP_ERP_TV_RRK_LIFETIME = 2
68 EAP_ERP_TV_RMSK_LIFETIME = 3
69 EAP_ERP_TLV_DOMAIN_NAME = 4
70 EAP_ERP_TLV_CRYPTOSUITES = 5
71 EAP_ERP_TLV_AUTHORIZATION_INDICATION = 6
72 EAP_ERP_TLV_CALLED_STATION_ID = 128
73 EAP_ERP_TLV_CALLING_STATION_ID = 129
74 EAP_ERP_TLV_NAS_IDENTIFIER = 130
75 EAP_ERP_TLV_NAS_IP_ADDRESS = 131
76 EAP_ERP_TLV_NAS_IPV6_ADDRESS = 132
77
78 def run_pyrad_server(srv, t_stop, eap_handler):
79     srv.RunWithStop(t_stop, eap_handler)
80
81 def start_radius_server(eap_handler):
82     try:
83         import pyrad.server
84         import pyrad.packet
85         import pyrad.dictionary
86     except ImportError:
87         raise HwsimSkip("No pyrad modules available")
88
89     class TestServer(pyrad.server.Server):
90         def _HandleAuthPacket(self, pkt):
91             pyrad.server.Server._HandleAuthPacket(self, pkt)
92             eap = ""
93             for p in pkt[79]:
94                 eap += p
95             eap_req = self.eap_handler(self.ctx, eap)
96             reply = self.CreateReplyPacket(pkt)
97             if eap_req:
98                 while True:
99                     if len(eap_req) > 253:
100                         reply.AddAttribute("EAP-Message", eap_req[0:253])
101                         eap_req = eap_req[253:]
102                     else:
103                         reply.AddAttribute("EAP-Message", eap_req)
104                         break
105             else:
106                 logger.info("No EAP request available")
107             reply.code = pyrad.packet.AccessChallenge
108
109             hmac_obj = hmac.new(reply.secret)
110             hmac_obj.update(struct.pack("B", reply.code))
111             hmac_obj.update(struct.pack("B", reply.id))
112
113             # reply attributes
114             reply.AddAttribute("Message-Authenticator",
115                                "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
116             attrs = reply._PktEncodeAttributes()
117
118             # Length
119             flen = 4 + 16 + len(attrs)
120             hmac_obj.update(struct.pack(">H", flen))
121             hmac_obj.update(pkt.authenticator)
122             hmac_obj.update(attrs)
123             del reply[80]
124             reply.AddAttribute("Message-Authenticator", hmac_obj.digest())
125
126             self.SendReplyPacket(pkt.fd, reply)
127
128         def RunWithStop(self, t_stop, eap_handler):
129             self._poll = select.poll()
130             self._fdmap = {}
131             self._PrepareSockets()
132             self.t_stop = t_stop
133             self.eap_handler = eap_handler
134             self.ctx = {}
135
136             while not t_stop.is_set():
137                 for (fd, event) in self._poll.poll(200):
138                     if event == select.POLLIN:
139                         try:
140                             fdo = self._fdmap[fd]
141                             self._ProcessInput(fdo)
142                         except pyrad.server.ServerPacketError as err:
143                             logger.info("pyrad server dropping packet: " + str(err))
144                         except pyrad.packet.PacketError as err:
145                             logger.info("pyrad server received invalid packet: " + str(err))
146                     else:
147                         logger.error("Unexpected event in pyrad server main loop")
148
149     srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
150                      authport=18138, acctport=18139)
151     srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
152                                                      "radius",
153                                                      "localhost")
154     srv.BindToAddress("")
155     t_stop = threading.Event()
156     t = threading.Thread(target=run_pyrad_server, args=(srv, t_stop, eap_handler))
157     t.start()
158
159     return { 'srv': srv, 'stop': t_stop, 'thread': t }
160
161 def stop_radius_server(srv):
162     srv['stop'].set()
163     srv['thread'].join()
164
165 def start_ap(ap):
166     params = hostapd.wpa2_eap_params(ssid="eap-test")
167     params['auth_server_port'] = "18138"
168     hapd = hostapd.add_ap(ap, params)
169     return hapd
170
171 def test_eap_proto(dev, apdev):
172     """EAP protocol tests"""
173     check_eap_capa(dev[0], "MD5")
174     def eap_handler(ctx, req):
175         logger.info("eap_handler - RX " + req.encode("hex"))
176         if 'num' not in ctx:
177             ctx['num'] = 0
178         ctx['num'] = ctx['num'] + 1
179         if 'id' not in ctx:
180             ctx['id'] = 1
181         ctx['id'] = (ctx['id'] + 1) % 256
182         idx = 0
183
184         idx += 1
185         if ctx['num'] == idx:
186             logger.info("Test: MD5 challenge")
187             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
188                                4 + 1 + 3,
189                                EAP_TYPE_MD5,
190                                1, 0xaa, ord('n'))
191         idx += 1
192         if ctx['num'] == idx:
193             logger.info("Test: EAP-Success - id off by 2")
194             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] + 1, 4)
195
196         idx += 1
197         if ctx['num'] == idx:
198             logger.info("Test: MD5 challenge")
199             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
200                                4 + 1 + 3,
201                                EAP_TYPE_MD5,
202                                1, 0xaa, ord('n'))
203         idx += 1
204         if ctx['num'] == idx:
205             logger.info("Test: EAP-Success - id off by 3")
206             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] + 2, 4)
207
208         idx += 1
209         if ctx['num'] == idx:
210             logger.info("Test: MD5 challenge")
211             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
212                                4 + 1 + 3,
213                                EAP_TYPE_MD5,
214                                1, 0xaa, ord('n'))
215         idx += 1
216         if ctx['num'] == idx:
217             logger.info("Test: EAP-Notification/Request")
218             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
219                                4 + 1 + 1,
220                                EAP_TYPE_NOTIFICATION,
221                                ord('A'))
222         idx += 1
223         if ctx['num'] == idx:
224             logger.info("Test: EAP-Success")
225             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
226
227         idx += 1
228         if ctx['num'] == idx:
229             logger.info("Test: EAP-Notification/Request")
230             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
231                                4 + 1 + 1,
232                                EAP_TYPE_NOTIFICATION,
233                                ord('B'))
234         idx += 1
235         if ctx['num'] == idx:
236             logger.info("Test: MD5 challenge")
237             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
238                                4 + 1 + 3,
239                                EAP_TYPE_MD5,
240                                1, 0xaa, ord('n'))
241         idx += 1
242         if ctx['num'] == idx:
243             logger.info("Test: EAP-Success")
244             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
245
246         idx += 1
247         if ctx['num'] == idx:
248             logger.info("Test: EAP-Notification/Request")
249             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
250                                4 + 1 + 1,
251                                EAP_TYPE_NOTIFICATION,
252                                ord('C'))
253         idx += 1
254         if ctx['num'] == idx:
255             logger.info("Test: MD5 challenge")
256             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
257                                4 + 1 + 3,
258                                EAP_TYPE_MD5,
259                                1, 0xaa, ord('n'))
260         idx += 1
261         if ctx['num'] == idx:
262             logger.info("Test: EAP-Notification/Request")
263             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
264                                4 + 1 + 1,
265                                EAP_TYPE_NOTIFICATION,
266                                ord('D'))
267         idx += 1
268         if ctx['num'] == idx:
269             logger.info("Test: EAP-Success")
270             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
271
272         idx += 1
273         if ctx['num'] == idx:
274             logger.info("Test: EAP-Notification/Request")
275             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
276                                4 + 1 + 1,
277                                EAP_TYPE_NOTIFICATION,
278                                ord('E'))
279         idx += 1
280         if ctx['num'] == idx:
281             logger.info("Test: EAP-Notification/Request (same id)")
282             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'] - 1,
283                                4 + 1 + 1,
284                                EAP_TYPE_NOTIFICATION,
285                                ord('F'))
286         idx += 1
287         if ctx['num'] == idx:
288             logger.info("Test: Unexpected EAP-Success")
289             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 2, 4)
290
291         return None
292
293     srv = start_radius_server(eap_handler)
294
295     try:
296         hapd = start_ap(apdev[0])
297
298         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
299                        eap="MD5", identity="user", password="password",
300                        wait_connect=False)
301         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
302         if ev is None:
303             raise Exception("Timeout on EAP start")
304         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
305         if ev is None:
306             raise Exception("Timeout on EAP success")
307         dev[0].request("REMOVE_NETWORK all")
308
309         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
310                        eap="MD5", identity="user", password="password",
311                        wait_connect=False)
312         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
313         if ev is None:
314             raise Exception("Timeout on EAP start")
315         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=1)
316         if ev is not None:
317             raise Exception("Unexpected EAP success")
318         dev[0].request("REMOVE_NETWORK all")
319
320         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
321                        eap="MD5", identity="user", password="password",
322                        wait_connect=False)
323         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
324         if ev is None:
325             raise Exception("Timeout on EAP start")
326         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
327         if ev is None:
328             raise Exception("Timeout on EAP notification")
329         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION A":
330             raise Exception("Unexpected notification contents: " + ev)
331         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
332         if ev is None:
333             raise Exception("Timeout on EAP success")
334         dev[0].request("REMOVE_NETWORK all")
335
336         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
337                        eap="MD5", identity="user", password="password",
338                        wait_connect=False)
339         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
340         if ev is None:
341             raise Exception("Timeout on EAP notification")
342         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION B":
343             raise Exception("Unexpected notification contents: " + ev)
344         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
345         if ev is None:
346             raise Exception("Timeout on EAP start")
347         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
348         if ev is None:
349             raise Exception("Timeout on EAP success")
350         dev[0].request("REMOVE_NETWORK all")
351
352         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
353                        eap="MD5", identity="user", password="password",
354                        wait_connect=False)
355         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
356         if ev is None:
357             raise Exception("Timeout on EAP notification")
358         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION C":
359             raise Exception("Unexpected notification contents: " + ev)
360         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
361         if ev is None:
362             raise Exception("Timeout on EAP start")
363         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
364         if ev is None:
365             raise Exception("Timeout on EAP notification")
366         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION D":
367             raise Exception("Unexpected notification contents: " + ev)
368         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
369         if ev is None:
370             raise Exception("Timeout on EAP success")
371         dev[0].request("REMOVE_NETWORK all")
372
373         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
374                        eap="MD5", identity="user", password="password",
375                        wait_connect=False)
376         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
377         if ev is None:
378             raise Exception("Timeout on EAP notification")
379         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION E":
380             raise Exception("Unexpected notification contents: " + ev)
381         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
382         if ev is None:
383             raise Exception("Timeout on EAP notification")
384         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION F":
385             raise Exception("Unexpected notification contents: " + ev)
386         ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=15)
387         if ev is None:
388             raise Exception("Timeout on EAP failure")
389         dev[0].request("REMOVE_NETWORK all")
390     finally:
391         stop_radius_server(srv)
392
393 def test_eap_proto_notification_errors(dev, apdev):
394     """EAP Notification errors"""
395     def eap_handler(ctx, req):
396         logger.info("eap_handler - RX " + req.encode("hex"))
397         if 'num' not in ctx:
398             ctx['num'] = 0
399         ctx['num'] = ctx['num'] + 1
400         if 'id' not in ctx:
401             ctx['id'] = 1
402         ctx['id'] = (ctx['id'] + 1) % 256
403         idx = 0
404
405         idx += 1
406         if ctx['num'] == idx:
407             logger.info("Test: MD5 challenge")
408             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
409                                4 + 1 + 3,
410                                EAP_TYPE_MD5,
411                                1, 0xaa, ord('n'))
412         idx += 1
413         if ctx['num'] == idx:
414             logger.info("Test: EAP-Notification/Request")
415             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
416                                4 + 1 + 1,
417                                EAP_TYPE_NOTIFICATION,
418                                ord('A'))
419
420         idx += 1
421         if ctx['num'] == idx:
422             logger.info("Test: MD5 challenge")
423             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
424                                4 + 1 + 3,
425                                EAP_TYPE_MD5,
426                                1, 0xaa, ord('n'))
427         idx += 1
428         if ctx['num'] == idx:
429             logger.info("Test: EAP-Notification/Request")
430             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
431                                4 + 1 + 1,
432                                EAP_TYPE_NOTIFICATION,
433                                ord('A'))
434
435         return None
436
437     srv = start_radius_server(eap_handler)
438
439     try:
440         hapd = start_ap(apdev[0])
441
442         with alloc_fail(dev[0], 1, "eap_sm_processNotify"):
443             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
444                            eap="MD5", identity="user", password="password",
445                            wait_connect=False)
446             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
447             dev[0].request("REMOVE_NETWORK all")
448             dev[0].wait_disconnected()
449
450         with alloc_fail(dev[0], 1, "eap_msg_alloc;sm_EAP_NOTIFICATION_Enter"):
451             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
452                            eap="MD5", identity="user", password="password",
453                            wait_connect=False)
454             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
455             dev[0].request("REMOVE_NETWORK all")
456             dev[0].wait_disconnected()
457     finally:
458         stop_radius_server(srv)
459
460 EAP_SAKE_VERSION = 2
461
462 EAP_SAKE_SUBTYPE_CHALLENGE = 1
463 EAP_SAKE_SUBTYPE_CONFIRM = 2
464 EAP_SAKE_SUBTYPE_AUTH_REJECT = 3
465 EAP_SAKE_SUBTYPE_IDENTITY = 4
466
467 EAP_SAKE_AT_RAND_S = 1
468 EAP_SAKE_AT_RAND_P = 2
469 EAP_SAKE_AT_MIC_S = 3
470 EAP_SAKE_AT_MIC_P = 4
471 EAP_SAKE_AT_SERVERID = 5
472 EAP_SAKE_AT_PEERID = 6
473 EAP_SAKE_AT_SPI_S = 7
474 EAP_SAKE_AT_SPI_P = 8
475 EAP_SAKE_AT_ANY_ID_REQ = 9
476 EAP_SAKE_AT_PERM_ID_REQ = 10
477 EAP_SAKE_AT_ENCR_DATA = 128
478 EAP_SAKE_AT_IV = 129
479 EAP_SAKE_AT_PADDING = 130
480 EAP_SAKE_AT_NEXT_TMPID = 131
481 EAP_SAKE_AT_MSK_LIFE = 132
482
483 def test_eap_proto_sake(dev, apdev):
484     """EAP-SAKE protocol tests"""
485     global eap_proto_sake_test_done
486     eap_proto_sake_test_done = False
487
488     def sake_challenge(ctx):
489         logger.info("Test: Challenge subtype")
490         return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
491                            4 + 1 + 3 + 18,
492                            EAP_TYPE_SAKE,
493                            EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
494                            EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
495
496     def sake_handler(ctx, req):
497         logger.info("sake_handler - RX " + req.encode("hex"))
498         if 'num' not in ctx:
499             ctx['num'] = 0
500         ctx['num'] += 1
501         if 'id' not in ctx:
502             ctx['id'] = 1
503         ctx['id'] = (ctx['id'] + 1) % 256
504         idx = 0
505
506         idx += 1
507         if ctx['num'] == idx:
508             logger.info("Test: Missing payload")
509             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
510                                EAP_TYPE_SAKE)
511
512         idx += 1
513         if ctx['num'] == idx:
514             logger.info("Test: Identity subtype without any attributes")
515             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
516                                4 + 1 + 3,
517                                EAP_TYPE_SAKE,
518                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY)
519
520         idx += 1
521         if ctx['num'] == idx:
522             logger.info("Test: Identity subtype")
523             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
524                                4 + 1 + 3 + 4,
525                                EAP_TYPE_SAKE,
526                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
527                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
528         idx += 1
529         if ctx['num'] == idx:
530             logger.info("Test: Identity subtype (different session id)")
531             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
532                                4 + 1 + 3 + 4,
533                                EAP_TYPE_SAKE,
534                                EAP_SAKE_VERSION, 1, EAP_SAKE_SUBTYPE_IDENTITY,
535                                EAP_SAKE_AT_PERM_ID_REQ, 4, 0)
536
537         idx += 1
538         if ctx['num'] == idx:
539             logger.info("Test: Identity subtype with too short attribute")
540             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
541                                4 + 1 + 3 + 2,
542                                EAP_TYPE_SAKE,
543                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
544                                EAP_SAKE_AT_ANY_ID_REQ, 2)
545
546         idx += 1
547         if ctx['num'] == idx:
548             logger.info("Test: Identity subtype with truncated attribute")
549             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
550                                4 + 1 + 3 + 2,
551                                EAP_TYPE_SAKE,
552                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
553                                EAP_SAKE_AT_ANY_ID_REQ, 4)
554
555         idx += 1
556         if ctx['num'] == idx:
557             logger.info("Test: Identity subtype with too short attribute header")
558             payload = struct.pack("B", EAP_SAKE_AT_ANY_ID_REQ)
559             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
560                                4 + 1 + 3 + len(payload),
561                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
562                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
563
564         idx += 1
565         if ctx['num'] == idx:
566             logger.info("Test: Identity subtype with AT_IV but not AT_ENCR_DATA")
567             payload = struct.pack("BB", EAP_SAKE_AT_IV, 2)
568             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
569                                4 + 1 + 3 + len(payload),
570                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
571                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
572
573         idx += 1
574         if ctx['num'] == idx:
575             logger.info("Test: Identity subtype with skippable and non-skippable unknown attribute")
576             payload = struct.pack("BBBB", 255, 2, 127, 2)
577             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
578                                4 + 1 + 3 + len(payload),
579                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
580                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
581
582         idx += 1
583         if ctx['num'] == idx:
584             logger.info("Test: Identity subtype: AT_RAND_P with invalid payload length")
585             payload = struct.pack("BB", EAP_SAKE_AT_RAND_P, 2)
586             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
587                                4 + 1 + 3 + len(payload),
588                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
589                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
590
591         idx += 1
592         if ctx['num'] == idx:
593             logger.info("Test: Identity subtype: AT_MIC_P with invalid payload length")
594             payload = struct.pack("BB", EAP_SAKE_AT_MIC_P, 2)
595             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
596                                4 + 1 + 3 + len(payload),
597                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
598                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
599
600         idx += 1
601         if ctx['num'] == idx:
602             logger.info("Test: Identity subtype: AT_PERM_ID_REQ with invalid payload length")
603             payload = struct.pack("BBBBBBBBBBBBBB",
604                                   EAP_SAKE_AT_SPI_S, 2,
605                                   EAP_SAKE_AT_SPI_P, 2,
606                                   EAP_SAKE_AT_ENCR_DATA, 2,
607                                   EAP_SAKE_AT_NEXT_TMPID, 2,
608                                   EAP_SAKE_AT_PERM_ID_REQ, 4, 0, 0,
609                                   EAP_SAKE_AT_PERM_ID_REQ, 2)
610             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
611                                4 + 1 + 3 + len(payload),
612                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
613                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
614
615         idx += 1
616         if ctx['num'] == idx:
617             logger.info("Test: Identity subtype: AT_PADDING")
618             payload = struct.pack("BBBBBB",
619                                   EAP_SAKE_AT_PADDING, 3, 0,
620                                   EAP_SAKE_AT_PADDING, 3, 1)
621             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
622                                4 + 1 + 3 + len(payload),
623                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
624                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
625
626         idx += 1
627         if ctx['num'] == idx:
628             logger.info("Test: Identity subtype: AT_MSK_LIFE")
629             payload = struct.pack(">BBLBBH",
630                                   EAP_SAKE_AT_MSK_LIFE, 6, 0,
631                                   EAP_SAKE_AT_MSK_LIFE, 4, 0)
632             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
633                                4 + 1 + 3 + len(payload),
634                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
635                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
636
637         idx += 1
638         if ctx['num'] == idx:
639             logger.info("Test: Identity subtype with invalid attribute length")
640             payload = struct.pack("BB", EAP_SAKE_AT_ANY_ID_REQ, 0)
641             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
642                                4 + 1 + 3 + len(payload),
643                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
644                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
645
646         idx += 1
647         if ctx['num'] == idx:
648             logger.info("Test: Unknown subtype")
649             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
650                                4 + 1 + 3,
651                                EAP_TYPE_SAKE,
652                                EAP_SAKE_VERSION, 0, 123)
653
654         idx += 1
655         if ctx['num'] == idx:
656             logger.info("Test: Challenge subtype without any attributes")
657             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
658                                4 + 1 + 3,
659                                EAP_TYPE_SAKE,
660                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE)
661
662         idx += 1
663         if ctx['num'] == idx:
664             logger.info("Test: Challenge subtype with too short AT_RAND_S")
665             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
666                                4 + 1 + 3 + 2,
667                                EAP_TYPE_SAKE,
668                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
669                                EAP_SAKE_AT_RAND_S, 2)
670
671         idx += 1
672         if ctx['num'] == idx:
673             return sake_challenge(ctx)
674         idx += 1
675         if ctx['num'] == idx:
676             logger.info("Test: Unexpected Identity subtype")
677             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
678                                4 + 1 + 3 + 4,
679                                EAP_TYPE_SAKE,
680                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
681                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
682
683         idx += 1
684         if ctx['num'] == idx:
685             return sake_challenge(ctx)
686         idx += 1
687         if ctx['num'] == idx:
688             logger.info("Test: Unexpected Challenge subtype")
689             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
690                                4 + 1 + 3 + 18,
691                                EAP_TYPE_SAKE,
692                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
693                                EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
694
695         idx += 1
696         if ctx['num'] == idx:
697             return sake_challenge(ctx)
698         idx += 1
699         if ctx['num'] == idx:
700             logger.info("Test: Confirm subtype without any attributes")
701             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
702                                4 + 1 + 3,
703                                EAP_TYPE_SAKE,
704                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM)
705
706         idx += 1
707         if ctx['num'] == idx:
708             return sake_challenge(ctx)
709         idx += 1
710         if ctx['num'] == idx:
711             logger.info("Test: Confirm subtype with too short AT_MIC_S")
712             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
713                                4 + 1 + 3 + 2,
714                                EAP_TYPE_SAKE,
715                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
716                                EAP_SAKE_AT_MIC_S, 2)
717
718         idx += 1
719         if ctx['num'] == idx:
720             logger.info("Test: Unexpected Confirm subtype")
721             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
722                                4 + 1 + 3 + 18,
723                                EAP_TYPE_SAKE,
724                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
725                                EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
726
727         idx += 1
728         if ctx['num'] == idx:
729             return sake_challenge(ctx)
730         idx += 1
731         if ctx['num'] == idx:
732             logger.info("Test: Confirm subtype with incorrect AT_MIC_S")
733             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
734                                4 + 1 + 3 + 18,
735                                EAP_TYPE_SAKE,
736                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
737                                EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
738
739         global eap_proto_sake_test_done
740         if eap_proto_sake_test_done:
741             return sake_challenge(ctx)
742
743         logger.info("No more test responses available - test case completed")
744         eap_proto_sake_test_done = True
745         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
746
747     srv = start_radius_server(sake_handler)
748
749     try:
750         hapd = start_ap(apdev[0])
751
752         while not eap_proto_sake_test_done:
753             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
754                            eap="SAKE", identity="sake user",
755                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
756                            wait_connect=False)
757             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
758             if ev is None:
759                 raise Exception("Timeout on EAP start")
760             time.sleep(0.1)
761             dev[0].request("REMOVE_NETWORK all")
762
763         logger.info("Too short password")
764         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
765                        eap="SAKE", identity="sake user",
766                        password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd",
767                        wait_connect=False)
768         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
769         if ev is None:
770             raise Exception("Timeout on EAP start")
771         time.sleep(0.1)
772     finally:
773         stop_radius_server(srv)
774
775 def test_eap_proto_sake_errors(dev, apdev):
776     """EAP-SAKE local error cases"""
777     check_eap_capa(dev[0], "SAKE")
778     params = hostapd.wpa2_eap_params(ssid="eap-test")
779     hapd = hostapd.add_ap(apdev[0], params)
780
781     for i in range(1, 3):
782         with alloc_fail(dev[0], i, "eap_sake_init"):
783             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
784                            eap="SAKE", identity="sake user",
785                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
786                            wait_connect=False)
787             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
788                                    timeout=15)
789             if ev is None:
790                 raise Exception("Timeout on EAP start")
791             dev[0].request("REMOVE_NETWORK all")
792             dev[0].wait_disconnected()
793
794     tests = [ ( 1, "eap_msg_alloc;eap_sake_build_msg;eap_sake_process_challenge" ),
795               ( 1, "=eap_sake_process_challenge" ),
796               ( 1, "eap_sake_compute_mic;eap_sake_process_challenge" ),
797               ( 1, "eap_sake_build_msg;eap_sake_process_confirm" ),
798               ( 1, "eap_sake_compute_mic;eap_sake_process_confirm" ),
799               ( 2, "eap_sake_compute_mic;eap_sake_process_confirm" ),
800               ( 1, "eap_sake_getKey" ),
801               ( 1, "eap_sake_get_emsk" ),
802               ( 1, "eap_sake_get_session_id" ) ]
803     for count, func in tests:
804         with alloc_fail(dev[0], count, func):
805             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
806                            eap="SAKE", identity="sake user",
807                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
808                            erp="1",
809                            wait_connect=False)
810             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
811                                    timeout=15)
812             if ev is None:
813                 raise Exception("Timeout on EAP start")
814             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
815             dev[0].request("REMOVE_NETWORK all")
816             dev[0].wait_disconnected()
817
818     with fail_test(dev[0], 1, "os_get_random;eap_sake_process_challenge"):
819         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
820                        eap="SAKE", identity="sake user",
821                        password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
822                        wait_connect=False)
823         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
824         if ev is None:
825             raise Exception("Timeout on EAP start")
826         wait_fail_trigger(dev[0], "GET_FAIL")
827         dev[0].request("REMOVE_NETWORK all")
828         dev[0].wait_disconnected()
829
830 def test_eap_proto_sake_errors2(dev, apdev):
831     """EAP-SAKE protocol tests (2)"""
832     def sake_handler(ctx, req):
833         logger.info("sake_handler - RX " + req.encode("hex"))
834         if 'num' not in ctx:
835             ctx['num'] = 0
836         ctx['num'] += 1
837         if 'id' not in ctx:
838             ctx['id'] = 1
839         ctx['id'] = (ctx['id'] + 1) % 256
840         idx = 0
841
842         idx += 1
843         if ctx['num'] == idx:
844             logger.info("Test: Identity subtype")
845             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
846                                4 + 1 + 3 + 4,
847                                EAP_TYPE_SAKE,
848                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
849                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
850
851     srv = start_radius_server(sake_handler)
852
853     try:
854         hapd = start_ap(apdev[0])
855
856         with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sake_build_msg;eap_sake_process_identity"):
857             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
858                            eap="SAKE", identity="sake user",
859                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
860                            wait_connect=False)
861             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
862                                    timeout=15)
863             if ev is None:
864                 raise Exception("Timeout on EAP start")
865                 dev[0].request("REMOVE_NETWORK all")
866                 dev[0].wait_disconnected()
867
868     finally:
869         stop_radius_server(srv)
870
871 def test_eap_proto_leap(dev, apdev):
872     """EAP-LEAP protocol tests"""
873     check_eap_capa(dev[0], "LEAP")
874     def leap_handler(ctx, req):
875         logger.info("leap_handler - RX " + req.encode("hex"))
876         if 'num' not in ctx:
877             ctx['num'] = 0
878         ctx['num'] = ctx['num'] + 1
879         if 'id' not in ctx:
880             ctx['id'] = 1
881         ctx['id'] = (ctx['id'] + 1) % 256
882
883         if ctx['num'] == 1:
884             logger.info("Test: Missing payload")
885             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
886                                4 + 1,
887                                EAP_TYPE_LEAP)
888
889         if ctx['num'] == 2:
890             logger.info("Test: Unexpected version")
891             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
892                                4 + 1 + 3,
893                                EAP_TYPE_LEAP,
894                                0, 0, 0)
895
896         if ctx['num'] == 3:
897             logger.info("Test: Invalid challenge length")
898             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
899                                4 + 1 + 3,
900                                EAP_TYPE_LEAP,
901                                1, 0, 0)
902
903         if ctx['num'] == 4:
904             logger.info("Test: Truncated challenge")
905             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
906                                4 + 1 + 3,
907                                EAP_TYPE_LEAP,
908                                1, 0, 8)
909
910         if ctx['num'] == 5:
911             logger.info("Test: Valid challenge")
912             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
913                                4 + 1 + 3 + 8,
914                                EAP_TYPE_LEAP,
915                                1, 0, 8, 0, 0)
916         if ctx['num'] == 6:
917             logger.info("Test: Missing payload in Response")
918             return struct.pack(">BBHB", EAP_CODE_RESPONSE, ctx['id'],
919                                4 + 1,
920                                EAP_TYPE_LEAP)
921
922         if ctx['num'] == 7:
923             logger.info("Test: Valid challenge")
924             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
925                                4 + 1 + 3 + 8,
926                                EAP_TYPE_LEAP,
927                                1, 0, 8, 0, 0)
928         if ctx['num'] == 8:
929             logger.info("Test: Unexpected version in Response")
930             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
931                                4 + 1 + 3,
932                                EAP_TYPE_LEAP,
933                                0, 0, 8)
934
935         if ctx['num'] == 9:
936             logger.info("Test: Valid challenge")
937             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
938                                4 + 1 + 3 + 8,
939                                EAP_TYPE_LEAP,
940                                1, 0, 8, 0, 0)
941         if ctx['num'] == 10:
942             logger.info("Test: Invalid challenge length in Response")
943             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
944                                4 + 1 + 3,
945                                EAP_TYPE_LEAP,
946                                1, 0, 0)
947
948         if ctx['num'] == 11:
949             logger.info("Test: Valid challenge")
950             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
951                                4 + 1 + 3 + 8,
952                                EAP_TYPE_LEAP,
953                                1, 0, 8, 0, 0)
954         if ctx['num'] == 12:
955             logger.info("Test: Truncated challenge in Response")
956             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
957                                4 + 1 + 3,
958                                EAP_TYPE_LEAP,
959                                1, 0, 24)
960
961         if ctx['num'] == 13:
962             logger.info("Test: Valid challenge")
963             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
964                                4 + 1 + 3 + 8,
965                                EAP_TYPE_LEAP,
966                                1, 0, 8, 0, 0)
967         if ctx['num'] == 14:
968             logger.info("Test: Invalid challange value in Response")
969             return struct.pack(">BBHBBBB6L", EAP_CODE_RESPONSE, ctx['id'],
970                                4 + 1 + 3 + 24,
971                                EAP_TYPE_LEAP,
972                                1, 0, 24,
973                                0, 0, 0, 0, 0, 0)
974
975         if ctx['num'] == 15:
976             logger.info("Test: Valid challenge")
977             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
978                                4 + 1 + 3 + 8,
979                                EAP_TYPE_LEAP,
980                                1, 0, 8, 0, 0)
981         if ctx['num'] == 16:
982             logger.info("Test: Valid challange value in Response")
983             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
984                                4 + 1 + 3 + 24,
985                                EAP_TYPE_LEAP,
986                                1, 0, 24,
987                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
988                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
989                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
990
991         if ctx['num'] == 17:
992             logger.info("Test: Valid challenge")
993             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
994                                4 + 1 + 3 + 8,
995                                EAP_TYPE_LEAP,
996                                1, 0, 8, 0, 0)
997         if ctx['num'] == 18:
998             logger.info("Test: Success")
999             return struct.pack(">BBHB", EAP_CODE_SUCCESS, ctx['id'],
1000                                4 + 1,
1001                                EAP_TYPE_LEAP)
1002         # hostapd will drop the next frame in the sequence
1003
1004         if ctx['num'] == 19:
1005             logger.info("Test: Valid challenge")
1006             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1007                                4 + 1 + 3 + 8,
1008                                EAP_TYPE_LEAP,
1009                                1, 0, 8, 0, 0)
1010         if ctx['num'] == 20:
1011             logger.info("Test: Failure")
1012             return struct.pack(">BBHB", EAP_CODE_FAILURE, ctx['id'],
1013                                4 + 1,
1014                                EAP_TYPE_LEAP)
1015
1016         return None
1017
1018     srv = start_radius_server(leap_handler)
1019
1020     try:
1021         hapd = start_ap(apdev[0])
1022
1023         for i in range(0, 12):
1024             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1025                            eap="LEAP", identity="user", password="password",
1026                            wait_connect=False)
1027             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
1028             if ev is None:
1029                 raise Exception("Timeout on EAP start")
1030             time.sleep(0.1)
1031             if i == 10:
1032                 logger.info("Wait for additional roundtrip")
1033                 time.sleep(1)
1034             dev[0].request("REMOVE_NETWORK all")
1035     finally:
1036         stop_radius_server(srv)
1037
1038 def test_eap_proto_leap_errors(dev, apdev):
1039     """EAP-LEAP protocol tests (error paths)"""
1040     check_eap_capa(dev[0], "LEAP")
1041
1042     def leap_handler2(ctx, req):
1043         logger.info("leap_handler2 - RX " + req.encode("hex"))
1044         if 'num' not in ctx:
1045             ctx['num'] = 0
1046         ctx['num'] = ctx['num'] + 1
1047         if 'id' not in ctx:
1048             ctx['id'] = 1
1049         ctx['id'] = (ctx['id'] + 1) % 256
1050         idx = 0
1051
1052         idx += 1
1053         if ctx['num'] == idx:
1054             logger.info("Test: Valid challenge")
1055             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1056                                4 + 1 + 3 + 8,
1057                                EAP_TYPE_LEAP,
1058                                1, 0, 8, 0, 0)
1059         idx += 1
1060         if ctx['num'] == idx:
1061             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1062
1063         idx += 1
1064         if ctx['num'] == idx:
1065             logger.info("Test: Valid challenge")
1066             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1067                                4 + 1 + 3 + 8,
1068                                EAP_TYPE_LEAP,
1069                                1, 0, 8, 0, 0)
1070
1071         idx += 1
1072         if ctx['num'] == idx:
1073             logger.info("Test: Valid challenge")
1074             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1075                                4 + 1 + 3 + 8,
1076                                EAP_TYPE_LEAP,
1077                                1, 0, 8, 0, 0)
1078         idx += 1
1079         if ctx['num'] == idx:
1080             logger.info("Test: Success")
1081             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
1082
1083         idx += 1
1084         if ctx['num'] == idx:
1085             logger.info("Test: Valid challenge")
1086             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1087                                4 + 1 + 3 + 8,
1088                                EAP_TYPE_LEAP,
1089                                1, 0, 8, 0, 0)
1090         idx += 1
1091         if ctx['num'] == idx:
1092             logger.info("Test: Success")
1093             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
1094
1095         idx += 1
1096         if ctx['num'] == idx:
1097             logger.info("Test: Valid challenge")
1098             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1099                                4 + 1 + 3 + 8,
1100                                EAP_TYPE_LEAP,
1101                                1, 0, 8, 0, 0)
1102         idx += 1
1103         if ctx['num'] == idx:
1104             logger.info("Test: Valid challange value in Response")
1105             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1106                                4 + 1 + 3 + 24,
1107                                EAP_TYPE_LEAP,
1108                                1, 0, 24,
1109                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1110                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1111                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1112
1113         idx += 1
1114         if ctx['num'] == idx:
1115             logger.info("Test: Valid challenge")
1116             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1117                                4 + 1 + 3 + 8,
1118                                EAP_TYPE_LEAP,
1119                                1, 0, 8, 0, 0)
1120         idx += 1
1121         if ctx['num'] == idx:
1122             logger.info("Test: Valid challange value in Response")
1123             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1124                                4 + 1 + 3 + 24,
1125                                EAP_TYPE_LEAP,
1126                                1, 0, 24,
1127                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1128                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1129                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1130
1131         idx += 1
1132         if ctx['num'] == idx:
1133             logger.info("Test: Valid challenge")
1134             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1135                                4 + 1 + 3 + 8,
1136                                EAP_TYPE_LEAP,
1137                                1, 0, 8, 0, 0)
1138         idx += 1
1139         if ctx['num'] == idx:
1140             logger.info("Test: Valid challange value in Response")
1141             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1142                                4 + 1 + 3 + 24,
1143                                EAP_TYPE_LEAP,
1144                                1, 0, 24,
1145                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1146                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1147                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1148
1149         idx += 1
1150         if ctx['num'] == idx:
1151             logger.info("Test: Valid challenge")
1152             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1153                                4 + 1 + 3 + 8,
1154                                EAP_TYPE_LEAP,
1155                                1, 0, 8, 0, 0)
1156         idx += 1
1157         if ctx['num'] == idx:
1158             logger.info("Test: Valid challange value in Response")
1159             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1160                                4 + 1 + 3 + 24,
1161                                EAP_TYPE_LEAP,
1162                                1, 0, 24,
1163                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1164                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1165                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1166
1167         idx += 1
1168         if ctx['num'] == idx:
1169             logger.info("Test: Valid challenge")
1170             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1171                                4 + 1 + 3 + 8,
1172                                EAP_TYPE_LEAP,
1173                                1, 0, 8, 0, 0)
1174         idx += 1
1175         if ctx['num'] == idx:
1176             logger.info("Test: Valid challange value in Response")
1177             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1178                                4 + 1 + 3 + 24,
1179                                EAP_TYPE_LEAP,
1180                                1, 0, 24,
1181                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1182                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1183                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1184
1185         idx += 1
1186         if ctx['num'] == idx:
1187             logger.info("Test: Valid challenge")
1188             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1189                                4 + 1 + 3 + 8,
1190                                EAP_TYPE_LEAP,
1191                                1, 0, 8, 0, 0)
1192         idx += 1
1193         if ctx['num'] == idx:
1194             logger.info("Test: Valid challange value in Response")
1195             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1196                                4 + 1 + 3 + 24,
1197                                EAP_TYPE_LEAP,
1198                                1, 0, 24,
1199                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1200                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1201                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1202
1203         idx += 1
1204         if ctx['num'] == idx:
1205             logger.info("Test: Valid challenge")
1206             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1207                                4 + 1 + 3 + 8,
1208                                EAP_TYPE_LEAP,
1209                                1, 0, 8, 0, 0)
1210         idx += 1
1211         if ctx['num'] == idx:
1212             logger.info("Test: Valid challange value in Response")
1213             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1214                                4 + 1 + 3 + 24,
1215                                EAP_TYPE_LEAP,
1216                                1, 0, 24,
1217                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1218                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1219                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1220
1221         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1222
1223     srv = start_radius_server(leap_handler2)
1224
1225     try:
1226         hapd = start_ap(apdev[0])
1227
1228         with alloc_fail(dev[0], 1, "eap_leap_init"):
1229             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1230                            eap="LEAP", identity="user", password="password",
1231                            wait_connect=False)
1232             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1233             dev[0].request("REMOVE_NETWORK all")
1234             dev[0].wait_disconnected()
1235
1236         with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_leap_process_request"):
1237             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1238                            eap="LEAP", identity="user",
1239                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1240                            wait_connect=False)
1241             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1242             dev[0].request("REMOVE_NETWORK all")
1243             dev[0].wait_disconnected()
1244
1245         with alloc_fail(dev[0], 1, "eap_leap_process_success"):
1246             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1247                            eap="LEAP", identity="user", password="password",
1248                            wait_connect=False)
1249             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1250             dev[0].request("REMOVE_NETWORK all")
1251             dev[0].wait_disconnected()
1252
1253         with fail_test(dev[0], 1, "os_get_random;eap_leap_process_success"):
1254             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1255                            eap="LEAP", identity="user", password="password",
1256                            wait_connect=False)
1257             wait_fail_trigger(dev[0], "GET_FAIL")
1258             dev[0].request("REMOVE_NETWORK all")
1259             dev[0].wait_disconnected()
1260
1261         with fail_test(dev[0], 1, "eap_leap_process_response"):
1262             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1263                            eap="LEAP", identity="user",
1264                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1265                            wait_connect=False)
1266             wait_fail_trigger(dev[0], "GET_FAIL")
1267             dev[0].request("REMOVE_NETWORK all")
1268             dev[0].wait_disconnected()
1269
1270         with fail_test(dev[0], 1, "nt_password_hash;eap_leap_process_response"):
1271             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1272                            eap="LEAP", identity="user", password="password",
1273                            wait_connect=False)
1274             wait_fail_trigger(dev[0], "GET_FAIL")
1275             dev[0].request("REMOVE_NETWORK all")
1276             dev[0].wait_disconnected()
1277
1278         with fail_test(dev[0], 1, "hash_nt_password_hash;eap_leap_process_response"):
1279             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1280                            eap="LEAP", identity="user", password="password",
1281                            wait_connect=False)
1282             wait_fail_trigger(dev[0], "GET_FAIL")
1283             dev[0].request("REMOVE_NETWORK all")
1284             dev[0].wait_disconnected()
1285
1286         with alloc_fail(dev[0], 1, "eap_leap_getKey"):
1287             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1288                            eap="LEAP", identity="user",
1289                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1290                            wait_connect=False)
1291             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1292             dev[0].request("REMOVE_NETWORK all")
1293             dev[0].wait_disconnected()
1294
1295         with fail_test(dev[0], 1, "eap_leap_getKey"):
1296             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1297                            eap="LEAP", identity="user",
1298                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1299                            wait_connect=False)
1300             wait_fail_trigger(dev[0], "GET_FAIL")
1301             dev[0].request("REMOVE_NETWORK all")
1302             dev[0].wait_disconnected()
1303
1304         with fail_test(dev[0], 1, "nt_password_hash;eap_leap_getKey"):
1305             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1306                            eap="LEAP", identity="user", password="password",
1307                            wait_connect=False)
1308             wait_fail_trigger(dev[0], "GET_FAIL")
1309             dev[0].request("REMOVE_NETWORK all")
1310             dev[0].wait_disconnected()
1311
1312         with fail_test(dev[0], 1, "hash_nt_password_hash;eap_leap_getKey"):
1313             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1314                            eap="LEAP", identity="user", password="password",
1315                            wait_connect=False)
1316             wait_fail_trigger(dev[0], "GET_FAIL")
1317             dev[0].request("REMOVE_NETWORK all")
1318             dev[0].wait_disconnected()
1319     finally:
1320         stop_radius_server(srv)
1321
1322 def test_eap_proto_md5(dev, apdev):
1323     """EAP-MD5 protocol tests"""
1324     check_eap_capa(dev[0], "MD5")
1325
1326     def md5_handler(ctx, req):
1327         logger.info("md5_handler - RX " + req.encode("hex"))
1328         if 'num' not in ctx:
1329             ctx['num'] = 0
1330         ctx['num'] = ctx['num'] + 1
1331         if 'id' not in ctx:
1332             ctx['id'] = 1
1333         ctx['id'] = (ctx['id'] + 1) % 256
1334
1335         if ctx['num'] == 1:
1336             logger.info("Test: Missing payload")
1337             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1338                                4 + 1,
1339                                EAP_TYPE_MD5)
1340
1341         if ctx['num'] == 2:
1342             logger.info("Test: Zero-length challenge")
1343             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1344                                4 + 1 + 1,
1345                                EAP_TYPE_MD5,
1346                                0)
1347
1348         if ctx['num'] == 3:
1349             logger.info("Test: Truncated challenge")
1350             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1351                                4 + 1 + 1,
1352                                EAP_TYPE_MD5,
1353                                1)
1354
1355         if ctx['num'] == 4:
1356             logger.info("Test: Shortest possible challenge and name")
1357             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
1358                                4 + 1 + 3,
1359                                EAP_TYPE_MD5,
1360                                1, 0xaa, ord('n'))
1361
1362         return None
1363
1364     srv = start_radius_server(md5_handler)
1365
1366     try:
1367         hapd = start_ap(apdev[0])
1368
1369         for i in range(0, 4):
1370             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1371                            eap="MD5", identity="user", password="password",
1372                            wait_connect=False)
1373             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
1374             if ev is None:
1375                 raise Exception("Timeout on EAP start")
1376             time.sleep(0.1)
1377             dev[0].request("REMOVE_NETWORK all")
1378     finally:
1379         stop_radius_server(srv)
1380
1381 def test_eap_proto_md5_errors(dev, apdev):
1382     """EAP-MD5 local error cases"""
1383     check_eap_capa(dev[0], "MD5")
1384     params = hostapd.wpa2_eap_params(ssid="eap-test")
1385     hapd = hostapd.add_ap(apdev[0], params)
1386
1387     with fail_test(dev[0], 1, "chap_md5"):
1388         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1389                        eap="MD5", identity="phase1-user", password="password",
1390                        wait_connect=False)
1391         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
1392         if ev is None:
1393             raise Exception("Timeout on EAP start")
1394         dev[0].request("REMOVE_NETWORK all")
1395         dev[0].wait_disconnected()
1396
1397     with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_md5_process"):
1398         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1399                        eap="MD5", identity="phase1-user", password="password",
1400                        wait_connect=False)
1401         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
1402         if ev is None:
1403             raise Exception("Timeout on EAP start")
1404         time.sleep(0.1)
1405         dev[0].request("REMOVE_NETWORK all")
1406
1407 def test_eap_proto_otp(dev, apdev):
1408     """EAP-OTP protocol tests"""
1409     def otp_handler(ctx, req):
1410         logger.info("otp_handler - RX " + req.encode("hex"))
1411         if 'num' not in ctx:
1412             ctx['num'] = 0
1413         ctx['num'] = ctx['num'] + 1
1414         if 'id' not in ctx:
1415             ctx['id'] = 1
1416         ctx['id'] = (ctx['id'] + 1) % 256
1417
1418         if ctx['num'] == 1:
1419             logger.info("Test: Empty payload")
1420             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1421                                4 + 1,
1422                                EAP_TYPE_OTP)
1423         if ctx['num'] == 2:
1424             logger.info("Test: Success")
1425             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
1426                                4)
1427
1428         if ctx['num'] == 3:
1429             logger.info("Test: Challenge included")
1430             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1431                                4 + 1 + 1,
1432                                EAP_TYPE_OTP,
1433                                ord('A'))
1434         if ctx['num'] == 4:
1435             logger.info("Test: Success")
1436             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
1437                                4)
1438
1439         return None
1440
1441     srv = start_radius_server(otp_handler)
1442
1443     try:
1444         hapd = start_ap(apdev[0])
1445
1446         for i in range(0, 1):
1447             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1448                            eap="OTP", identity="user", password="password",
1449                            wait_connect=False)
1450             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
1451                                    timeout=15)
1452             if ev is None:
1453                 raise Exception("Timeout on EAP start")
1454             time.sleep(0.1)
1455             dev[0].request("REMOVE_NETWORK all")
1456
1457         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1458                        eap="OTP", identity="user", wait_connect=False)
1459         ev = dev[0].wait_event(["CTRL-REQ-OTP"])
1460         if ev is None:
1461             raise Exception("Request for password timed out")
1462         id = ev.split(':')[0].split('-')[-1]
1463         dev[0].request("CTRL-RSP-OTP-" + id + ":password")
1464         ev = dev[0].wait_event("CTRL-EVENT-EAP-SUCCESS")
1465         if ev is None:
1466             raise Exception("Success not reported")
1467     finally:
1468         stop_radius_server(srv)
1469
1470 def test_eap_proto_otp_errors(dev, apdev):
1471     """EAP-OTP local error cases"""
1472     def otp_handler2(ctx, req):
1473         logger.info("otp_handler2 - RX " + req.encode("hex"))
1474         if 'num' not in ctx:
1475             ctx['num'] = 0
1476         ctx['num'] = ctx['num'] + 1
1477         if 'id' not in ctx:
1478             ctx['id'] = 1
1479         ctx['id'] = (ctx['id'] + 1) % 256
1480         idx = 0
1481
1482         idx += 1
1483         if ctx['num'] == idx:
1484             logger.info("Test: Challenge included")
1485             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1486                                4 + 1 + 1,
1487                                EAP_TYPE_OTP,
1488                                ord('A'))
1489
1490         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1491
1492     srv = start_radius_server(otp_handler2)
1493
1494     try:
1495         hapd = start_ap(apdev[0])
1496
1497         with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_otp_process"):
1498             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1499                            eap="OTP", identity="user", password="password",
1500                            wait_connect=False)
1501             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1502             dev[0].request("REMOVE_NETWORK all")
1503             dev[0].wait_disconnected()
1504     finally:
1505         stop_radius_server(srv)
1506
1507 EAP_GPSK_OPCODE_GPSK_1 = 1
1508 EAP_GPSK_OPCODE_GPSK_2 = 2
1509 EAP_GPSK_OPCODE_GPSK_3 = 3
1510 EAP_GPSK_OPCODE_GPSK_4 = 4
1511 EAP_GPSK_OPCODE_FAIL = 5
1512 EAP_GPSK_OPCODE_PROTECTED_FAIL = 6
1513
1514 def test_eap_proto_gpsk(dev, apdev):
1515     """EAP-GPSK protocol tests"""
1516     def gpsk_handler(ctx, req):
1517         logger.info("gpsk_handler - RX " + req.encode("hex"))
1518         if 'num' not in ctx:
1519             ctx['num'] = 0
1520         ctx['num'] = ctx['num'] + 1
1521         if 'id' not in ctx:
1522             ctx['id'] = 1
1523         ctx['id'] = (ctx['id'] + 1) % 256
1524
1525         idx = 0
1526
1527         idx += 1
1528         if ctx['num'] == idx:
1529             logger.info("Test: Missing payload")
1530             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1531                                4 + 1,
1532                                EAP_TYPE_GPSK)
1533
1534         idx += 1
1535         if ctx['num'] == idx:
1536             logger.info("Test: Unknown opcode")
1537             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1538                                4 + 1 + 1,
1539                                EAP_TYPE_GPSK,
1540                                255)
1541
1542         idx += 1
1543         if ctx['num'] == idx:
1544             logger.info("Test: Unexpected GPSK-3")
1545             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1546                                4 + 1 + 1,
1547                                EAP_TYPE_GPSK,
1548                                EAP_GPSK_OPCODE_GPSK_3)
1549
1550         idx += 1
1551         if ctx['num'] == idx:
1552             logger.info("Test: GPSK-1 Too short GPSK-1")
1553             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1554                                4 + 1 + 1,
1555                                EAP_TYPE_GPSK,
1556                                EAP_GPSK_OPCODE_GPSK_1)
1557
1558         idx += 1
1559         if ctx['num'] == idx:
1560             logger.info("Test: GPSK-1 Truncated ID_Server")
1561             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
1562                                4 + 1 + 1 + 2,
1563                                EAP_TYPE_GPSK,
1564                                EAP_GPSK_OPCODE_GPSK_1, 1)
1565
1566         idx += 1
1567         if ctx['num'] == idx:
1568             logger.info("Test: GPSK-1 Missing RAND_Server")
1569             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
1570                                4 + 1 + 1 + 2,
1571                                EAP_TYPE_GPSK,
1572                                EAP_GPSK_OPCODE_GPSK_1, 0)
1573
1574         idx += 1
1575         if ctx['num'] == idx:
1576             logger.info("Test: GPSK-1 Missing CSuite_List")
1577             return struct.pack(">BBHBBH8L", EAP_CODE_REQUEST, ctx['id'],
1578                                4 + 1 + 1 + 2 + 32,
1579                                EAP_TYPE_GPSK,
1580                                EAP_GPSK_OPCODE_GPSK_1, 0,
1581                                0, 0, 0, 0, 0, 0, 0, 0)
1582
1583         idx += 1
1584         if ctx['num'] == idx:
1585             logger.info("Test: GPSK-1 Truncated CSuite_List")
1586             return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
1587                                4 + 1 + 1 + 2 + 32 + 2,
1588                                EAP_TYPE_GPSK,
1589                                EAP_GPSK_OPCODE_GPSK_1, 0,
1590                                0, 0, 0, 0, 0, 0, 0, 0,
1591                                1)
1592
1593         idx += 1
1594         if ctx['num'] == idx:
1595             logger.info("Test: GPSK-1 Empty CSuite_List")
1596             return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
1597                                4 + 1 + 1 + 2 + 32 + 2,
1598                                EAP_TYPE_GPSK,
1599                                EAP_GPSK_OPCODE_GPSK_1, 0,
1600                                0, 0, 0, 0, 0, 0, 0, 0,
1601                                0)
1602
1603         idx += 1
1604         if ctx['num'] == idx:
1605             logger.info("Test: GPSK-1 Invalid CSuite_List")
1606             return struct.pack(">BBHBBH8LHB", EAP_CODE_REQUEST, ctx['id'],
1607                                4 + 1 + 1 + 2 + 32 + 2 + 1,
1608                                EAP_TYPE_GPSK,
1609                                EAP_GPSK_OPCODE_GPSK_1, 0,
1610                                0, 0, 0, 0, 0, 0, 0, 0,
1611                                1, 0)
1612
1613         idx += 1
1614         if ctx['num'] == idx:
1615             logger.info("Test: GPSK-1 No supported CSuite")
1616             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1617                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1618                                EAP_TYPE_GPSK,
1619                                EAP_GPSK_OPCODE_GPSK_1, 0,
1620                                0, 0, 0, 0, 0, 0, 0, 0,
1621                                6, 0, 0)
1622
1623         idx += 1
1624         if ctx['num'] == idx:
1625             logger.info("Test: GPSK-1 Supported CSuite")
1626             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1627                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1628                                EAP_TYPE_GPSK,
1629                                EAP_GPSK_OPCODE_GPSK_1, 0,
1630                                0, 0, 0, 0, 0, 0, 0, 0,
1631                                6, 0, 1)
1632         idx += 1
1633         if ctx['num'] == idx:
1634             logger.info("Test: Unexpected GPSK-1")
1635             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1636                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1637                                EAP_TYPE_GPSK,
1638                                EAP_GPSK_OPCODE_GPSK_1, 0,
1639                                0, 0, 0, 0, 0, 0, 0, 0,
1640                                6, 0, 1)
1641
1642         idx += 1
1643         if ctx['num'] == idx:
1644             logger.info("Test: GPSK-1 Supported CSuite but too short key")
1645             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1646                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1647                                EAP_TYPE_GPSK,
1648                                EAP_GPSK_OPCODE_GPSK_1, 0,
1649                                0, 0, 0, 0, 0, 0, 0, 0,
1650                                6, 0, 1)
1651
1652         idx += 1
1653         if ctx['num'] == idx:
1654             logger.info("Test: GPSK-1 Supported CSuite")
1655             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1656                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1657                                EAP_TYPE_GPSK,
1658                                EAP_GPSK_OPCODE_GPSK_1, 0,
1659                                0, 0, 0, 0, 0, 0, 0, 0,
1660                                6, 0, 1)
1661         idx += 1
1662         if ctx['num'] == idx:
1663             logger.info("Test: Too short GPSK-3")
1664             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1665                                4 + 1 + 1,
1666                                EAP_TYPE_GPSK,
1667                                EAP_GPSK_OPCODE_GPSK_3)
1668
1669         idx += 1
1670         if ctx['num'] == idx:
1671             logger.info("Test: GPSK-1 Supported CSuite")
1672             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1673                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1674                                EAP_TYPE_GPSK,
1675                                EAP_GPSK_OPCODE_GPSK_1, 0,
1676                                0, 0, 0, 0, 0, 0, 0, 0,
1677                                6, 0, 1)
1678         idx += 1
1679         if ctx['num'] == idx:
1680             logger.info("Test: GPSK-3 Mismatch in RAND_Peer")
1681             return struct.pack(">BBHBB8L", EAP_CODE_REQUEST, ctx['id'],
1682                                4 + 1 + 1 + 32,
1683                                EAP_TYPE_GPSK,
1684                                EAP_GPSK_OPCODE_GPSK_3,
1685                                0, 0, 0, 0, 0, 0, 0, 0)
1686
1687         idx += 1
1688         if ctx['num'] == idx:
1689             logger.info("Test: GPSK-1 Supported CSuite")
1690             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1691                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1692                                EAP_TYPE_GPSK,
1693                                EAP_GPSK_OPCODE_GPSK_1, 0,
1694                                0, 0, 0, 0, 0, 0, 0, 0,
1695                                6, 0, 1)
1696         idx += 1
1697         if ctx['num'] == idx:
1698             logger.info("Test: GPSK-3 Missing RAND_Server")
1699             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1700                               4 + 1 + 1 + 32,
1701                               EAP_TYPE_GPSK,
1702                               EAP_GPSK_OPCODE_GPSK_3)
1703             msg += req[14:46]
1704             return msg
1705
1706         idx += 1
1707         if ctx['num'] == idx:
1708             logger.info("Test: GPSK-1 Supported CSuite")
1709             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1710                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1711                                EAP_TYPE_GPSK,
1712                                EAP_GPSK_OPCODE_GPSK_1, 0,
1713                                0, 0, 0, 0, 0, 0, 0, 0,
1714                                6, 0, 1)
1715         idx += 1
1716         if ctx['num'] == idx:
1717             logger.info("Test: GPSK-3 Mismatch in RAND_Server")
1718             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1719                               4 + 1 + 1 + 32 + 32,
1720                               EAP_TYPE_GPSK,
1721                               EAP_GPSK_OPCODE_GPSK_3)
1722             msg += req[14:46]
1723             msg += struct.pack(">8L", 1, 1, 1, 1, 1, 1, 1, 1)
1724             return msg
1725
1726         idx += 1
1727         if ctx['num'] == idx:
1728             logger.info("Test: GPSK-1 Supported CSuite")
1729             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1730                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1731                                EAP_TYPE_GPSK,
1732                                EAP_GPSK_OPCODE_GPSK_1, 0,
1733                                0, 0, 0, 0, 0, 0, 0, 0,
1734                                6, 0, 1)
1735         idx += 1
1736         if ctx['num'] == idx:
1737             logger.info("Test: GPSK-3 Missing ID_Server")
1738             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1739                               4 + 1 + 1 + 32 + 32,
1740                               EAP_TYPE_GPSK,
1741                               EAP_GPSK_OPCODE_GPSK_3)
1742             msg += req[14:46]
1743             msg += struct.pack(">8L", 0, 0, 0, 0, 0, 0, 0, 0)
1744             return msg
1745
1746         idx += 1
1747         if ctx['num'] == idx:
1748             logger.info("Test: GPSK-1 Supported CSuite")
1749             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1750                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1751                                EAP_TYPE_GPSK,
1752                                EAP_GPSK_OPCODE_GPSK_1, 0,
1753                                0, 0, 0, 0, 0, 0, 0, 0,
1754                                6, 0, 1)
1755         idx += 1
1756         if ctx['num'] == idx:
1757             logger.info("Test: GPSK-3 Truncated ID_Server")
1758             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1759                               4 + 1 + 1 + 32 + 32 + 2,
1760                               EAP_TYPE_GPSK,
1761                               EAP_GPSK_OPCODE_GPSK_3)
1762             msg += req[14:46]
1763             msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 1)
1764             return msg
1765
1766         idx += 1
1767         if ctx['num'] == idx:
1768             logger.info("Test: GPSK-1 Supported CSuite")
1769             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1770                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1771                                EAP_TYPE_GPSK,
1772                                EAP_GPSK_OPCODE_GPSK_1, 0,
1773                                0, 0, 0, 0, 0, 0, 0, 0,
1774                                6, 0, 1)
1775         idx += 1
1776         if ctx['num'] == idx:
1777             logger.info("Test: GPSK-3 Mismatch in ID_Server")
1778             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1779                               4 + 1 + 1 + 32 + 32 + 3,
1780                               EAP_TYPE_GPSK,
1781                               EAP_GPSK_OPCODE_GPSK_3)
1782             msg += req[14:46]
1783             msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
1784             return msg
1785
1786         idx += 1
1787         if ctx['num'] == idx:
1788             logger.info("Test: GPSK-1 Supported CSuite")
1789             return struct.pack(">BBHBBHB8LHLH", EAP_CODE_REQUEST, ctx['id'],
1790                                4 + 1 + 1 + 3 + 32 + 2 + 6,
1791                                EAP_TYPE_GPSK,
1792                                EAP_GPSK_OPCODE_GPSK_1, 1, ord('A'),
1793                                0, 0, 0, 0, 0, 0, 0, 0,
1794                                6, 0, 1)
1795         idx += 1
1796         if ctx['num'] == idx:
1797             logger.info("Test: GPSK-3 Mismatch in ID_Server (same length)")
1798             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1799                               4 + 1 + 1 + 32 + 32 + 3,
1800                               EAP_TYPE_GPSK,
1801                               EAP_GPSK_OPCODE_GPSK_3)
1802             msg += req[15:47]
1803             msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
1804             return msg
1805
1806         idx += 1
1807         if ctx['num'] == idx:
1808             logger.info("Test: GPSK-1 Supported CSuite")
1809             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1810                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1811                                EAP_TYPE_GPSK,
1812                                EAP_GPSK_OPCODE_GPSK_1, 0,
1813                                0, 0, 0, 0, 0, 0, 0, 0,
1814                                6, 0, 1)
1815         idx += 1
1816         if ctx['num'] == idx:
1817             logger.info("Test: GPSK-3 Missing CSuite_Sel")
1818             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1819                               4 + 1 + 1 + 32 + 32 + 2,
1820                               EAP_TYPE_GPSK,
1821                               EAP_GPSK_OPCODE_GPSK_3)
1822             msg += req[14:46]
1823             msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 0)
1824             return msg
1825
1826         idx += 1
1827         if ctx['num'] == idx:
1828             logger.info("Test: GPSK-1 Supported CSuite")
1829             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1830                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1831                                EAP_TYPE_GPSK,
1832                                EAP_GPSK_OPCODE_GPSK_1, 0,
1833                                0, 0, 0, 0, 0, 0, 0, 0,
1834                                6, 0, 1)
1835         idx += 1
1836         if ctx['num'] == idx:
1837             logger.info("Test: GPSK-3 Mismatch in CSuite_Sel")
1838             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1839                               4 + 1 + 1 + 32 + 32 + 2 + 6,
1840                               EAP_TYPE_GPSK,
1841                               EAP_GPSK_OPCODE_GPSK_3)
1842             msg += req[14:46]
1843             msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2)
1844             return msg
1845
1846         idx += 1
1847         if ctx['num'] == idx:
1848             logger.info("Test: GPSK-1 Supported CSuite")
1849             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1850                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1851                                EAP_TYPE_GPSK,
1852                                EAP_GPSK_OPCODE_GPSK_1, 0,
1853                                0, 0, 0, 0, 0, 0, 0, 0,
1854                                6, 0, 1)
1855         idx += 1
1856         if ctx['num'] == idx:
1857             logger.info("Test: GPSK-3 Missing len(PD_Payload_Block)")
1858             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1859                               4 + 1 + 1 + 32 + 32 + 2 + 6,
1860                               EAP_TYPE_GPSK,
1861                               EAP_GPSK_OPCODE_GPSK_3)
1862             msg += req[14:46]
1863             msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
1864             return msg
1865
1866         idx += 1
1867         if ctx['num'] == idx:
1868             logger.info("Test: GPSK-1 Supported CSuite")
1869             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1870                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1871                                EAP_TYPE_GPSK,
1872                                EAP_GPSK_OPCODE_GPSK_1, 0,
1873                                0, 0, 0, 0, 0, 0, 0, 0,
1874                                6, 0, 1)
1875         idx += 1
1876         if ctx['num'] == idx:
1877             logger.info("Test: GPSK-3 Truncated PD_Payload_Block")
1878             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1879                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 2,
1880                               EAP_TYPE_GPSK,
1881                               EAP_GPSK_OPCODE_GPSK_3)
1882             msg += req[14:46]
1883             msg += struct.pack(">8LHLHH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
1884             return msg
1885
1886         idx += 1
1887         if ctx['num'] == idx:
1888             logger.info("Test: GPSK-1 Supported CSuite")
1889             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1890                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1891                                EAP_TYPE_GPSK,
1892                                EAP_GPSK_OPCODE_GPSK_1, 0,
1893                                0, 0, 0, 0, 0, 0, 0, 0,
1894                                6, 0, 1)
1895         idx += 1
1896         if ctx['num'] == idx:
1897             logger.info("Test: GPSK-3 Missing MAC")
1898             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1899                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 3,
1900                               EAP_TYPE_GPSK,
1901                               EAP_GPSK_OPCODE_GPSK_3)
1902             msg += req[14:46]
1903             msg += struct.pack(">8LHLHHB",
1904                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123)
1905             return msg
1906
1907         idx += 1
1908         if ctx['num'] == idx:
1909             logger.info("Test: GPSK-1 Supported CSuite")
1910             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1911                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1912                                EAP_TYPE_GPSK,
1913                                EAP_GPSK_OPCODE_GPSK_1, 0,
1914                                0, 0, 0, 0, 0, 0, 0, 0,
1915                                6, 0, 1)
1916         idx += 1
1917         if ctx['num'] == idx:
1918             logger.info("Test: GPSK-3 Incorrect MAC")
1919             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1920                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 3 + 16,
1921                               EAP_TYPE_GPSK,
1922                               EAP_GPSK_OPCODE_GPSK_3)
1923             msg += req[14:46]
1924             msg += struct.pack(">8LHLHHB4L",
1925                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123,
1926                                0, 0, 0, 0)
1927             return msg
1928
1929         return None
1930
1931     srv = start_radius_server(gpsk_handler)
1932
1933     try:
1934         hapd = start_ap(apdev[0])
1935
1936         for i in range(0, 27):
1937             if i == 12:
1938                 pw = "short"
1939             else:
1940                 pw = "abcdefghijklmnop0123456789abcdef"
1941             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1942                            eap="GPSK", identity="user", password=pw,
1943                            wait_connect=False)
1944             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
1945                                    timeout=15)
1946             if ev is None:
1947                 raise Exception("Timeout on EAP start")
1948             time.sleep(0.05)
1949             dev[0].request("REMOVE_NETWORK all")
1950     finally:
1951         stop_radius_server(srv)
1952
1953 EAP_EKE_ID = 1
1954 EAP_EKE_COMMIT = 2
1955 EAP_EKE_CONFIRM = 3
1956 EAP_EKE_FAILURE = 4
1957
1958 def test_eap_proto_eke(dev, apdev):
1959     """EAP-EKE protocol tests"""
1960     def eke_handler(ctx, req):
1961         logger.info("eke_handler - RX " + req.encode("hex"))
1962         if 'num' not in ctx:
1963             ctx['num'] = 0
1964         ctx['num'] = ctx['num'] + 1
1965         if 'id' not in ctx:
1966             ctx['id'] = 1
1967         ctx['id'] = (ctx['id'] + 1) % 256
1968
1969         idx = 0
1970
1971         idx += 1
1972         if ctx['num'] == idx:
1973             logger.info("Test: Missing payload")
1974             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1975                                4 + 1,
1976                                EAP_TYPE_EKE)
1977
1978         idx += 1
1979         if ctx['num'] == idx:
1980             logger.info("Test: Unknown exchange")
1981             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1982                                4 + 1 + 1,
1983                                EAP_TYPE_EKE,
1984                                255)
1985
1986         idx += 1
1987         if ctx['num'] == idx:
1988             logger.info("Test: No NumProposals in EAP-EKE-ID/Request")
1989             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1990                                4 + 1 + 1,
1991                                EAP_TYPE_EKE,
1992                                EAP_EKE_ID)
1993         idx += 1
1994         if ctx['num'] == idx:
1995             logger.info("Test: EAP-Failure")
1996             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1997
1998         idx += 1
1999         if ctx['num'] == idx:
2000             logger.info("Test: NumProposals=0 in EAP-EKE-ID/Request")
2001             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
2002                                4 + 1 + 1 + 1,
2003                                EAP_TYPE_EKE,
2004                                EAP_EKE_ID,
2005                                0)
2006         idx += 1
2007         if ctx['num'] == idx:
2008             logger.info("Test: EAP-Failure")
2009             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2010
2011         idx += 1
2012         if ctx['num'] == idx:
2013             logger.info("Test: Truncated Proposals list in EAP-EKE-ID/Request")
2014             return struct.pack(">BBHBBBB4B", EAP_CODE_REQUEST, ctx['id'],
2015                                4 + 1 + 1 + 2 + 4,
2016                                EAP_TYPE_EKE,
2017                                EAP_EKE_ID,
2018                                2, 0, 0, 0, 0, 0)
2019         idx += 1
2020         if ctx['num'] == idx:
2021             logger.info("Test: EAP-Failure")
2022             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2023
2024         idx += 1
2025         if ctx['num'] == idx:
2026             logger.info("Test: Unsupported proposals in EAP-EKE-ID/Request")
2027             return struct.pack(">BBHBBBB4B4B4B4B", EAP_CODE_REQUEST, ctx['id'],
2028                                4 + 1 + 1 + 2 + 4 * 4,
2029                                EAP_TYPE_EKE,
2030                                EAP_EKE_ID,
2031                                4, 0,
2032                                0, 0, 0, 0,
2033                                3, 0, 0, 0,
2034                                3, 1, 0, 0,
2035                                3, 1, 1, 0)
2036         idx += 1
2037         if ctx['num'] == idx:
2038             logger.info("Test: EAP-Failure")
2039             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2040
2041         idx += 1
2042         if ctx['num'] == idx:
2043             logger.info("Test: Missing IDType/Identity in EAP-EKE-ID/Request")
2044             return struct.pack(">BBHBBBB4B4B4B4B4B",
2045                                EAP_CODE_REQUEST, ctx['id'],
2046                                4 + 1 + 1 + 2 + 5 * 4,
2047                                EAP_TYPE_EKE,
2048                                EAP_EKE_ID,
2049                                5, 0,
2050                                0, 0, 0, 0,
2051                                3, 0, 0, 0,
2052                                3, 1, 0, 0,
2053                                3, 1, 1, 0,
2054                                3, 1, 1, 1)
2055         idx += 1
2056         if ctx['num'] == idx:
2057             logger.info("Test: EAP-Failure")
2058             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2059
2060         idx += 1
2061         if ctx['num'] == idx:
2062             logger.info("Test: Valid EAP-EKE-ID/Request")
2063             return struct.pack(">BBHBBBB4BB",
2064                                EAP_CODE_REQUEST, ctx['id'],
2065                                4 + 1 + 1 + 2 + 4 + 1,
2066                                EAP_TYPE_EKE,
2067                                EAP_EKE_ID,
2068                                1, 0,
2069                                3, 1, 1, 1,
2070                                255)
2071         idx += 1
2072         if ctx['num'] == idx:
2073             logger.info("Test: Unexpected EAP-EKE-ID/Request")
2074             return struct.pack(">BBHBBBB4BB",
2075                                EAP_CODE_REQUEST, ctx['id'],
2076                                4 + 1 + 1 + 2 + 4 + 1,
2077                                EAP_TYPE_EKE,
2078                                EAP_EKE_ID,
2079                                1, 0,
2080                                3, 1, 1, 1,
2081                                255)
2082         idx += 1
2083         if ctx['num'] == idx:
2084             logger.info("Test: EAP-Failure")
2085             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2086
2087         idx += 1
2088         if ctx['num'] == idx:
2089             logger.info("Test: Valid EAP-EKE-ID/Request")
2090             return struct.pack(">BBHBBBB4BB",
2091                                EAP_CODE_REQUEST, ctx['id'],
2092                                4 + 1 + 1 + 2 + 4 + 1,
2093                                EAP_TYPE_EKE,
2094                                EAP_EKE_ID,
2095                                1, 0,
2096                                3, 1, 1, 1,
2097                                255)
2098         idx += 1
2099         if ctx['num'] == idx:
2100             logger.info("Test: Unexpected EAP-EKE-Confirm/Request")
2101             return struct.pack(">BBHBB",
2102                                EAP_CODE_REQUEST, ctx['id'],
2103                                4 + 1 + 1,
2104                                EAP_TYPE_EKE,
2105                                EAP_EKE_CONFIRM)
2106         idx += 1
2107         if ctx['num'] == idx:
2108             logger.info("Test: EAP-Failure")
2109             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2110
2111         idx += 1
2112         if ctx['num'] == idx:
2113             logger.info("Test: Too short EAP-EKE-Failure/Request")
2114             return struct.pack(">BBHBB",
2115                                EAP_CODE_REQUEST, ctx['id'],
2116                                4 + 1 + 1,
2117                                EAP_TYPE_EKE,
2118                                EAP_EKE_FAILURE)
2119         idx += 1
2120         if ctx['num'] == idx:
2121             logger.info("Test: EAP-Failure")
2122             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2123
2124         idx += 1
2125         if ctx['num'] == idx:
2126             logger.info("Test: Unexpected EAP-EKE-Commit/Request")
2127             return struct.pack(">BBHBB",
2128                                EAP_CODE_REQUEST, ctx['id'],
2129                                4 + 1 + 1,
2130                                EAP_TYPE_EKE,
2131                                EAP_EKE_COMMIT)
2132         idx += 1
2133         if ctx['num'] == idx:
2134             logger.info("Test: EAP-Failure")
2135             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2136
2137         idx += 1
2138         if ctx['num'] == idx:
2139             logger.info("Test: Valid EAP-EKE-ID/Request")
2140             return struct.pack(">BBHBBBB4BB",
2141                                EAP_CODE_REQUEST, ctx['id'],
2142                                4 + 1 + 1 + 2 + 4 + 1,
2143                                EAP_TYPE_EKE,
2144                                EAP_EKE_ID,
2145                                1, 0,
2146                                3, 1, 1, 1,
2147                                255)
2148         idx += 1
2149         if ctx['num'] == idx:
2150             logger.info("Test: Too short EAP-EKE-Commit/Request")
2151             return struct.pack(">BBHBB",
2152                                EAP_CODE_REQUEST, ctx['id'],
2153                                4 + 1 + 1,
2154                                EAP_TYPE_EKE,
2155                                EAP_EKE_COMMIT)
2156         idx += 1
2157         if ctx['num'] == idx:
2158             logger.info("Test: EAP-Failure")
2159             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2160
2161         idx += 1
2162         if ctx['num'] == idx:
2163             logger.info("Test: Valid EAP-EKE-ID/Request")
2164             return struct.pack(">BBHBBBB4BB",
2165                                EAP_CODE_REQUEST, ctx['id'],
2166                                4 + 1 + 1 + 2 + 4 + 1,
2167                                EAP_TYPE_EKE,
2168                                EAP_EKE_ID,
2169                                1, 0,
2170                                1, 1, 1, 1,
2171                                255)
2172         idx += 1
2173         if ctx['num'] == idx:
2174             logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
2175             return struct.pack(">BBHBB4L32L",
2176                                EAP_CODE_REQUEST, ctx['id'],
2177                                4 + 1 + 1 + 16 + 128,
2178                                EAP_TYPE_EKE,
2179                                EAP_EKE_COMMIT,
2180                                0, 0, 0, 0,
2181                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2182                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2183         idx += 1
2184         if ctx['num'] == idx:
2185             logger.info("Test: Too short EAP-EKE-Confirm/Request")
2186             return struct.pack(">BBHBB",
2187                                EAP_CODE_REQUEST, ctx['id'],
2188                                4 + 1 + 1,
2189                                EAP_TYPE_EKE,
2190                                EAP_EKE_CONFIRM)
2191         idx += 1
2192         if ctx['num'] == idx:
2193             logger.info("Test: EAP-Failure")
2194             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2195
2196         idx += 1
2197         if ctx['num'] == idx:
2198             logger.info("Test: Valid EAP-EKE-ID/Request")
2199             return struct.pack(">BBHBBBB4BB",
2200                                EAP_CODE_REQUEST, ctx['id'],
2201                                4 + 1 + 1 + 2 + 4 + 1,
2202                                EAP_TYPE_EKE,
2203                                EAP_EKE_ID,
2204                                1, 0,
2205                                1, 1, 1, 1,
2206                                255)
2207         idx += 1
2208         if ctx['num'] == idx:
2209             logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
2210             return struct.pack(">BBHBB4L32L",
2211                                EAP_CODE_REQUEST, ctx['id'],
2212                                4 + 1 + 1 + 16 + 128,
2213                                EAP_TYPE_EKE,
2214                                EAP_EKE_COMMIT,
2215                                0, 0, 0, 0,
2216                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2217                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2218         idx += 1
2219         if ctx['num'] == idx:
2220             logger.info("Test: Invalid PNonce_PS and Auth_S values in EAP-EKE-Confirm/Request")
2221             return struct.pack(">BBHBB4L8L5L5L",
2222                                EAP_CODE_REQUEST, ctx['id'],
2223                                4 + 1 + 1 + 16 + 2 * 16 + 20 + 20,
2224                                EAP_TYPE_EKE,
2225                                EAP_EKE_CONFIRM,
2226                                0, 0, 0, 0,
2227                                0, 0, 0, 0, 0, 0, 0, 0,
2228                                0, 0, 0, 0, 0,
2229                                0, 0, 0, 0, 0)
2230         idx += 1
2231         if ctx['num'] == idx:
2232             logger.info("Test: EAP-Failure")
2233             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2234
2235         return None
2236
2237     srv = start_radius_server(eke_handler)
2238
2239     try:
2240         hapd = start_ap(apdev[0])
2241
2242         for i in range(0, 14):
2243             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2244                            eap="EKE", identity="user", password="password",
2245                            wait_connect=False)
2246             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2247                                    timeout=15)
2248             if ev is None:
2249                 raise Exception("Timeout on EAP start")
2250             if i in [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]:
2251                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
2252                                        timeout=10)
2253                 if ev is None:
2254                     raise Exception("Timeout on EAP failure")
2255             else:
2256                 time.sleep(0.05)
2257             dev[0].request("REMOVE_NETWORK all")
2258             dev[0].dump_monitor()
2259     finally:
2260         stop_radius_server(srv)
2261
2262 def eap_eke_test_fail(dev, phase1=None, success=False):
2263     dev.connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2264                 eap="EKE", identity="eke user", password="hello",
2265                 phase1=phase1, erp="1", wait_connect=False)
2266     ev = dev.wait_event([ "CTRL-EVENT-EAP-FAILURE",
2267                           "CTRL-EVENT-EAP-SUCCESS" ], timeout=5)
2268     if ev is None:
2269         raise Exception("Timeout on EAP failure")
2270     if not success and "CTRL-EVENT-EAP-FAILURE" not in ev:
2271         raise Exception("EAP did not fail during failure test")
2272     dev.request("REMOVE_NETWORK all")
2273     dev.wait_disconnected()
2274
2275 def test_eap_proto_eke_errors(dev, apdev):
2276     """EAP-EKE local error cases"""
2277     check_eap_capa(dev[0], "EKE")
2278     params = hostapd.wpa2_eap_params(ssid="eap-test")
2279     hapd = hostapd.add_ap(apdev[0], params)
2280
2281     for i in range(1, 3):
2282         with alloc_fail(dev[0], i, "eap_eke_init"):
2283             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2284                            eap="EKE", identity="eke user", password="hello",
2285                            wait_connect=False)
2286             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
2287                                    timeout=15)
2288             if ev is None:
2289                 raise Exception("Timeout on EAP start")
2290             dev[0].request("REMOVE_NETWORK all")
2291             dev[0].wait_disconnected()
2292
2293     tests = [ (1, "eap_eke_dh_init", None),
2294               (1, "eap_eke_prf_hmac_sha1", "dhgroup=3 encr=1 prf=1 mac=1"),
2295               (1, "eap_eke_prf_hmac_sha256", "dhgroup=5 encr=1 prf=2 mac=2"),
2296               (1, "eap_eke_prf", None),
2297               (1, "os_get_random;eap_eke_dhcomp", None),
2298               (1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
2299               (1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
2300               (1, "eap_eke_prf;eap_eke_shared_secret", None),
2301               (1, "eap_eke_prfplus;eap_eke_derive_ke_ki", None),
2302               (1, "eap_eke_prfplus;eap_eke_derive_ka", None),
2303               (1, "eap_eke_prfplus;eap_eke_derive_msk", None),
2304               (1, "os_get_random;eap_eke_prot", None),
2305               (1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
2306               (1, "eap_eke_derive_key;eap_eke_process_commit", None),
2307               (1, "eap_eke_dh_init;eap_eke_process_commit", None),
2308               (1, "eap_eke_shared_secret;eap_eke_process_commit", None),
2309               (1, "eap_eke_derive_ke_ki;eap_eke_process_commit", None),
2310               (1, "eap_eke_dhcomp;eap_eke_process_commit", None),
2311               (1, "os_get_random;eap_eke_process_commit", None),
2312               (1, "os_get_random;=eap_eke_process_commit", None),
2313               (1, "eap_eke_prot;eap_eke_process_commit", None),
2314               (1, "eap_eke_decrypt_prot;eap_eke_process_confirm", None),
2315               (1, "eap_eke_derive_ka;eap_eke_process_confirm", None),
2316               (1, "eap_eke_auth;eap_eke_process_confirm", None),
2317               (2, "eap_eke_auth;eap_eke_process_confirm", None),
2318               (1, "eap_eke_prot;eap_eke_process_confirm", None),
2319               (1, "eap_eke_derive_msk;eap_eke_process_confirm", None) ]
2320     for count, func, phase1 in tests:
2321         with fail_test(dev[0], count, func):
2322             eap_eke_test_fail(dev[0], phase1)
2323
2324     tests = [ (1, "=eap_eke_derive_ke_ki", None),
2325               (1, "=eap_eke_derive_ka", None),
2326               (1, "=eap_eke_derive_msk", None),
2327               (1, "eap_eke_build_msg;eap_eke_process_id", None),
2328               (1, "wpabuf_alloc;eap_eke_process_id", None),
2329               (1, "=eap_eke_process_id", None),
2330               (1, "wpabuf_alloc;=eap_eke_process_id", None),
2331               (1, "wpabuf_alloc;eap_eke_process_id", None),
2332               (1, "eap_eke_build_msg;eap_eke_process_commit", None),
2333               (1, "wpabuf_resize;eap_eke_process_commit", None),
2334               (1, "eap_eke_build_msg;eap_eke_process_confirm", None) ]
2335     for count, func, phase1 in tests:
2336         with alloc_fail(dev[0], count, func):
2337             eap_eke_test_fail(dev[0], phase1)
2338
2339     tests = [ (1, "eap_eke_getKey", None),
2340               (1, "eap_eke_get_emsk", None),
2341               (1, "eap_eke_get_session_id", None) ]
2342     for count, func, phase1 in tests:
2343         with alloc_fail(dev[0], count, func):
2344             eap_eke_test_fail(dev[0], phase1, success=True)
2345
2346 EAP_PAX_OP_STD_1 = 0x01
2347 EAP_PAX_OP_STD_2 = 0x02
2348 EAP_PAX_OP_STD_3 = 0x03
2349 EAP_PAX_OP_SEC_1 = 0x11
2350 EAP_PAX_OP_SEC_2 = 0x12
2351 EAP_PAX_OP_SEC_3 = 0x13
2352 EAP_PAX_OP_SEC_4 = 0x14
2353 EAP_PAX_OP_SEC_5 = 0x15
2354 EAP_PAX_OP_ACK = 0x21
2355
2356 EAP_PAX_FLAGS_MF = 0x01
2357 EAP_PAX_FLAGS_CE = 0x02
2358 EAP_PAX_FLAGS_AI = 0x04
2359
2360 EAP_PAX_MAC_HMAC_SHA1_128 = 0x01
2361 EAP_PAX_HMAC_SHA256_128 = 0x02
2362
2363 EAP_PAX_DH_GROUP_NONE = 0x00
2364 EAP_PAX_DH_GROUP_2048_MODP = 0x01
2365 EAP_PAX_DH_GROUP_3072_MODP = 0x02
2366 EAP_PAX_DH_GROUP_NIST_ECC_P_256 = 0x03
2367
2368 EAP_PAX_PUBLIC_KEY_NONE = 0x00
2369 EAP_PAX_PUBLIC_KEY_RSAES_OAEP = 0x01
2370 EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 = 0x02
2371 EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC = 0x03
2372
2373 EAP_PAX_ADE_VENDOR_SPECIFIC = 0x01
2374 EAP_PAX_ADE_CLIENT_CHANNEL_BINDING = 0x02
2375 EAP_PAX_ADE_SERVER_CHANNEL_BINDING = 0x03
2376
2377 def test_eap_proto_pax(dev, apdev):
2378     """EAP-PAX protocol tests"""
2379     def pax_std_1(ctx):
2380             logger.info("Test: STD-1")
2381             ctx['id'] = 10
2382             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2383                                4 + 1 + 5 + 2 + 32 + 16,
2384                                EAP_TYPE_PAX,
2385                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2386                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2387                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2388                                0x16, 0xc9, 0x08, 0x9d, 0x98, 0xa5, 0x6e, 0x1f,
2389                                0xf0, 0xac, 0xcf, 0xc4, 0x66, 0xcd, 0x2d, 0xbf)
2390
2391     def pax_handler(ctx, req):
2392         logger.info("pax_handler - RX " + req.encode("hex"))
2393         if 'num' not in ctx:
2394             ctx['num'] = 0
2395         ctx['num'] = ctx['num'] + 1
2396         if 'id' not in ctx:
2397             ctx['id'] = 1
2398         ctx['id'] = (ctx['id'] + 1) % 256
2399
2400         idx = 0
2401
2402         idx += 1
2403         if ctx['num'] == idx:
2404             logger.info("Test: Missing payload")
2405             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2406                                4 + 1,
2407                                EAP_TYPE_PAX)
2408
2409         idx += 1
2410         if ctx['num'] == idx:
2411             logger.info("Test: Minimum length payload")
2412             return struct.pack(">BBHB4L", EAP_CODE_REQUEST, ctx['id'],
2413                                4 + 1 + 16,
2414                                EAP_TYPE_PAX,
2415                                0, 0, 0, 0)
2416
2417         idx += 1
2418         if ctx['num'] == idx:
2419             logger.info("Test: Unsupported MAC ID")
2420             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
2421                                4 + 1 + 5 + 16,
2422                                EAP_TYPE_PAX,
2423                                EAP_PAX_OP_STD_1, 0, 255, EAP_PAX_DH_GROUP_NONE,
2424                                EAP_PAX_PUBLIC_KEY_NONE,
2425                                0, 0, 0, 0)
2426
2427         idx += 1
2428         if ctx['num'] == idx:
2429             logger.info("Test: Unsupported DH Group ID")
2430             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
2431                                4 + 1 + 5 + 16,
2432                                EAP_TYPE_PAX,
2433                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2434                                255, EAP_PAX_PUBLIC_KEY_NONE,
2435                                0, 0, 0, 0)
2436
2437         idx += 1
2438         if ctx['num'] == idx:
2439             logger.info("Test: Unsupported Public Key ID")
2440             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
2441                                4 + 1 + 5 + 16,
2442                                EAP_TYPE_PAX,
2443                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2444                                EAP_PAX_DH_GROUP_NONE, 255,
2445                                0, 0, 0, 0)
2446
2447         idx += 1
2448         if ctx['num'] == idx:
2449             logger.info("Test: More fragments")
2450             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
2451                                4 + 1 + 5 + 16,
2452                                EAP_TYPE_PAX,
2453                                EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_MF,
2454                                EAP_PAX_MAC_HMAC_SHA1_128,
2455                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2456                                0, 0, 0, 0)
2457
2458         idx += 1
2459         if ctx['num'] == idx:
2460             logger.info("Test: Invalid ICV")
2461             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
2462                                4 + 1 + 5 + 16,
2463                                EAP_TYPE_PAX,
2464                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2465                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2466                                0, 0, 0, 0)
2467
2468         idx += 1
2469         if ctx['num'] == idx:
2470             logger.info("Test: Invalid ICV in short frame")
2471             return struct.pack(">BBHBBBBBB3L", EAP_CODE_REQUEST, ctx['id'],
2472                                4 + 1 + 5 + 12,
2473                                EAP_TYPE_PAX,
2474                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2475                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2476                                0, 0, 0)
2477
2478         idx += 1
2479         if ctx['num'] == idx:
2480             logger.info("Test: Correct ICV - unsupported op_code")
2481             ctx['id'] = 10
2482             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
2483                                4 + 1 + 5 + 16,
2484                                EAP_TYPE_PAX,
2485                                255, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2486                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2487                                0x90, 0x78, 0x97, 0x38, 0x29, 0x94, 0x32, 0xd4,
2488                                0x81, 0x27, 0xe0, 0xf6, 0x3b, 0x0d, 0xb2, 0xb2)
2489
2490         idx += 1
2491         if ctx['num'] == idx:
2492             logger.info("Test: Correct ICV - CE flag in STD-1")
2493             ctx['id'] = 10
2494             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
2495                                4 + 1 + 5 + 16,
2496                                EAP_TYPE_PAX,
2497                                EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_CE,
2498                                EAP_PAX_MAC_HMAC_SHA1_128,
2499                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2500                                0x9c, 0x98, 0xb4, 0x0b, 0x94, 0x90, 0xde, 0x88,
2501                                0xb7, 0x72, 0x63, 0x44, 0x1d, 0xe3, 0x7c, 0x5c)
2502
2503         idx += 1
2504         if ctx['num'] == idx:
2505             logger.info("Test: Correct ICV - too short STD-1 payload")
2506             ctx['id'] = 10
2507             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
2508                                4 + 1 + 5 + 16,
2509                                EAP_TYPE_PAX,
2510                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2511                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2512                                0xda, 0xab, 0x2c, 0xe7, 0x84, 0x41, 0xb5, 0x5c,
2513                                0xee, 0xcf, 0x62, 0x03, 0xc5, 0x69, 0xcb, 0xf4)
2514
2515         idx += 1
2516         if ctx['num'] == idx:
2517             logger.info("Test: Correct ICV - incorrect A length in STD-1")
2518             ctx['id'] = 10
2519             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2520                                4 + 1 + 5 + 2 + 32 + 16,
2521                                EAP_TYPE_PAX,
2522                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2523                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2524                                0, 0, 0, 0, 0, 0, 0, 0, 0,
2525                                0xc4, 0xb0, 0x81, 0xe4, 0x6c, 0x8c, 0x20, 0x23,
2526                                0x60, 0x46, 0x89, 0xea, 0x94, 0x60, 0xf3, 0x2a)
2527
2528         idx += 1
2529         if ctx['num'] == idx:
2530             logger.info("Test: Correct ICV - extra data in STD-1")
2531             ctx['id'] = 10
2532             return struct.pack(">BBHBBBBBBH8LB16B", EAP_CODE_REQUEST, ctx['id'],
2533                                4 + 1 + 5 + 2 + 32 + 1 + 16,
2534                                EAP_TYPE_PAX,
2535                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2536                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2537                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2538                                1,
2539                                0x61, 0x49, 0x65, 0x37, 0x21, 0xe8, 0xd8, 0xbf,
2540                                0xf3, 0x02, 0x01, 0xe5, 0x42, 0x51, 0xd3, 0x34)
2541         idx += 1
2542         if ctx['num'] == idx:
2543             logger.info("Test: Unexpected STD-1")
2544             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2545                                4 + 1 + 5 + 2 + 32 + 16,
2546                                EAP_TYPE_PAX,
2547                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2548                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2549                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2550                                0xe5, 0x1d, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
2551                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
2552
2553         idx += 1
2554         if ctx['num'] == idx:
2555             return pax_std_1(ctx)
2556         idx += 1
2557         if ctx['num'] == idx:
2558             logger.info("Test: MAC ID changed during session")
2559             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2560                                4 + 1 + 5 + 2 + 32 + 16,
2561                                EAP_TYPE_PAX,
2562                                EAP_PAX_OP_STD_1, 0, EAP_PAX_HMAC_SHA256_128,
2563                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2564                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2565                                0xee, 0x00, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
2566                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
2567
2568         idx += 1
2569         if ctx['num'] == idx:
2570             return pax_std_1(ctx)
2571         idx += 1
2572         if ctx['num'] == idx:
2573             logger.info("Test: DH Group ID changed during session")
2574             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2575                                4 + 1 + 5 + 2 + 32 + 16,
2576                                EAP_TYPE_PAX,
2577                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2578                                EAP_PAX_DH_GROUP_2048_MODP,
2579                                EAP_PAX_PUBLIC_KEY_NONE,
2580                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2581                                0xee, 0x01, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
2582                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
2583
2584         idx += 1
2585         if ctx['num'] == idx:
2586             return pax_std_1(ctx)
2587         idx += 1
2588         if ctx['num'] == idx:
2589             logger.info("Test: Public Key ID changed during session")
2590             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2591                                4 + 1 + 5 + 2 + 32 + 16,
2592                                EAP_TYPE_PAX,
2593                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2594                                EAP_PAX_DH_GROUP_NONE,
2595                                EAP_PAX_PUBLIC_KEY_RSAES_OAEP,
2596                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2597                                0xee, 0x02, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
2598                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
2599
2600         idx += 1
2601         if ctx['num'] == idx:
2602             logger.info("Test: Unexpected STD-3")
2603             ctx['id'] = 10
2604             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2605                                4 + 1 + 5 + 2 + 32 + 16,
2606                                EAP_TYPE_PAX,
2607                                EAP_PAX_OP_STD_3, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2608                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2609                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2610                                0x47, 0xbb, 0xc0, 0xf9, 0xb9, 0x69, 0xf5, 0xcb,
2611                                0x3a, 0xe8, 0xe7, 0xd6, 0x80, 0x28, 0xf2, 0x59)
2612
2613         idx += 1
2614         if ctx['num'] == idx:
2615             return pax_std_1(ctx)
2616         idx += 1
2617         if ctx['num'] == idx:
2618             # TODO: MAC calculation; for now, this gets dropped due to incorrect
2619             # ICV
2620             logger.info("Test: STD-3 with CE flag")
2621             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2622                                4 + 1 + 5 + 2 + 32 + 16,
2623                                EAP_TYPE_PAX,
2624                                EAP_PAX_OP_STD_3, EAP_PAX_FLAGS_CE,
2625                                EAP_PAX_MAC_HMAC_SHA1_128,
2626                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2627                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2628                                0x8a, 0xc2, 0xf9, 0xf4, 0x8b, 0x75, 0x72, 0xa2,
2629                                0x4d, 0xd3, 0x1e, 0x54, 0x77, 0x04, 0x05, 0xe2)
2630
2631         idx += 1
2632         if ctx['num'] & 0x1 == idx & 0x1:
2633             logger.info("Test: Default request")
2634             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2635                                4 + 1,
2636                                EAP_TYPE_PAX)
2637         else:
2638             logger.info("Test: Default EAP-Failure")
2639             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2640
2641     srv = start_radius_server(pax_handler)
2642
2643     try:
2644         hapd = start_ap(apdev[0])
2645
2646         for i in range(0, 18):
2647             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2648                            eap="PAX", identity="user",
2649                            password_hex="0123456789abcdef0123456789abcdef",
2650                            wait_connect=False)
2651             logger.info("Waiting for EAP method to start")
2652             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2653                                    timeout=15)
2654             if ev is None:
2655                 raise Exception("Timeout on EAP start")
2656             time.sleep(0.05)
2657             dev[0].request("REMOVE_NETWORK all")
2658             dev[0].dump_monitor()
2659
2660         logger.info("Too short password")
2661         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2662                        eap="PAX", identity="user",
2663                        password_hex="0123456789abcdef0123456789abcd",
2664                        wait_connect=False)
2665         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
2666         if ev is None:
2667             raise Exception("Timeout on EAP start")
2668         time.sleep(0.1)
2669         dev[0].request("REMOVE_NETWORK all")
2670         dev[0].dump_monitor()
2671
2672         logger.info("No password")
2673         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2674                        eap="PAX", identity="user",
2675                        wait_connect=False)
2676         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
2677         if ev is None:
2678             raise Exception("Timeout on EAP start")
2679         time.sleep(0.1)
2680         dev[0].request("REMOVE_NETWORK all")
2681         dev[0].dump_monitor()
2682     finally:
2683         stop_radius_server(srv)
2684
2685 def test_eap_proto_pax_errors(dev, apdev):
2686     """EAP-PAX local error cases"""
2687     check_eap_capa(dev[0], "PAX")
2688     params = hostapd.wpa2_eap_params(ssid="eap-test")
2689     hapd = hostapd.add_ap(apdev[0], params)
2690
2691     for i in range(1, 3):
2692         with alloc_fail(dev[0], i, "eap_pax_init"):
2693             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2694                            eap="PAX", identity="pax.user@example.com",
2695                            password_hex="0123456789abcdef0123456789abcdef",
2696                            wait_connect=False)
2697             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
2698                                    timeout=15)
2699             if ev is None:
2700                 raise Exception("Timeout on EAP start")
2701             dev[0].request("REMOVE_NETWORK all")
2702             dev[0].wait_disconnected()
2703
2704     tests = [ "eap_msg_alloc;eap_pax_alloc_resp;eap_pax_process_std_1",
2705               "eap_msg_alloc;eap_pax_alloc_resp;eap_pax_process_std_3",
2706               "eap_pax_getKey",
2707               "eap_pax_get_emsk",
2708               "eap_pax_get_session_id" ]
2709     for func in tests:
2710         with alloc_fail(dev[0], 1, func):
2711             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2712                            eap="PAX", identity="pax.user@example.com",
2713                            password_hex="0123456789abcdef0123456789abcdef",
2714                            erp="1", wait_connect=False)
2715             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
2716             dev[0].request("REMOVE_NETWORK all")
2717             dev[0].wait_disconnected()
2718
2719     tests = [ (1, "os_get_random;eap_pax_process_std_1"),
2720               (1, "eap_pax_initial_key_derivation"),
2721               (1, "eap_pax_mac;eap_pax_process_std_3"),
2722               (2, "eap_pax_mac;eap_pax_process_std_3"),
2723               (1, "eap_pax_kdf;eap_pax_getKey"),
2724               (1, "eap_pax_kdf;eap_pax_get_emsk") ]
2725     for count, func in tests:
2726         with fail_test(dev[0], count, func):
2727             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2728                            eap="PAX", identity="pax.user@example.com",
2729                            password_hex="0123456789abcdef0123456789abcdef",
2730                            erp="1", wait_connect=False)
2731             wait_fail_trigger(dev[0], "GET_FAIL")
2732             dev[0].request("REMOVE_NETWORK all")
2733             dev[0].wait_disconnected()
2734
2735 def test_eap_proto_psk(dev, apdev):
2736     """EAP-PSK protocol tests"""
2737     def psk_handler(ctx, req):
2738         logger.info("psk_handler - RX " + req.encode("hex"))
2739         if 'num' not in ctx:
2740             ctx['num'] = 0
2741         ctx['num'] = ctx['num'] + 1
2742         if 'id' not in ctx:
2743             ctx['id'] = 1
2744         ctx['id'] = (ctx['id'] + 1) % 256
2745
2746         idx = 0
2747
2748         idx += 1
2749         if ctx['num'] == idx:
2750             logger.info("Test: Missing payload")
2751             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2752                                4 + 1,
2753                                EAP_TYPE_PSK)
2754
2755         idx += 1
2756         if ctx['num'] == idx:
2757             logger.info("Test: Non-zero T in first message")
2758             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2759                                4 + 1 + 1 + 16,
2760                                EAP_TYPE_PSK, 0xc0, 0, 0, 0, 0)
2761
2762         idx += 1
2763         if ctx['num'] == idx:
2764             logger.info("Test: Valid first message")
2765             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2766                                4 + 1 + 1 + 16,
2767                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2768         idx += 1
2769         if ctx['num'] == idx:
2770             logger.info("Test: Too short third message")
2771             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2772                                4 + 1,
2773                                EAP_TYPE_PSK)
2774
2775         idx += 1
2776         if ctx['num'] == idx:
2777             logger.info("Test: Valid first message")
2778             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2779                                4 + 1 + 1 + 16,
2780                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2781         idx += 1
2782         if ctx['num'] == idx:
2783             logger.info("Test: Incorrect T in third message")
2784             return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
2785                                4 + 1 + 1 + 16 + 16,
2786                                EAP_TYPE_PSK, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2787
2788         idx += 1
2789         if ctx['num'] == idx:
2790             logger.info("Test: Valid first message")
2791             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2792                                4 + 1 + 1 + 16,
2793                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2794         idx += 1
2795         if ctx['num'] == idx:
2796             logger.info("Test: Missing PCHANNEL in third message")
2797             return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
2798                                4 + 1 + 1 + 16 + 16,
2799                                EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0)
2800
2801         idx += 1
2802         if ctx['num'] == idx:
2803             logger.info("Test: Valid first message")
2804             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2805                                4 + 1 + 1 + 16,
2806                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2807         idx += 1
2808         if ctx['num'] == idx:
2809             logger.info("Test: Invalic MAC_S in third message")
2810             return struct.pack(">BBHBB4L4L5LB", EAP_CODE_REQUEST, ctx['id'],
2811                                4 + 1 + 1 + 16 + 16 + 21,
2812                                EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
2813                                0, 0, 0, 0, 0, 0)
2814
2815         idx += 1
2816         if ctx['num'] == idx:
2817             logger.info("Test: Valid first message")
2818             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2819                                4 + 1 + 1 + 16,
2820                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2821         idx += 1
2822         if ctx['num'] == idx:
2823             logger.info("Test: EAP-Failure")
2824             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2825
2826         return None
2827
2828     srv = start_radius_server(psk_handler)
2829
2830     try:
2831         hapd = start_ap(apdev[0])
2832
2833         for i in range(0, 6):
2834             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2835                            eap="PSK", identity="user",
2836                            password_hex="0123456789abcdef0123456789abcdef",
2837                            wait_connect=False)
2838             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2839                                    timeout=15)
2840             if ev is None:
2841                 raise Exception("Timeout on EAP start")
2842             time.sleep(0.1)
2843             dev[0].request("REMOVE_NETWORK all")
2844
2845         logger.info("Test: Invalid PSK length")
2846         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2847                        eap="PSK", identity="user",
2848                        password_hex="0123456789abcdef0123456789abcd",
2849                        wait_connect=False)
2850         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2851                                timeout=15)
2852         if ev is None:
2853             raise Exception("Timeout on EAP start")
2854         time.sleep(0.1)
2855         dev[0].request("REMOVE_NETWORK all")
2856     finally:
2857         stop_radius_server(srv)
2858
2859 def test_eap_proto_psk_errors(dev, apdev):
2860     """EAP-PSK local error cases"""
2861     check_eap_capa(dev[0], "PSK")
2862     params = hostapd.wpa2_eap_params(ssid="eap-test")
2863     hapd = hostapd.add_ap(apdev[0], params)
2864
2865     for i in range(1, 3):
2866         with alloc_fail(dev[0], i, "eap_psk_init"):
2867             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2868                            eap="PSK", identity="psk.user@example.com",
2869                            password_hex="0123456789abcdef0123456789abcdef",
2870                            wait_connect=False)
2871             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
2872                                    timeout=15)
2873             if ev is None:
2874                 raise Exception("Timeout on EAP start")
2875             dev[0].request("REMOVE_NETWORK all")
2876             dev[0].wait_disconnected()
2877
2878     for i in range(1, 4):
2879         with fail_test(dev[0], i, "eap_psk_key_setup;eap_psk_init"):
2880             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2881                            eap="PSK", identity="psk.user@example.com",
2882                            password_hex="0123456789abcdef0123456789abcdef",
2883                            wait_connect=False)
2884             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
2885                                    timeout=15)
2886             if ev is None:
2887                 raise Exception("Timeout on EAP start")
2888             dev[0].request("REMOVE_NETWORK all")
2889             dev[0].wait_disconnected()
2890
2891     tests = [ (1, "=eap_psk_process_1"),
2892               (2, "=eap_psk_process_1"),
2893               (1, "eap_msg_alloc;eap_psk_process_1"),
2894               (1, "=eap_psk_process_3"),
2895               (2, "=eap_psk_process_3"),
2896               (1, "eap_msg_alloc;eap_psk_process_3"),
2897               (1, "eap_psk_getKey"),
2898               (1, "eap_psk_get_session_id"),
2899               (1, "eap_psk_get_emsk") ]
2900     for count, func in tests:
2901         with alloc_fail(dev[0], count, func):
2902             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2903                            eap="PSK", identity="psk.user@example.com",
2904                            password_hex="0123456789abcdef0123456789abcdef",
2905                            erp="1", wait_connect=False)
2906             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2907                                    timeout=15)
2908             if ev is None:
2909                 raise Exception("Timeout on EAP start")
2910             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
2911                               note="No allocation failure seen for %d:%s" % (count, func))
2912             dev[0].request("REMOVE_NETWORK all")
2913             dev[0].wait_disconnected()
2914
2915     tests = [ (1, "os_get_random;eap_psk_process_1"),
2916               (1, "omac1_aes_128;eap_psk_process_3"),
2917               (1, "aes_128_eax_decrypt;eap_psk_process_3"),
2918               (2, "aes_128_eax_decrypt;eap_psk_process_3"),
2919               (3, "aes_128_eax_decrypt;eap_psk_process_3"),
2920               (1, "aes_128_eax_encrypt;eap_psk_process_3"),
2921               (2, "aes_128_eax_encrypt;eap_psk_process_3"),
2922               (3, "aes_128_eax_encrypt;eap_psk_process_3"),
2923               (1, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2924               (2, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2925               (3, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2926               (4, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2927               (5, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2928               (6, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2929               (7, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2930               (8, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2931               (9, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2932               (10, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
2933               (1, "aes_128_ctr_encrypt;aes_128_eax_decrypt;eap_psk_process_3"),
2934               (1, "aes_128_ctr_encrypt;aes_128_eax_encrypt;eap_psk_process_3") ]
2935     for count, func in tests:
2936         with fail_test(dev[0], count, func):
2937             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2938                            eap="PSK", identity="psk.user@example.com",
2939                            password_hex="0123456789abcdef0123456789abcdef",
2940                            wait_connect=False)
2941             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2942                                    timeout=15)
2943             if ev is None:
2944                 raise Exception("Timeout on EAP start")
2945             wait_fail_trigger(dev[0], "GET_FAIL",
2946                               note="No failure seen for %d:%s" % (count, func))
2947             dev[0].request("REMOVE_NETWORK all")
2948             dev[0].wait_disconnected()
2949
2950 EAP_SIM_SUBTYPE_START = 10
2951 EAP_SIM_SUBTYPE_CHALLENGE = 11
2952 EAP_SIM_SUBTYPE_NOTIFICATION = 12
2953 EAP_SIM_SUBTYPE_REAUTHENTICATION = 13
2954 EAP_SIM_SUBTYPE_CLIENT_ERROR = 14
2955
2956 EAP_AKA_SUBTYPE_CHALLENGE = 1
2957 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT = 2
2958 EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE = 4
2959 EAP_AKA_SUBTYPE_IDENTITY = 5
2960 EAP_AKA_SUBTYPE_NOTIFICATION = 12
2961 EAP_AKA_SUBTYPE_REAUTHENTICATION = 13
2962 EAP_AKA_SUBTYPE_CLIENT_ERROR = 14
2963
2964 EAP_SIM_AT_RAND = 1
2965 EAP_SIM_AT_AUTN = 2
2966 EAP_SIM_AT_RES = 3
2967 EAP_SIM_AT_AUTS = 4
2968 EAP_SIM_AT_PADDING = 6
2969 EAP_SIM_AT_NONCE_MT = 7
2970 EAP_SIM_AT_PERMANENT_ID_REQ = 10
2971 EAP_SIM_AT_MAC = 11
2972 EAP_SIM_AT_NOTIFICATION = 12
2973 EAP_SIM_AT_ANY_ID_REQ = 13
2974 EAP_SIM_AT_IDENTITY = 14
2975 EAP_SIM_AT_VERSION_LIST = 15
2976 EAP_SIM_AT_SELECTED_VERSION = 16
2977 EAP_SIM_AT_FULLAUTH_ID_REQ = 17
2978 EAP_SIM_AT_COUNTER = 19
2979 EAP_SIM_AT_COUNTER_TOO_SMALL = 20
2980 EAP_SIM_AT_NONCE_S = 21
2981 EAP_SIM_AT_CLIENT_ERROR_CODE = 22
2982 EAP_SIM_AT_KDF_INPUT = 23
2983 EAP_SIM_AT_KDF = 24
2984 EAP_SIM_AT_IV = 129
2985 EAP_SIM_AT_ENCR_DATA = 130
2986 EAP_SIM_AT_NEXT_PSEUDONYM = 132
2987 EAP_SIM_AT_NEXT_REAUTH_ID = 133
2988 EAP_SIM_AT_CHECKCODE = 134
2989 EAP_SIM_AT_RESULT_IND = 135
2990 EAP_SIM_AT_BIDDING = 136
2991
2992 def test_eap_proto_aka(dev, apdev):
2993     """EAP-AKA protocol tests"""
2994     def aka_handler(ctx, req):
2995         logger.info("aka_handler - RX " + req.encode("hex"))
2996         if 'num' not in ctx:
2997             ctx['num'] = 0
2998         ctx['num'] = ctx['num'] + 1
2999         if 'id' not in ctx:
3000             ctx['id'] = 1
3001         ctx['id'] = (ctx['id'] + 1) % 256
3002
3003         idx = 0
3004
3005         idx += 1
3006         if ctx['num'] == idx:
3007             logger.info("Test: Missing payload")
3008             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3009                                4 + 1,
3010                                EAP_TYPE_AKA)
3011
3012         idx += 1
3013         if ctx['num'] == idx:
3014             logger.info("Test: Unknown subtype")
3015             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3016                                4 + 1 + 3,
3017                                EAP_TYPE_AKA, 255, 0)
3018         idx += 1
3019         if ctx['num'] == idx:
3020             logger.info("Test: EAP-Failure")
3021             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3022
3023         idx += 1
3024         if ctx['num'] == idx:
3025             logger.info("Test: Client Error")
3026             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3027                                4 + 1 + 3,
3028                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR, 0)
3029         idx += 1
3030         if ctx['num'] == idx:
3031             logger.info("Test: EAP-Failure")
3032             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3033
3034         idx += 1
3035         if ctx['num'] == idx:
3036             logger.info("Test: Too short attribute header")
3037             return struct.pack(">BBHBBHB", EAP_CODE_REQUEST, ctx['id'],
3038                                4 + 1 + 1 + 3,
3039                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255)
3040         idx += 1
3041         if ctx['num'] == idx:
3042             logger.info("Test: EAP-Failure")
3043             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3044
3045         idx += 1
3046         if ctx['num'] == idx:
3047             logger.info("Test: Truncated attribute")
3048             return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
3049                                4 + 1 + 1 + 4,
3050                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
3051                                255)
3052         idx += 1
3053         if ctx['num'] == idx:
3054             logger.info("Test: EAP-Failure")
3055             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3056
3057         idx += 1
3058         if ctx['num'] == idx:
3059             logger.info("Test: Too short attribute data")
3060             return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
3061                                4 + 1 + 1 + 4,
3062                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
3063                                0)
3064         idx += 1
3065         if ctx['num'] == idx:
3066             logger.info("Test: EAP-Failure")
3067             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3068
3069         idx += 1
3070         if ctx['num'] == idx:
3071             logger.info("Test: Skippable/non-skippable unrecognzized attribute")
3072             return struct.pack(">BBHBBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3073                                4 + 1 + 1 + 10,
3074                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3075                                255, 1, 0, 127, 1, 0)
3076         idx += 1
3077         if ctx['num'] == idx:
3078             logger.info("Test: EAP-Failure")
3079             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3080
3081         idx += 1
3082         if ctx['num'] == idx:
3083             logger.info("Test: Identity request without ID type")
3084             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3085                                4 + 1 + 3,
3086                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0)
3087         idx += 1
3088         if ctx['num'] == idx:
3089             logger.info("Test: Identity request ANY_ID")
3090             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3091                                4 + 1 + 3 + 4,
3092                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3093                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3094         idx += 1
3095         if ctx['num'] == idx:
3096             logger.info("Test: Identity request ANY_ID (duplicate)")
3097             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3098                                4 + 1 + 3 + 4,
3099                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3100                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3101         idx += 1
3102         if ctx['num'] == idx:
3103             logger.info("Test: EAP-Failure")
3104             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3105
3106         idx += 1
3107         if ctx['num'] == idx:
3108             logger.info("Test: Identity request ANY_ID")
3109             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3110                                4 + 1 + 3 + 4,
3111                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3112                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3113         idx += 1
3114         if ctx['num'] == idx:
3115             logger.info("Test: Identity request FULLAUTH_ID")
3116             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3117                                4 + 1 + 3 + 4,
3118                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3119                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
3120         idx += 1
3121         if ctx['num'] == idx:
3122             logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
3123             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3124                                4 + 1 + 3 + 4,
3125                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3126                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
3127         idx += 1
3128         if ctx['num'] == idx:
3129             logger.info("Test: EAP-Failure")
3130             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3131
3132         idx += 1
3133         if ctx['num'] == idx:
3134             logger.info("Test: Identity request ANY_ID")
3135             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3136                                4 + 1 + 3 + 4,
3137                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3138                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3139         idx += 1
3140         if ctx['num'] == idx:
3141             logger.info("Test: Identity request FULLAUTH_ID")
3142             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3143                                4 + 1 + 3 + 4,
3144                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3145                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
3146         idx += 1
3147         if ctx['num'] == idx:
3148             logger.info("Test: Identity request PERMANENT_ID")
3149             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3150                                4 + 1 + 3 + 4,
3151                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3152                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
3153         idx += 1
3154         if ctx['num'] == idx:
3155             logger.info("Test: Identity request PERMANENT_ID (duplicate)")
3156             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3157                                4 + 1 + 3 + 4,
3158                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3159                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
3160         idx += 1
3161         if ctx['num'] == idx:
3162             logger.info("Test: EAP-Failure")
3163             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3164
3165         idx += 1
3166         if ctx['num'] == idx:
3167             logger.info("Test: Challenge with no attributes")
3168             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3169                                4 + 1 + 3,
3170                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0)
3171         idx += 1
3172         if ctx['num'] == idx:
3173             logger.info("Test: EAP-Failure")
3174             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3175
3176         idx += 1
3177         if ctx['num'] == idx:
3178             logger.info("Test: AKA Challenge with BIDDING")
3179             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3180                                4 + 1 + 3 + 4,
3181                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3182                                EAP_SIM_AT_BIDDING, 1, 0x8000)
3183         idx += 1
3184         if ctx['num'] == idx:
3185             logger.info("Test: EAP-Failure")
3186             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3187
3188         idx += 1
3189         if ctx['num'] == idx:
3190             logger.info("Test: Notification with no attributes")
3191             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3192                                4 + 1 + 3,
3193                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0)
3194         idx += 1
3195         if ctx['num'] == idx:
3196             logger.info("Test: EAP-Failure")
3197             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3198
3199         idx += 1
3200         if ctx['num'] == idx:
3201             logger.info("Test: Notification indicating success, but no MAC")
3202             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3203                                4 + 1 + 3 + 4,
3204                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3205                                EAP_SIM_AT_NOTIFICATION, 1, 32768)
3206         idx += 1
3207         if ctx['num'] == idx:
3208             logger.info("Test: EAP-Failure")
3209             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3210
3211         idx += 1
3212         if ctx['num'] == idx:
3213             logger.info("Test: Notification indicating success, but invalid MAC value")
3214             return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
3215                                4 + 1 + 3 + 4 + 20,
3216                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3217                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
3218                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
3219         idx += 1
3220         if ctx['num'] == idx:
3221             logger.info("Test: EAP-Failure")
3222             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3223
3224         idx += 1
3225         if ctx['num'] == idx:
3226             logger.info("Test: Notification indicating success with zero-key MAC")
3227             return struct.pack(">BBHBBHBBHBBH16B", EAP_CODE_REQUEST,
3228                                ctx['id'] - 2,
3229                                4 + 1 + 3 + 4 + 20,
3230                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3231                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
3232                                EAP_SIM_AT_MAC, 5, 0,
3233                                0xbe, 0x2e, 0xbb, 0xa9, 0xfa, 0x2e, 0x82, 0x36,
3234                                0x37, 0x8c, 0x32, 0x41, 0xb7, 0xc7, 0x58, 0xa3)
3235         idx += 1
3236         if ctx['num'] == idx:
3237             logger.info("Test: EAP-Success")
3238             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
3239
3240         idx += 1
3241         if ctx['num'] == idx:
3242             logger.info("Test: Notification before auth")
3243             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3244                                4 + 1 + 3 + 4,
3245                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3246                                EAP_SIM_AT_NOTIFICATION, 1, 16384)
3247         idx += 1
3248         if ctx['num'] == idx:
3249             logger.info("Test: EAP-Failure")
3250             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3251
3252         idx += 1
3253         if ctx['num'] == idx:
3254             logger.info("Test: Notification before auth")
3255             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3256                                4 + 1 + 3 + 4,
3257                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3258                                EAP_SIM_AT_NOTIFICATION, 1, 16385)
3259         idx += 1
3260         if ctx['num'] == idx:
3261             logger.info("Test: EAP-Failure")
3262             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3263
3264         idx += 1
3265         if ctx['num'] == idx:
3266             logger.info("Test: Notification with unrecognized non-failure")
3267             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3268                                4 + 1 + 3 + 4,
3269                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3270                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
3271         idx += 1
3272         if ctx['num'] == idx:
3273             logger.info("Test: Notification before auth (duplicate)")
3274             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3275                                4 + 1 + 3 + 4,
3276                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
3277                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
3278         idx += 1
3279         if ctx['num'] == idx:
3280             logger.info("Test: EAP-Failure")
3281             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3282
3283         idx += 1
3284         if ctx['num'] == idx:
3285             logger.info("Test: Re-authentication (unexpected) with no attributes")
3286             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3287                                4 + 1 + 3,
3288                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
3289                                0)
3290         idx += 1
3291         if ctx['num'] == idx:
3292             logger.info("Test: EAP-Failure")
3293             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3294
3295         idx += 1
3296         if ctx['num'] == idx:
3297             logger.info("Test: AKA Challenge with Checkcode claiming identity round was used")
3298             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
3299                                4 + 1 + 3 + 24,
3300                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3301                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
3302         idx += 1
3303         if ctx['num'] == idx:
3304             logger.info("Test: EAP-Failure")
3305             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3306
3307         idx += 1
3308         if ctx['num'] == idx:
3309             logger.info("Test: Identity request ANY_ID")
3310             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3311                                4 + 1 + 3 + 4,
3312                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3313                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3314         idx += 1
3315         if ctx['num'] == idx:
3316             logger.info("Test: AKA Challenge with Checkcode claiming no identity round was used")
3317             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3318                                4 + 1 + 3 + 4,
3319                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3320                                EAP_SIM_AT_CHECKCODE, 1, 0)
3321         idx += 1
3322         if ctx['num'] == idx:
3323             logger.info("Test: EAP-Failure")
3324             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3325
3326         idx += 1
3327         if ctx['num'] == idx:
3328             logger.info("Test: Identity request ANY_ID")
3329             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3330                                4 + 1 + 3 + 4,
3331                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3332                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3333         idx += 1
3334         if ctx['num'] == idx:
3335             logger.info("Test: AKA Challenge with mismatching Checkcode value")
3336             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
3337                                4 + 1 + 3 + 24,
3338                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3339                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
3340         idx += 1
3341         if ctx['num'] == idx:
3342             logger.info("Test: EAP-Failure")
3343             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3344
3345         idx += 1
3346         if ctx['num'] == idx:
3347             logger.info("Test: Re-authentication (unexpected) with Checkcode claimin identity round was used")
3348             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
3349                                4 + 1 + 3 + 24,
3350                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
3351                                0,
3352                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
3353         idx += 1
3354         if ctx['num'] == idx:
3355             logger.info("Test: EAP-Failure")
3356             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3357
3358         idx += 1
3359         if ctx['num'] == idx:
3360             logger.info("Test: Invalid AT_RAND length")
3361             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3362                                4 + 1 + 3 + 4,
3363                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3364                                EAP_SIM_AT_RAND, 1, 0)
3365         idx += 1
3366         if ctx['num'] == idx:
3367             logger.info("Test: EAP-Failure")
3368             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3369
3370         idx += 1
3371         if ctx['num'] == idx:
3372             logger.info("Test: Invalid AT_AUTN length")
3373             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3374                                4 + 1 + 3 + 4,
3375                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3376                                EAP_SIM_AT_AUTN, 1, 0)
3377         idx += 1
3378         if ctx['num'] == idx:
3379             logger.info("Test: EAP-Failure")
3380             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3381
3382         idx += 1
3383         if ctx['num'] == idx:
3384             logger.info("Test: Unencrypted AT_PADDING")
3385             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3386                                4 + 1 + 3 + 4,
3387                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3388                                EAP_SIM_AT_PADDING, 1, 0)
3389         idx += 1
3390         if ctx['num'] == idx:
3391             logger.info("Test: EAP-Failure")
3392             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3393
3394         idx += 1
3395         if ctx['num'] == idx:
3396             logger.info("Test: Invalid AT_NONCE_MT length")
3397             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3398                                4 + 1 + 3 + 4,
3399                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3400                                EAP_SIM_AT_NONCE_MT, 1, 0)
3401         idx += 1
3402         if ctx['num'] == idx:
3403             logger.info("Test: EAP-Failure")
3404             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3405
3406         idx += 1
3407         if ctx['num'] == idx:
3408             logger.info("Test: Invalid AT_MAC length")
3409             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3410                                4 + 1 + 3 + 4,
3411                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3412                                EAP_SIM_AT_MAC, 1, 0)
3413         idx += 1
3414         if ctx['num'] == idx:
3415             logger.info("Test: EAP-Failure")
3416             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3417
3418         idx += 1
3419         if ctx['num'] == idx:
3420             logger.info("Test: Invalid AT_NOTIFICATION length")
3421             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3422                                4 + 1 + 3 + 8,
3423                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3424                                EAP_SIM_AT_NOTIFICATION, 2, 0, 0)
3425         idx += 1
3426         if ctx['num'] == idx:
3427             logger.info("Test: EAP-Failure")
3428             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3429
3430         idx += 1
3431         if ctx['num'] == idx:
3432             logger.info("Test: AT_IDENTITY overflow")
3433             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3434                                4 + 1 + 3 + 4,
3435                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3436                                EAP_SIM_AT_IDENTITY, 1, 0xffff)
3437         idx += 1
3438         if ctx['num'] == idx:
3439             logger.info("Test: EAP-Failure")
3440             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3441
3442         idx += 1
3443         if ctx['num'] == idx:
3444             logger.info("Test: Unexpected AT_VERSION_LIST")
3445             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3446                                4 + 1 + 3 + 4,
3447                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3448                                EAP_SIM_AT_VERSION_LIST, 1, 0)
3449         idx += 1
3450         if ctx['num'] == idx:
3451             logger.info("Test: EAP-Failure")
3452             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3453
3454         idx += 1
3455         if ctx['num'] == idx:
3456             logger.info("Test: Invalid AT_SELECTED_VERSION length")
3457             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3458                                4 + 1 + 3 + 8,
3459                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3460                                EAP_SIM_AT_SELECTED_VERSION, 2, 0, 0)
3461         idx += 1
3462         if ctx['num'] == idx:
3463             logger.info("Test: EAP-Failure")
3464             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3465
3466         idx += 1
3467         if ctx['num'] == idx:
3468             logger.info("Test: Unencrypted AT_COUNTER")
3469             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3470                                4 + 1 + 3 + 4,
3471                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3472                                EAP_SIM_AT_COUNTER, 1, 0)
3473         idx += 1
3474         if ctx['num'] == idx:
3475             logger.info("Test: EAP-Failure")
3476             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3477
3478         idx += 1
3479         if ctx['num'] == idx:
3480             logger.info("Test: Unencrypted AT_COUNTER_TOO_SMALL")
3481             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3482                                4 + 1 + 3 + 4,
3483                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3484                                EAP_SIM_AT_COUNTER_TOO_SMALL, 1, 0)
3485         idx += 1
3486         if ctx['num'] == idx:
3487             logger.info("Test: EAP-Failure")
3488             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3489
3490         idx += 1
3491         if ctx['num'] == idx:
3492             logger.info("Test: Unencrypted AT_NONCE_S")
3493             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3494                                4 + 1 + 3 + 4,
3495                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3496                                EAP_SIM_AT_NONCE_S, 1, 0)
3497         idx += 1
3498         if ctx['num'] == idx:
3499             logger.info("Test: EAP-Failure")
3500             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3501
3502         idx += 1
3503         if ctx['num'] == idx:
3504             logger.info("Test: Invalid AT_CLIENT_ERROR_CODE length")
3505             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3506                                4 + 1 + 3 + 8,
3507                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3508                                EAP_SIM_AT_CLIENT_ERROR_CODE, 2, 0, 0)
3509         idx += 1
3510         if ctx['num'] == idx:
3511             logger.info("Test: EAP-Failure")
3512             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3513
3514         idx += 1
3515         if ctx['num'] == idx:
3516             logger.info("Test: Invalid AT_IV length")
3517             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3518                                4 + 1 + 3 + 4,
3519                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3520                                EAP_SIM_AT_IV, 1, 0)
3521         idx += 1
3522         if ctx['num'] == idx:
3523             logger.info("Test: EAP-Failure")
3524             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3525
3526         idx += 1
3527         if ctx['num'] == idx:
3528             logger.info("Test: Invalid AT_ENCR_DATA length")
3529             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3530                                4 + 1 + 3 + 8,
3531                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3532                                EAP_SIM_AT_ENCR_DATA, 2, 0, 0)
3533         idx += 1
3534         if ctx['num'] == idx:
3535             logger.info("Test: EAP-Failure")
3536             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3537
3538         idx += 1
3539         if ctx['num'] == idx:
3540             logger.info("Test: Unencrypted AT_NEXT_PSEUDONYM")
3541             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3542                                4 + 1 + 3 + 4,
3543                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3544                                EAP_SIM_AT_NEXT_PSEUDONYM, 1, 0)
3545         idx += 1
3546         if ctx['num'] == idx:
3547             logger.info("Test: EAP-Failure")
3548             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3549
3550         idx += 1
3551         if ctx['num'] == idx:
3552             logger.info("Test: Unencrypted AT_NEXT_REAUTH_ID")
3553             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3554                                4 + 1 + 3 + 4,
3555                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3556                                EAP_SIM_AT_NEXT_REAUTH_ID, 1, 0)
3557         idx += 1
3558         if ctx['num'] == idx:
3559             logger.info("Test: EAP-Failure")
3560             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3561
3562         idx += 1
3563         if ctx['num'] == idx:
3564             logger.info("Test: Invalid AT_RES length")
3565             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3566                                4 + 1 + 3 + 4,
3567                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3568                                EAP_SIM_AT_RES, 1, 0)
3569         idx += 1
3570         if ctx['num'] == idx:
3571             logger.info("Test: EAP-Failure")
3572             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3573
3574         idx += 1
3575         if ctx['num'] == idx:
3576             logger.info("Test: Invalid AT_RES length")
3577             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
3578                                4 + 1 + 3 + 24,
3579                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3580                                EAP_SIM_AT_RES, 6, 0xffff, 0, 0, 0, 0, 0)
3581         idx += 1
3582         if ctx['num'] == idx:
3583             logger.info("Test: EAP-Failure")
3584             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3585
3586         idx += 1
3587         if ctx['num'] == idx:
3588             logger.info("Test: Invalid AT_AUTS length")
3589             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3590                                4 + 1 + 3 + 8,
3591                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3592                                EAP_SIM_AT_AUTS, 2, 0, 0)
3593         idx += 1
3594         if ctx['num'] == idx:
3595             logger.info("Test: EAP-Failure")
3596             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3597
3598         idx += 1
3599         if ctx['num'] == idx:
3600             logger.info("Test: Invalid AT_CHECKCODE length")
3601             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3602                                4 + 1 + 3 + 8,
3603                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3604                                EAP_SIM_AT_CHECKCODE, 2, 0, 0)
3605         idx += 1
3606         if ctx['num'] == idx:
3607             logger.info("Test: EAP-Failure")
3608             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3609
3610         idx += 1
3611         if ctx['num'] == idx:
3612             logger.info("Test: Invalid AT_RESULT_IND length")
3613             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3614                                4 + 1 + 3 + 8,
3615                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3616                                EAP_SIM_AT_RESULT_IND, 2, 0, 0)
3617         idx += 1
3618         if ctx['num'] == idx:
3619             logger.info("Test: EAP-Failure")
3620             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3621
3622         idx += 1
3623         if ctx['num'] == idx:
3624             logger.info("Test: Unexpected AT_KDF_INPUT")
3625             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3626                                4 + 1 + 3 + 8,
3627                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3628                                EAP_SIM_AT_KDF_INPUT, 2, 0, 0)
3629         idx += 1
3630         if ctx['num'] == idx:
3631             logger.info("Test: EAP-Failure")
3632             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3633
3634         idx += 1
3635         if ctx['num'] == idx:
3636             logger.info("Test: Unexpected AT_KDF")
3637             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3638                                4 + 1 + 3 + 8,
3639                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3640                                EAP_SIM_AT_KDF, 2, 0, 0)
3641         idx += 1
3642         if ctx['num'] == idx:
3643             logger.info("Test: EAP-Failure")
3644             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3645
3646         idx += 1
3647         if ctx['num'] == idx:
3648             logger.info("Test: Invalid AT_BIDDING length")
3649             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3650                                4 + 1 + 3 + 8,
3651                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
3652                                EAP_SIM_AT_BIDDING, 2, 0, 0)
3653         idx += 1
3654         if ctx['num'] == idx:
3655             logger.info("Test: EAP-Failure")
3656             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3657
3658         return None
3659
3660     srv = start_radius_server(aka_handler)
3661
3662     try:
3663         hapd = start_ap(apdev[0])
3664
3665         for i in range(0, 49):
3666             eap = "AKA AKA'" if i == 11 else "AKA"
3667             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3668                            eap=eap, identity="0232010000000000",
3669                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
3670                            wait_connect=False)
3671             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3672                                    timeout=15)
3673             if ev is None:
3674                 raise Exception("Timeout on EAP start")
3675             if i in [ 0, 15 ]:
3676                 time.sleep(0.1)
3677             else:
3678                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
3679                                        timeout=10)
3680                 if ev is None:
3681                     raise Exception("Timeout on EAP failure")
3682             dev[0].request("REMOVE_NETWORK all")
3683             dev[0].dump_monitor()
3684     finally:
3685         stop_radius_server(srv)
3686
3687 def test_eap_proto_aka_prime(dev, apdev):
3688     """EAP-AKA' protocol tests"""
3689     def aka_prime_handler(ctx, req):
3690         logger.info("aka_prime_handler - RX " + req.encode("hex"))
3691         if 'num' not in ctx:
3692             ctx['num'] = 0
3693         ctx['num'] = ctx['num'] + 1
3694         if 'id' not in ctx:
3695             ctx['id'] = 1
3696         ctx['id'] = (ctx['id'] + 1) % 256
3697
3698         idx = 0
3699
3700         idx += 1
3701         if ctx['num'] == idx:
3702             logger.info("Test: Missing payload")
3703             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3704                                4 + 1,
3705                                EAP_TYPE_AKA_PRIME)
3706
3707         idx += 1
3708         if ctx['num'] == idx:
3709             logger.info("Test: Challenge with no attributes")
3710             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3711                                4 + 1 + 3,
3712                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0)
3713         idx += 1
3714         if ctx['num'] == idx:
3715             logger.info("Test: EAP-Failure")
3716             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3717
3718         idx += 1
3719         if ctx['num'] == idx:
3720             logger.info("Test: Challenge with empty AT_KDF_INPUT")
3721             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3722                                4 + 1 + 3 + 4,
3723                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3724                                EAP_SIM_AT_KDF_INPUT, 1, 0)
3725         idx += 1
3726         if ctx['num'] == idx:
3727             logger.info("Test: EAP-Failure")
3728             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3729
3730         idx += 1
3731         if ctx['num'] == idx:
3732             logger.info("Test: Challenge with AT_KDF_INPUT")
3733             return struct.pack(">BBHBBHBBHBBBB", EAP_CODE_REQUEST, ctx['id'],
3734                                4 + 1 + 3 + 8,
3735                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3736                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3737                                ord('c'), ord('d'))
3738         idx += 1
3739         if ctx['num'] == idx:
3740             logger.info("Test: EAP-Failure")
3741             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3742
3743         idx += 1
3744         if ctx['num'] == idx:
3745             logger.info("Test: Challenge with duplicated KDF")
3746             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
3747                                EAP_CODE_REQUEST, ctx['id'],
3748                                4 + 1 + 3 + 8 + 3 * 4,
3749                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3750                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3751                                ord('c'), ord('d'),
3752                                EAP_SIM_AT_KDF, 1, 1,
3753                                EAP_SIM_AT_KDF, 1, 2,
3754                                EAP_SIM_AT_KDF, 1, 1)
3755         idx += 1
3756         if ctx['num'] == idx:
3757             logger.info("Test: EAP-Failure")
3758             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3759
3760         idx += 1
3761         if ctx['num'] == idx:
3762             logger.info("Test: Challenge with multiple KDF proposals")
3763             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
3764                                EAP_CODE_REQUEST, ctx['id'],
3765                                4 + 1 + 3 + 8 + 3 * 4,
3766                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3767                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3768                                ord('c'), ord('d'),
3769                                EAP_SIM_AT_KDF, 1, 255,
3770                                EAP_SIM_AT_KDF, 1, 254,
3771                                EAP_SIM_AT_KDF, 1, 1)
3772         idx += 1
3773         if ctx['num'] == idx:
3774             logger.info("Test: Challenge with incorrect KDF selected")
3775             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
3776                                EAP_CODE_REQUEST, ctx['id'],
3777                                4 + 1 + 3 + 8 + 4 * 4,
3778                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3779                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3780                                ord('c'), ord('d'),
3781                                EAP_SIM_AT_KDF, 1, 255,
3782                                EAP_SIM_AT_KDF, 1, 255,
3783                                EAP_SIM_AT_KDF, 1, 254,
3784                                EAP_SIM_AT_KDF, 1, 1)
3785         idx += 1
3786         if ctx['num'] == idx:
3787             logger.info("Test: EAP-Failure")
3788             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3789
3790         idx += 1
3791         if ctx['num'] == idx:
3792             logger.info("Test: Challenge with multiple KDF proposals")
3793             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
3794                                EAP_CODE_REQUEST, ctx['id'],
3795                                4 + 1 + 3 + 8 + 3 * 4,
3796                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3797                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3798                                ord('c'), ord('d'),
3799                                EAP_SIM_AT_KDF, 1, 255,
3800                                EAP_SIM_AT_KDF, 1, 254,
3801                                EAP_SIM_AT_KDF, 1, 1)
3802         idx += 1
3803         if ctx['num'] == idx:
3804             logger.info("Test: Challenge with selected KDF not duplicated")
3805             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
3806                                EAP_CODE_REQUEST, ctx['id'],
3807                                4 + 1 + 3 + 8 + 3 * 4,
3808                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3809                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3810                                ord('c'), ord('d'),
3811                                EAP_SIM_AT_KDF, 1, 1,
3812                                EAP_SIM_AT_KDF, 1, 255,
3813                                EAP_SIM_AT_KDF, 1, 254)
3814         idx += 1
3815         if ctx['num'] == idx:
3816             logger.info("Test: EAP-Failure")
3817             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3818
3819         idx += 1
3820         if ctx['num'] == idx:
3821             logger.info("Test: Challenge with multiple KDF proposals")
3822             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
3823                                EAP_CODE_REQUEST, ctx['id'],
3824                                4 + 1 + 3 + 8 + 3 * 4,
3825                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3826                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3827                                ord('c'), ord('d'),
3828                                EAP_SIM_AT_KDF, 1, 255,
3829                                EAP_SIM_AT_KDF, 1, 254,
3830                                EAP_SIM_AT_KDF, 1, 1)
3831         idx += 1
3832         if ctx['num'] == idx:
3833             logger.info("Test: Challenge with selected KDF duplicated (missing MAC, RAND, AUTN)")
3834             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
3835                                EAP_CODE_REQUEST, ctx['id'],
3836                                4 + 1 + 3 + 8 + 4 * 4,
3837                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3838                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3839                                ord('c'), ord('d'),
3840                                EAP_SIM_AT_KDF, 1, 1,
3841                                EAP_SIM_AT_KDF, 1, 255,
3842                                EAP_SIM_AT_KDF, 1, 254,
3843                                EAP_SIM_AT_KDF, 1, 1)
3844         idx += 1
3845         if ctx['num'] == idx:
3846             logger.info("Test: EAP-Failure")
3847             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3848
3849         idx += 1
3850         if ctx['num'] == idx:
3851             logger.info("Test: Challenge with multiple unsupported KDF proposals")
3852             return struct.pack(">BBHBBHBBHBBBBBBHBBH",
3853                                EAP_CODE_REQUEST, ctx['id'],
3854                                4 + 1 + 3 + 8 + 2 * 4,
3855                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3856                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3857                                ord('c'), ord('d'),
3858                                EAP_SIM_AT_KDF, 1, 255,
3859                                EAP_SIM_AT_KDF, 1, 254)
3860         idx += 1
3861         if ctx['num'] == idx:
3862             logger.info("Test: EAP-Failure")
3863             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3864
3865         idx += 1
3866         if ctx['num'] == idx:
3867             logger.info("Test: Challenge with multiple KDF proposals")
3868             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
3869                                EAP_CODE_REQUEST, ctx['id'],
3870                                4 + 1 + 3 + 8 + 3 * 4,
3871                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3872                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3873                                ord('c'), ord('d'),
3874                                EAP_SIM_AT_KDF, 1, 255,
3875                                EAP_SIM_AT_KDF, 1, 254,
3876                                EAP_SIM_AT_KDF, 1, 1)
3877         idx += 1
3878         if ctx['num'] == idx:
3879             logger.info("Test: Challenge with invalid MAC, RAND, AUTN values)")
3880             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBHBBH4LBBH4LBBH4L",
3881                                EAP_CODE_REQUEST, ctx['id'],
3882                                4 + 1 + 3 + 8 + 4 * 4 + 20 + 20 + 20,
3883                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3884                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3885                                ord('c'), ord('d'),
3886                                EAP_SIM_AT_KDF, 1, 1,
3887                                EAP_SIM_AT_KDF, 1, 255,
3888                                EAP_SIM_AT_KDF, 1, 254,
3889                                EAP_SIM_AT_KDF, 1, 1,
3890                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0,
3891                                EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
3892                                EAP_SIM_AT_AUTN, 5, 0, 0, 0, 0, 0)
3893         idx += 1
3894         if ctx['num'] == idx:
3895             logger.info("Test: EAP-Failure")
3896             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3897
3898         idx += 1
3899         if ctx['num'] == idx:
3900             logger.info("Test: Challenge - AMF separation bit not set)")
3901             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
3902                                EAP_CODE_REQUEST, ctx['id'],
3903                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
3904                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3905                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3906                                ord('c'), ord('d'),
3907                                EAP_SIM_AT_KDF, 1, 1,
3908                                EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
3909                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
3910                                EAP_SIM_AT_AUTN, 5, 0, 9, 10,
3911                                0x2fda8ef7, 0xbba518cc)
3912         idx += 1
3913         if ctx['num'] == idx:
3914             logger.info("Test: EAP-Failure")
3915             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3916
3917         idx += 1
3918         if ctx['num'] == idx:
3919             logger.info("Test: Challenge - Invalid MAC")
3920             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
3921                                EAP_CODE_REQUEST, ctx['id'],
3922                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
3923                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3924                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3925                                ord('c'), ord('d'),
3926                                EAP_SIM_AT_KDF, 1, 1,
3927                                EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
3928                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
3929                                EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
3930                                0xd1f90322, 0x40514cb4)
3931         idx += 1
3932         if ctx['num'] == idx:
3933             logger.info("Test: EAP-Failure")
3934             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3935
3936         idx += 1
3937         if ctx['num'] == idx:
3938             logger.info("Test: Challenge - Valid MAC")
3939             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
3940                                EAP_CODE_REQUEST, ctx['id'],
3941                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
3942                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3943                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3944                                ord('c'), ord('d'),
3945                                EAP_SIM_AT_KDF, 1, 1,
3946                                EAP_SIM_AT_MAC, 5, 0,
3947                                0xf4a3c1d3, 0x7c901401, 0x34bd8b01, 0x6f7fa32f,
3948                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
3949                                EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
3950                                0xd1f90322, 0x40514cb4)
3951         idx += 1
3952         if ctx['num'] == idx:
3953             logger.info("Test: EAP-Failure")
3954             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3955
3956         idx += 1
3957         if ctx['num'] == idx:
3958             logger.info("Test: Invalid AT_KDF_INPUT length")
3959             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3960                                4 + 1 + 3 + 8,
3961                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
3962                                EAP_SIM_AT_KDF_INPUT, 2, 0xffff, 0)
3963         idx += 1
3964         if ctx['num'] == idx:
3965             logger.info("Test: EAP-Failure")
3966             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3967
3968         idx += 1
3969         if ctx['num'] == idx:
3970             logger.info("Test: Invalid AT_KDF length")
3971             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3972                                4 + 1 + 3 + 8,
3973                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
3974                                EAP_SIM_AT_KDF, 2, 0, 0)
3975         idx += 1
3976         if ctx['num'] == idx:
3977             logger.info("Test: EAP-Failure")
3978             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3979
3980         idx += 1
3981         if ctx['num'] == idx:
3982             logger.info("Test: Challenge with large number of KDF proposals")
3983             return struct.pack(">BBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
3984                                EAP_CODE_REQUEST, ctx['id'],
3985                                4 + 1 + 3 + 12 * 4,
3986                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3987                                EAP_SIM_AT_KDF, 1, 255,
3988                                EAP_SIM_AT_KDF, 1, 254,
3989                                EAP_SIM_AT_KDF, 1, 253,
3990                                EAP_SIM_AT_KDF, 1, 252,
3991                                EAP_SIM_AT_KDF, 1, 251,
3992                                EAP_SIM_AT_KDF, 1, 250,
3993                                EAP_SIM_AT_KDF, 1, 249,
3994                                EAP_SIM_AT_KDF, 1, 248,
3995                                EAP_SIM_AT_KDF, 1, 247,
3996                                EAP_SIM_AT_KDF, 1, 246,
3997                                EAP_SIM_AT_KDF, 1, 245,
3998                                EAP_SIM_AT_KDF, 1, 244)
3999         idx += 1
4000         if ctx['num'] == idx:
4001             logger.info("Test: EAP-Failure")
4002             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4003
4004         return None
4005
4006     srv = start_radius_server(aka_prime_handler)
4007
4008     try:
4009         hapd = start_ap(apdev[0])
4010
4011         for i in range(0, 16):
4012             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4013                            eap="AKA'", identity="6555444333222111",
4014                            password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
4015                            wait_connect=False)
4016             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
4017                                    timeout=15)
4018             if ev is None:
4019                 raise Exception("Timeout on EAP start")
4020             if i in [ 0 ]:
4021                 time.sleep(0.1)
4022             else:
4023                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
4024                                        timeout=10)
4025                 if ev is None:
4026                     raise Exception("Timeout on EAP failure")
4027             dev[0].request("REMOVE_NETWORK all")
4028             dev[0].dump_monitor()
4029     finally:
4030         stop_radius_server(srv)
4031
4032 def test_eap_proto_sim(dev, apdev):
4033     """EAP-SIM protocol tests"""
4034     def sim_handler(ctx, req):
4035         logger.info("sim_handler - RX " + req.encode("hex"))
4036         if 'num' not in ctx:
4037             ctx['num'] = 0
4038         ctx['num'] = ctx['num'] + 1
4039         if 'id' not in ctx:
4040             ctx['id'] = 1
4041         ctx['id'] = (ctx['id'] + 1) % 256
4042
4043         idx = 0
4044
4045         idx += 1
4046         if ctx['num'] == idx:
4047             logger.info("Test: Missing payload")
4048             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4049                                4 + 1,
4050                                EAP_TYPE_SIM)
4051
4052         idx += 1
4053         if ctx['num'] == idx:
4054             logger.info("Test: Unexpected AT_AUTN")
4055             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4056                                4 + 1 + 3 + 8,
4057                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4058                                EAP_SIM_AT_AUTN, 2, 0, 0)
4059         idx += 1
4060         if ctx['num'] == idx:
4061             logger.info("Test: EAP-Failure")
4062             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4063
4064         idx += 1
4065         if ctx['num'] == idx:
4066             logger.info("Test: Too short AT_VERSION_LIST")
4067             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4068                                4 + 1 + 3 + 4,
4069                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4070                                EAP_SIM_AT_VERSION_LIST, 1, 0)
4071         idx += 1
4072         if ctx['num'] == idx:
4073             logger.info("Test: EAP-Failure")
4074             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4075
4076         idx += 1
4077         if ctx['num'] == idx:
4078             logger.info("Test: AT_VERSION_LIST overflow")
4079             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4080                                4 + 1 + 3 + 4,
4081                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4082                                EAP_SIM_AT_VERSION_LIST, 1, 0xffff)
4083         idx += 1
4084         if ctx['num'] == idx:
4085             logger.info("Test: EAP-Failure")
4086             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4087
4088         idx += 1
4089         if ctx['num'] == idx:
4090             logger.info("Test: Unexpected AT_AUTS")
4091             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4092                                4 + 1 + 3 + 8,
4093                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4094                                EAP_SIM_AT_AUTS, 2, 0, 0)
4095         idx += 1
4096         if ctx['num'] == idx:
4097             logger.info("Test: EAP-Failure")
4098             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4099
4100         idx += 1
4101         if ctx['num'] == idx:
4102             logger.info("Test: Unexpected AT_CHECKCODE")
4103             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4104                                4 + 1 + 3 + 8,
4105                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4106                                EAP_SIM_AT_CHECKCODE, 2, 0, 0)
4107         idx += 1
4108         if ctx['num'] == idx:
4109             logger.info("Test: EAP-Failure")
4110             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4111
4112         idx += 1
4113         if ctx['num'] == idx:
4114             logger.info("Test: No AT_VERSION_LIST in Start")
4115             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4116                                4 + 1 + 3,
4117                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0)
4118         idx += 1
4119         if ctx['num'] == idx:
4120             logger.info("Test: EAP-Failure")
4121             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4122
4123         idx += 1
4124         if ctx['num'] == idx:
4125             logger.info("Test: No support version in AT_VERSION_LIST")
4126             return struct.pack(">BBHBBHBBH4B", EAP_CODE_REQUEST, ctx['id'],
4127                                4 + 1 + 3 + 8,
4128                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4129                                EAP_SIM_AT_VERSION_LIST, 2, 3, 2, 3, 4, 5)
4130         idx += 1
4131         if ctx['num'] == idx:
4132             logger.info("Test: EAP-Failure")
4133             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4134
4135
4136         idx += 1
4137         if ctx['num'] == idx:
4138             logger.info("Test: Identity request without ID type")
4139             return struct.pack(">BBHBBHBBH2H", EAP_CODE_REQUEST, ctx['id'],
4140                                4 + 1 + 3 + 8,
4141                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4142                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0)
4143         idx += 1
4144         if ctx['num'] == idx:
4145             logger.info("Test: Identity request ANY_ID")
4146             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4147                                4 + 1 + 3 + 8 + 4,
4148                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4149                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4150                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4151         idx += 1
4152         if ctx['num'] == idx:
4153             logger.info("Test: Identity request ANY_ID (duplicate)")
4154             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4155                                4 + 1 + 3 + 8 + 4,
4156                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4157                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4158                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4159         idx += 1
4160         if ctx['num'] == idx:
4161             logger.info("Test: EAP-Failure")
4162             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4163
4164         idx += 1
4165         if ctx['num'] == idx:
4166             logger.info("Test: Identity request ANY_ID")
4167             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4168                                4 + 1 + 3 + 8 + 4,
4169                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4170                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4171                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4172         idx += 1
4173         if ctx['num'] == idx:
4174             logger.info("Test: Identity request FULLAUTH_ID")
4175             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4176                                4 + 1 + 3 + 8 + 4,
4177                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4178                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4179                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
4180         idx += 1
4181         if ctx['num'] == idx:
4182             logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
4183             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4184                                4 + 1 + 3 + 8 + 4,
4185                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4186                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4187                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
4188         idx += 1
4189         if ctx['num'] == idx:
4190             logger.info("Test: EAP-Failure")
4191             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4192
4193         idx += 1
4194         if ctx['num'] == idx:
4195             logger.info("Test: Identity request ANY_ID")
4196             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4197                                4 + 1 + 3 + 8 + 4,
4198                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4199                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4200                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4201         idx += 1
4202         if ctx['num'] == idx:
4203             logger.info("Test: Identity request FULLAUTH_ID")
4204             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4205                                4 + 1 + 3 + 8 + 4,
4206                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4207                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4208                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
4209         idx += 1
4210         if ctx['num'] == idx:
4211             logger.info("Test: Identity request PERMANENT_ID")
4212             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4213                                4 + 1 + 3 + 8 + 4,
4214                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4215                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4216                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
4217         idx += 1
4218         if ctx['num'] == idx:
4219             logger.info("Test: Identity request PERMANENT_ID (duplicate)")
4220             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
4221                                4 + 1 + 3 + 8 + 4,
4222                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
4223                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
4224                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
4225         idx += 1
4226         if ctx['num'] == idx:
4227             logger.info("Test: EAP-Failure")
4228             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4229
4230         idx += 1
4231         if ctx['num'] == idx:
4232             logger.info("Test: No AT_MAC and AT_RAND in Challenge")
4233             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4234                                4 + 1 + 3,
4235                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0)
4236         idx += 1
4237         if ctx['num'] == idx:
4238             logger.info("Test: EAP-Failure")
4239             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4240
4241         idx += 1
4242         if ctx['num'] == idx:
4243             logger.info("Test: No AT_RAND in Challenge")
4244             return struct.pack(">BBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
4245                                4 + 1 + 3 + 20,
4246                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
4247                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
4248         idx += 1
4249         if ctx['num'] == idx:
4250             logger.info("Test: EAP-Failure")
4251             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4252
4253         idx += 1
4254         if ctx['num'] == idx:
4255             logger.info("Test: Insufficient number of challenges in Challenge")
4256             return struct.pack(">BBHBBHBBH4LBBH4L", EAP_CODE_REQUEST, ctx['id'],
4257                                4 + 1 + 3 + 20 + 20,
4258                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
4259                                EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
4260                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
4261         idx += 1
4262         if ctx['num'] == idx:
4263             logger.info("Test: EAP-Failure")
4264             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4265
4266         idx += 1
4267         if ctx['num'] == idx:
4268             logger.info("Test: Too many challenges in Challenge")
4269             return struct.pack(">BBHBBHBBH4L4L4L4LBBH4L", EAP_CODE_REQUEST,
4270                                ctx['id'],
4271                                4 + 1 + 3 + 4 + 4 * 16 + 20,
4272                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
4273                                EAP_SIM_AT_RAND, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4274                                0, 0, 0, 0, 0, 0, 0, 0,
4275                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
4276         idx += 1
4277         if ctx['num'] == idx:
4278             logger.info("Test: EAP-Failure")
4279             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4280
4281         idx += 1
4282         if ctx['num'] == idx:
4283             logger.info("Test: Same RAND multiple times in Challenge")
4284             return struct.pack(">BBHBBHBBH4L4L4LBBH4L", EAP_CODE_REQUEST,
4285                                ctx['id'],
4286                                4 + 1 + 3 + 4 + 3 * 16 + 20,
4287                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
4288                                EAP_SIM_AT_RAND, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1,
4289                                0, 0, 0, 0,
4290                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
4291         idx += 1
4292         if ctx['num'] == idx:
4293             logger.info("Test: EAP-Failure")
4294             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4295
4296         idx += 1
4297         if ctx['num'] == idx:
4298             logger.info("Test: Notification with no attributes")
4299             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4300                                4 + 1 + 3,
4301                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0)
4302         idx += 1
4303         if ctx['num'] == idx:
4304             logger.info("Test: EAP-Failure")
4305             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4306
4307         idx += 1
4308         if ctx['num'] == idx:
4309             logger.info("Test: Notification indicating success, but no MAC")
4310             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4311                                4 + 1 + 3 + 4,
4312                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
4313                                EAP_SIM_AT_NOTIFICATION, 1, 32768)
4314         idx += 1
4315         if ctx['num'] == idx:
4316             logger.info("Test: EAP-Failure")
4317             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4318
4319         idx += 1
4320         if ctx['num'] == idx:
4321             logger.info("Test: Notification indicating success, but invalid MAC value")
4322             return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
4323                                4 + 1 + 3 + 4 + 20,
4324                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
4325                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
4326                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
4327         idx += 1
4328         if ctx['num'] == idx:
4329             logger.info("Test: EAP-Failure")
4330             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4331
4332         idx += 1
4333         if ctx['num'] == idx:
4334             logger.info("Test: Notification before auth")
4335             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4336                                4 + 1 + 3 + 4,
4337                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
4338                                EAP_SIM_AT_NOTIFICATION, 1, 16384)
4339         idx += 1
4340         if ctx['num'] == idx:
4341             logger.info("Test: EAP-Failure")
4342             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4343
4344         idx += 1
4345         if ctx['num'] == idx:
4346             logger.info("Test: Notification before auth")
4347             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4348                                4 + 1 + 3 + 4,
4349                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
4350                                EAP_SIM_AT_NOTIFICATION, 1, 16385)
4351         idx += 1
4352         if ctx['num'] == idx:
4353             logger.info("Test: EAP-Failure")
4354             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4355
4356         idx += 1
4357         if ctx['num'] == idx:
4358             logger.info("Test: Notification with unrecognized non-failure")
4359             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4360                                4 + 1 + 3 + 4,
4361                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
4362                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
4363         idx += 1
4364         if ctx['num'] == idx:
4365             logger.info("Test: Notification before auth (duplicate)")
4366             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4367                                4 + 1 + 3 + 4,
4368                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
4369                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
4370         idx += 1
4371         if ctx['num'] == idx:
4372             logger.info("Test: EAP-Failure")
4373             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4374
4375         idx += 1
4376         if ctx['num'] == idx:
4377             logger.info("Test: Re-authentication (unexpected) with no attributes")
4378             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4379                                4 + 1 + 3,
4380                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION,
4381                                0)
4382         idx += 1
4383         if ctx['num'] == idx:
4384             logger.info("Test: EAP-Failure")
4385             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4386
4387         idx += 1
4388         if ctx['num'] == idx:
4389             logger.info("Test: Client Error")
4390             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4391                                4 + 1 + 3,
4392                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR, 0)
4393         idx += 1
4394         if ctx['num'] == idx:
4395             logger.info("Test: EAP-Failure")
4396             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4397
4398         idx += 1
4399         if ctx['num'] == idx:
4400             logger.info("Test: Unknown subtype")
4401             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4402                                4 + 1 + 3,
4403                                EAP_TYPE_SIM, 255, 0)
4404         idx += 1
4405         if ctx['num'] == idx:
4406             logger.info("Test: EAP-Failure")
4407             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4408
4409         return None
4410
4411     srv = start_radius_server(sim_handler)
4412
4413     try:
4414         hapd = start_ap(apdev[0])
4415
4416         for i in range(0, 25):
4417             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4418                            eap="SIM", identity="1232010000000000",
4419                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
4420                            wait_connect=False)
4421             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
4422                                    timeout=15)
4423             if ev is None:
4424                 raise Exception("Timeout on EAP start")
4425             if i in [ 0 ]:
4426                 time.sleep(0.1)
4427             else:
4428                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
4429                                        timeout=10)
4430                 if ev is None:
4431                     raise Exception("Timeout on EAP failure")
4432             dev[0].request("REMOVE_NETWORK all")
4433             dev[0].dump_monitor()
4434     finally:
4435         stop_radius_server(srv)
4436
4437 def test_eap_proto_sim_errors(dev, apdev):
4438     """EAP-SIM protocol tests (error paths)"""
4439     check_hlr_auc_gw_support()
4440     params = hostapd.wpa2_eap_params(ssid="eap-test")
4441     hapd = hostapd.add_ap(apdev[0], params)
4442
4443     with alloc_fail(dev[0], 1, "eap_sim_init"):
4444         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4445                        eap="SIM", identity="1232010000000000",
4446                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
4447                        wait_connect=False)
4448         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
4449                                timeout=15)
4450         if ev is None:
4451             raise Exception("Timeout on EAP start")
4452         dev[0].request("REMOVE_NETWORK all")
4453         dev[0].wait_disconnected()
4454
4455     with fail_test(dev[0], 1, "os_get_random;eap_sim_init"):
4456         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4457                        eap="SIM", identity="1232010000000000",
4458                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
4459                        wait_connect=False)
4460         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
4461                                timeout=15)
4462         if ev is None:
4463             raise Exception("Timeout on EAP start")
4464         dev[0].request("REMOVE_NETWORK all")
4465         dev[0].wait_disconnected()
4466
4467     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4468                    eap="SIM", identity="1232010000000000",
4469                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
4470
4471     with fail_test(dev[0], 1, "aes_128_cbc_encrypt;eap_sim_response_reauth"):
4472         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
4473         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
4474         if ev is None:
4475             raise Exception("EAP re-authentication did not start")
4476         wait_fail_trigger(dev[0], "GET_FAIL")
4477         dev[0].request("REMOVE_NETWORK all")
4478         dev[0].dump_monitor()
4479
4480     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4481                    eap="SIM", identity="1232010000000000",
4482                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
4483
4484     with fail_test(dev[0], 1, "os_get_random;eap_sim_msg_add_encr_start"):
4485         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
4486         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
4487         if ev is None:
4488             raise Exception("EAP re-authentication did not start")
4489         wait_fail_trigger(dev[0], "GET_FAIL")
4490         dev[0].request("REMOVE_NETWORK all")
4491         dev[0].dump_monitor()
4492
4493     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4494                    eap="SIM", identity="1232010000000000",
4495                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
4496
4497     with fail_test(dev[0], 1, "os_get_random;eap_sim_init_for_reauth"):
4498         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
4499         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
4500         if ev is None:
4501             raise Exception("EAP re-authentication did not start")
4502         wait_fail_trigger(dev[0], "GET_FAIL")
4503         dev[0].request("REMOVE_NETWORK all")
4504         dev[0].dump_monitor()
4505
4506     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4507                    eap="SIM", identity="1232010000000000",
4508                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
4509
4510     with alloc_fail(dev[0], 1, "eap_sim_parse_encr;eap_sim_process_reauthentication"):
4511         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
4512         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
4513         if ev is None:
4514             raise Exception("EAP re-authentication did not start")
4515         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4516         dev[0].request("REMOVE_NETWORK all")
4517         dev[0].dump_monitor()
4518
4519     tests = [ (1, "eap_sim_verify_mac;eap_sim_process_challenge"),
4520               (1, "eap_sim_parse_encr;eap_sim_process_challenge"),
4521               (1, "eap_sim_msg_init;eap_sim_response_start"),
4522               (1, "wpabuf_alloc;eap_sim_msg_init;eap_sim_response_start"),
4523               (1, "=eap_sim_learn_ids"),
4524               (2, "=eap_sim_learn_ids"),
4525               (2, "eap_sim_learn_ids"),
4526               (3, "eap_sim_learn_ids"),
4527               (1, "eap_sim_process_start"),
4528               (1, "eap_sim_getKey"),
4529               (1, "eap_sim_get_emsk"),
4530               (1, "eap_sim_get_session_id") ]
4531     for count, func in tests:
4532         with alloc_fail(dev[0], count, func):
4533             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4534                            eap="SIM", identity="1232010000000000",
4535                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
4536                            erp="1", wait_connect=False)
4537             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4538             dev[0].request("REMOVE_NETWORK all")
4539             dev[0].dump_monitor()
4540
4541     tests = [ (1, "aes_128_cbc_decrypt;eap_sim_parse_encr") ]
4542     for count, func in tests:
4543         with fail_test(dev[0], count, func):
4544             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4545                            eap="SIM", identity="1232010000000000",
4546                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
4547                            wait_connect=False)
4548             wait_fail_trigger(dev[0], "GET_FAIL")
4549             dev[0].request("REMOVE_NETWORK all")
4550             dev[0].dump_monitor()
4551
4552     params = int_eap_server_params()
4553     params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
4554     params['eap_sim_aka_result_ind'] = "1"
4555     hostapd.add_ap(apdev[1], params)
4556
4557     with alloc_fail(dev[0], 1,
4558                     "eap_sim_msg_init;eap_sim_response_notification"):
4559         dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
4560                        scan_freq="2412",
4561                        eap="SIM", identity="1232010000000000",
4562                        phase1="result_ind=1",
4563                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
4564                        wait_connect=False)
4565         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4566         dev[0].request("REMOVE_NETWORK all")
4567         dev[0].dump_monitor()
4568
4569     tests = [ "eap_sim_msg_add_encr_start;eap_sim_response_notification",
4570               "aes_128_cbc_encrypt;eap_sim_response_notification" ]
4571     for func in tests:
4572         with fail_test(dev[0], 1, func):
4573             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
4574                            scan_freq="2412",
4575                            eap="SIM", identity="1232010000000000",
4576                            phase1="result_ind=1",
4577                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
4578             dev[0].request("REAUTHENTICATE")
4579             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
4580             if ev is None:
4581                 raise Exception("EAP method not started on reauthentication")
4582             time.sleep(0.1)
4583             wait_fail_trigger(dev[0], "GET_FAIL")
4584             dev[0].request("REMOVE_NETWORK all")
4585             dev[0].dump_monitor()
4586
4587     tests = [ "eap_sim_parse_encr;eap_sim_process_notification_reauth" ]
4588     for func in tests:
4589         with alloc_fail(dev[0], 1, func):
4590             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
4591                            scan_freq="2412",
4592                            eap="SIM", identity="1232010000000000",
4593                            phase1="result_ind=1",
4594                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
4595             dev[0].request("REAUTHENTICATE")
4596             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
4597             if ev is None:
4598                 raise Exception("EAP method not started on reauthentication")
4599             time.sleep(0.1)
4600             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4601             dev[0].request("REMOVE_NETWORK all")
4602             dev[0].dump_monitor()
4603
4604 def test_eap_proto_aka_errors(dev, apdev):
4605     """EAP-AKA protocol tests (error paths)"""
4606     check_hlr_auc_gw_support()
4607     params = hostapd.wpa2_eap_params(ssid="eap-test")
4608     hapd = hostapd.add_ap(apdev[0], params)
4609
4610     with alloc_fail(dev[0], 1, "eap_aka_init"):
4611         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4612                        eap="AKA", identity="0232010000000000",
4613                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
4614                        wait_connect=False)
4615         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
4616                                timeout=15)
4617         if ev is None:
4618             raise Exception("Timeout on EAP start")
4619         dev[0].request("REMOVE_NETWORK all")
4620         dev[0].wait_disconnected()
4621
4622     tests = [ (1, "=eap_aka_learn_ids"),
4623               (2, "=eap_aka_learn_ids"),
4624               (1, "eap_sim_parse_encr;eap_aka_process_challenge"),
4625               (1, "wpabuf_dup;eap_aka_add_id_msg"),
4626               (1, "wpabuf_resize;eap_aka_add_id_msg"),
4627               (1, "eap_aka_getKey"),
4628               (1, "eap_aka_get_emsk"),
4629               (1, "eap_aka_get_session_id") ]
4630     for count, func in tests:
4631         with alloc_fail(dev[0], count, func):
4632             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4633                            eap="AKA", identity="0232010000000000",
4634                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
4635                            erp="1", wait_connect=False)
4636             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4637             dev[0].request("REMOVE_NETWORK all")
4638             dev[0].dump_monitor()
4639
4640     params = int_eap_server_params()
4641     params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
4642     params['eap_sim_aka_result_ind'] = "1"
4643     hostapd.add_ap(apdev[1], params)
4644
4645     with alloc_fail(dev[0], 1,
4646                     "eap_sim_msg_init;eap_aka_response_notification"):
4647         dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
4648                        eap="AKA", identity="0232010000000000",
4649                        phase1="result_ind=1",
4650                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
4651                        wait_connect=False)
4652         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4653         dev[0].request("REMOVE_NETWORK all")
4654         dev[0].dump_monitor()
4655
4656     tests = [ "eap_sim_msg_add_encr_start;eap_aka_response_notification",
4657               "aes_128_cbc_encrypt;eap_aka_response_notification" ]
4658     for func in tests:
4659         with fail_test(dev[0], 1, func):
4660             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
4661                            scan_freq="2412",
4662                            eap="AKA", identity="0232010000000000",
4663                            phase1="result_ind=1",
4664                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
4665             dev[0].request("REAUTHENTICATE")
4666             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
4667             if ev is None:
4668                 raise Exception("EAP method not started on reauthentication")
4669             time.sleep(0.1)
4670             wait_fail_trigger(dev[0], "GET_FAIL")
4671             dev[0].request("REMOVE_NETWORK all")
4672             dev[0].dump_monitor()
4673
4674     tests = [ "eap_sim_parse_encr;eap_aka_process_notification_reauth" ]
4675     for func in tests:
4676         with alloc_fail(dev[0], 1, func):
4677             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
4678                            scan_freq="2412",
4679                            eap="AKA", identity="0232010000000000",
4680                            phase1="result_ind=1",
4681                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
4682             dev[0].request("REAUTHENTICATE")
4683             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
4684             if ev is None:
4685                 raise Exception("EAP method not started on reauthentication")
4686             time.sleep(0.1)
4687             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4688             dev[0].request("REMOVE_NETWORK all")
4689             dev[0].dump_monitor()
4690
4691 def test_eap_proto_aka_prime_errors(dev, apdev):
4692     """EAP-AKA' protocol tests (error paths)"""
4693     check_hlr_auc_gw_support()
4694     params = hostapd.wpa2_eap_params(ssid="eap-test")
4695     hapd = hostapd.add_ap(apdev[0], params)
4696
4697     with alloc_fail(dev[0], 1, "eap_aka_init"):
4698         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4699                        eap="AKA'", identity="6555444333222111",
4700                        password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
4701                        wait_connect=False)
4702         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
4703                                timeout=15)
4704         if ev is None:
4705             raise Exception("Timeout on EAP start")
4706         dev[0].request("REMOVE_NETWORK all")
4707         dev[0].wait_disconnected()
4708
4709     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4710                    eap="AKA'", identity="6555444333222111",
4711                    password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
4712
4713     with fail_test(dev[0], 1, "aes_128_cbc_encrypt;eap_aka_response_reauth"):
4714         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
4715         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
4716         if ev is None:
4717             raise Exception("EAP re-authentication did not start")
4718         wait_fail_trigger(dev[0], "GET_FAIL")
4719         dev[0].request("REMOVE_NETWORK all")
4720         dev[0].dump_monitor()
4721
4722     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4723                    eap="AKA'", identity="6555444333222111",
4724                    password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
4725
4726     with alloc_fail(dev[0], 1, "eap_sim_parse_encr;eap_aka_process_reauthentication"):
4727         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
4728         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
4729         if ev is None:
4730             raise Exception("EAP re-authentication did not start")
4731         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4732         dev[0].request("REMOVE_NETWORK all")
4733         dev[0].dump_monitor()
4734
4735     tests = [ (1, "eap_sim_verify_mac_sha256"),
4736               (1, "=eap_aka_process_challenge") ]
4737     for count, func in tests:
4738         with alloc_fail(dev[0], count, func):
4739             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4740                            eap="AKA'", identity="6555444333222111",
4741                            password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
4742                            erp="1", wait_connect=False)
4743             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
4744             dev[0].request("REMOVE_NETWORK all")
4745             dev[0].dump_monitor()
4746
4747 def test_eap_proto_ikev2(dev, apdev):
4748     """EAP-IKEv2 protocol tests"""
4749     check_eap_capa(dev[0], "IKEV2")
4750
4751     global eap_proto_ikev2_test_done
4752     eap_proto_ikev2_test_done = False
4753
4754     def ikev2_handler(ctx, req):
4755         logger.info("ikev2_handler - RX " + req.encode("hex"))
4756         if 'num' not in ctx:
4757             ctx['num'] = 0
4758         ctx['num'] = ctx['num'] + 1
4759         if 'id' not in ctx:
4760             ctx['id'] = 1
4761         ctx['id'] = (ctx['id'] + 1) % 256
4762
4763         idx = 0
4764
4765         idx += 1
4766         if ctx['num'] == idx:
4767             logger.info("Test: Missing payload")
4768             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4769                                4 + 1,
4770                                EAP_TYPE_IKEV2)
4771
4772         idx += 1
4773         if ctx['num'] == idx:
4774             logger.info("Test: Truncated Message Length field")
4775             return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
4776                                4 + 1 + 1 + 3,
4777                                EAP_TYPE_IKEV2, 0x80, 0, 0, 0)
4778
4779         idx += 1
4780         if ctx['num'] == idx:
4781             logger.info("Test: Too short Message Length value")
4782             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
4783                                4 + 1 + 1 + 4 + 1,
4784                                EAP_TYPE_IKEV2, 0x80, 0, 1)
4785
4786         idx += 1
4787         if ctx['num'] == idx:
4788             logger.info("Test: Truncated message")
4789             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
4790                                4 + 1 + 1 + 4,
4791                                EAP_TYPE_IKEV2, 0x80, 1)
4792
4793         idx += 1
4794         if ctx['num'] == idx:
4795             logger.info("Test: Truncated message(2)")
4796             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
4797                                4 + 1 + 1 + 4,
4798                                EAP_TYPE_IKEV2, 0x80, 0xffffffff)
4799
4800         idx += 1
4801         if ctx['num'] == idx:
4802             logger.info("Test: Truncated message(3)")
4803             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
4804                                4 + 1 + 1 + 4,
4805                                EAP_TYPE_IKEV2, 0xc0, 0xffffffff)
4806
4807         idx += 1
4808         if ctx['num'] == idx:
4809             logger.info("Test: Truncated message(4)")
4810             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
4811                                4 + 1 + 1 + 4,
4812                                EAP_TYPE_IKEV2, 0xc0, 10000000)
4813
4814         idx += 1
4815         if ctx['num'] == idx:
4816             logger.info("Test: Too long fragments (first fragment)")
4817             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
4818                                4 + 1 + 1 + 4 + 1,
4819                                EAP_TYPE_IKEV2, 0xc0, 2, 1)
4820
4821         idx += 1
4822         if ctx['num'] == idx:
4823             logger.info("Test: Too long fragments (second fragment)")
4824             return struct.pack(">BBHBB2B", EAP_CODE_REQUEST, ctx['id'],
4825                                4 + 1 + 1 + 2,
4826                                EAP_TYPE_IKEV2, 0x00, 2, 3)
4827
4828         idx += 1
4829         if ctx['num'] == idx:
4830             logger.info("Test: No Message Length field in first fragment")
4831             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
4832                                4 + 1 + 1 + 1,
4833                                EAP_TYPE_IKEV2, 0x40, 1)
4834
4835         idx += 1
4836         if ctx['num'] == idx:
4837             logger.info("Test: ICV before keys")
4838             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
4839                                4 + 1 + 1,
4840                                EAP_TYPE_IKEV2, 0x20)
4841
4842         idx += 1
4843         if ctx['num'] == idx:
4844             logger.info("Test: Unsupported IKEv2 header version")
4845             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4846                                4 + 1 + 1 + 28,
4847                                EAP_TYPE_IKEV2, 0x00,
4848                                0, 0, 0, 0,
4849                                0, 0, 0, 0, 0, 0)
4850
4851         idx += 1
4852         if ctx['num'] == idx:
4853             logger.info("Test: Incorrect IKEv2 header Length")
4854             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4855                                4 + 1 + 1 + 28,
4856                                EAP_TYPE_IKEV2, 0x00,
4857                                0, 0, 0, 0,
4858                                0, 0x20, 0, 0, 0, 0)
4859
4860         idx += 1
4861         if ctx['num'] == idx:
4862             logger.info("Test: Unexpected IKEv2 Exchange Type in SA_INIT state")
4863             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4864                                4 + 1 + 1 + 28,
4865                                EAP_TYPE_IKEV2, 0x00,
4866                                0, 0, 0, 0,
4867                                0, 0x20, 0, 0, 0, 28)
4868
4869         idx += 1
4870         if ctx['num'] == idx:
4871             logger.info("Test: Unexpected IKEv2 Message ID in SA_INIT state")
4872             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4873                                4 + 1 + 1 + 28,
4874                                EAP_TYPE_IKEV2, 0x00,
4875                                0, 0, 0, 0,
4876                                0, 0x20, 34, 0, 1, 28)
4877
4878         idx += 1
4879         if ctx['num'] == idx:
4880             logger.info("Test: Unexpected IKEv2 Flags value")
4881             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4882                                4 + 1 + 1 + 28,
4883                                EAP_TYPE_IKEV2, 0x00,
4884                                0, 0, 0, 0,
4885                                0, 0x20, 34, 0, 0, 28)
4886
4887         idx += 1
4888         if ctx['num'] == idx:
4889             logger.info("Test: Unexpected IKEv2 Flags value(2)")
4890             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4891                                4 + 1 + 1 + 28,
4892                                EAP_TYPE_IKEV2, 0x00,
4893                                0, 0, 0, 0,
4894                                0, 0x20, 34, 0x20, 0, 28)
4895
4896         idx += 1
4897         if ctx['num'] == idx:
4898             logger.info("Test: No SAi1 in SA_INIT")
4899             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
4900                                4 + 1 + 1 + 28,
4901                                EAP_TYPE_IKEV2, 0x00,
4902                                0, 0, 0, 0,
4903                                0, 0x20, 34, 0x08, 0, 28)
4904
4905         def build_ike(id, next=0, exch_type=34, flags=0x00, ike=''):
4906             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, id,
4907                                4 + 1 + 1 + 28 + len(ike),
4908                                EAP_TYPE_IKEV2, flags,
4909                                0, 0, 0, 0,
4910                                next, 0x20, exch_type, 0x08, 0,
4911                                28 + len(ike)) + ike
4912
4913         idx += 1
4914         if ctx['num'] == idx:
4915             logger.info("Test: Unexpected extra data after payloads")
4916             return build_ike(ctx['id'], ike=struct.pack(">B", 1))
4917
4918         idx += 1
4919         if ctx['num'] == idx:
4920             logger.info("Test: Truncated payload header")
4921             return build_ike(ctx['id'], next=128, ike=struct.pack(">B", 1))
4922
4923         idx += 1
4924         if ctx['num'] == idx:
4925             logger.info("Test: Too small payload header length")
4926             ike = struct.pack(">BBH", 0, 0, 3)
4927             return build_ike(ctx['id'], next=128, ike=ike)
4928
4929         idx += 1
4930         if ctx['num'] == idx:
4931             logger.info("Test: Too large payload header length")
4932             ike = struct.pack(">BBH", 0, 0, 5)
4933             return build_ike(ctx['id'], next=128, ike=ike)
4934
4935         idx += 1
4936         if ctx['num'] == idx:
4937             logger.info("Test: Unsupported payload (non-critical and critical)")
4938             ike = struct.pack(">BBHBBH", 129, 0, 4, 0, 0x01, 4)
4939             return build_ike(ctx['id'], next=128, ike=ike)
4940
4941         idx += 1
4942         if ctx['num'] == idx:
4943             logger.info("Test: Certificate and empty SAi1")
4944             ike = struct.pack(">BBHBBH", 33, 0, 4, 0, 0, 4)
4945             return build_ike(ctx['id'], next=37, ike=ike)
4946
4947         idx += 1
4948         if ctx['num'] == idx:
4949             logger.info("Test: Too short proposal")
4950             ike = struct.pack(">BBHBBHBBB", 0, 0, 4 + 7,
4951                               0, 0, 7, 0, 0, 0)
4952             return build_ike(ctx['id'], next=33, ike=ike)
4953
4954         idx += 1
4955         if ctx['num'] == idx:
4956             logger.info("Test: Too small proposal length in SAi1")
4957             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
4958                               0, 0, 7, 0, 0, 0, 0)
4959             return build_ike(ctx['id'], next=33, ike=ike)
4960
4961         idx += 1
4962         if ctx['num'] == idx:
4963             logger.info("Test: Too large proposal length in SAi1")
4964             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
4965                               0, 0, 9, 0, 0, 0, 0)
4966             return build_ike(ctx['id'], next=33, ike=ike)
4967
4968         idx += 1
4969         if ctx['num'] == idx:
4970             logger.info("Test: Unexpected proposal type in SAi1")
4971             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
4972                               1, 0, 8, 0, 0, 0, 0)
4973             return build_ike(ctx['id'], next=33, ike=ike)
4974
4975         idx += 1
4976         if ctx['num'] == idx:
4977             logger.info("Test: Unexpected Protocol ID in SAi1")
4978             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
4979                               0, 0, 8, 0, 0, 0, 0)
4980             return build_ike(ctx['id'], next=33, ike=ike)
4981
4982         idx += 1
4983         if ctx['num'] == idx:
4984             logger.info("Test: Unexpected proposal number in SAi1")
4985             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
4986                               0, 0, 8, 0, 1, 0, 0)
4987             return build_ike(ctx['id'], next=33, ike=ike)
4988
4989         idx += 1
4990         if ctx['num'] == idx:
4991             logger.info("Test: Not enough room for SPI in SAi1")
4992             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
4993                               0, 0, 8, 1, 1, 1, 0)
4994             return build_ike(ctx['id'], next=33, ike=ike)
4995
4996         idx += 1
4997         if ctx['num'] == idx:
4998             logger.info("Test: Unexpected SPI in SAi1")
4999             ike = struct.pack(">BBHBBHBBBBB", 0, 0, 4 + 9,
5000                               0, 0, 9, 1, 1, 1, 0, 1)
5001             return build_ike(ctx['id'], next=33, ike=ike)
5002
5003         idx += 1
5004         if ctx['num'] == idx:
5005             logger.info("Test: No transforms in SAi1")
5006             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
5007                               0, 0, 8, 1, 1, 0, 0)
5008             return build_ike(ctx['id'], next=33, ike=ike)
5009
5010         idx += 1
5011         if ctx['num'] == idx:
5012             logger.info("Test: Too short transform in SAi1")
5013             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
5014                               0, 0, 8, 1, 1, 0, 1)
5015             return build_ike(ctx['id'], next=33, ike=ike)
5016
5017         idx += 1
5018         if ctx['num'] == idx:
5019             logger.info("Test: Too small transform length in SAi1")
5020             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
5021                               0, 0, 8 + 8, 1, 1, 0, 1,
5022                               0, 0, 7, 0, 0, 0)
5023             return build_ike(ctx['id'], next=33, ike=ike)
5024
5025         idx += 1
5026         if ctx['num'] == idx:
5027             logger.info("Test: Too large transform length in SAi1")
5028             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
5029                               0, 0, 8 + 8, 1, 1, 0, 1,
5030                               0, 0, 9, 0, 0, 0)
5031             return build_ike(ctx['id'], next=33, ike=ike)
5032
5033         idx += 1
5034         if ctx['num'] == idx:
5035             logger.info("Test: Unexpected Transform type in SAi1")
5036             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
5037                               0, 0, 8 + 8, 1, 1, 0, 1,
5038                               1, 0, 8, 0, 0, 0)
5039             return build_ike(ctx['id'], next=33, ike=ike)
5040
5041         idx += 1
5042         if ctx['num'] == idx:
5043             logger.info("Test: No transform attributes in SAi1")
5044             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
5045                               0, 0, 8 + 8, 1, 1, 0, 1,
5046                               0, 0, 8, 0, 0, 0)
5047             return build_ike(ctx['id'], next=33, ike=ike)
5048
5049         idx += 1
5050         if ctx['num'] == idx:
5051             logger.info("Test: No transform attr for AES and unexpected data after transforms in SAi1")
5052             tlen1 = 8 + 3
5053             tlen2 = 8 + 4
5054             tlen3 = 8 + 4
5055             tlen = tlen1 + tlen2 + tlen3
5056             ike = struct.pack(">BBHBBHBBBBBBHBBH3BBBHBBHHHBBHBBHHHB",
5057                               0, 0, 4 + 8 + tlen + 1,
5058                               0, 0, 8 + tlen + 1, 1, 1, 0, 3,
5059                               3, 0, tlen1, 1, 0, 12, 1, 2, 3,
5060                               3, 0, tlen2, 1, 0, 12, 0, 128,
5061                               0, 0, tlen3, 1, 0, 12, 0x8000 | 14, 127,
5062                               1)
5063             return build_ike(ctx['id'], next=33, ike=ike)
5064
5065         def build_sa(next=0):
5066             tlen = 5 * 8
5067             return struct.pack(">BBHBBHBBBBBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
5068                                next, 0, 4 + 8 + tlen,
5069                                0, 0, 8 + tlen, 1, 1, 0, 5,
5070                                3, 0, 8, 1, 0, 3,
5071                                3, 0, 8, 2, 0, 1,
5072                                3, 0, 8, 3, 0, 1,
5073                                3, 0, 8, 4, 0, 5,
5074                                0, 0, 8, 241, 0, 0)
5075
5076         idx += 1
5077         if ctx['num'] == idx:
5078             logger.info("Test: Valid proposal, but no KEi in SAi1")
5079             ike = build_sa()
5080             return build_ike(ctx['id'], next=33, ike=ike)
5081
5082         idx += 1
5083         if ctx['num'] == idx:
5084             logger.info("Test: Empty KEi in SAi1")
5085             ike = build_sa(next=34) + struct.pack(">BBH", 0, 0, 4)
5086             return build_ike(ctx['id'], next=33, ike=ike)
5087
5088         idx += 1
5089         if ctx['num'] == idx:
5090             logger.info("Test: Mismatch in DH Group in SAi1")
5091             ike = build_sa(next=34)
5092             ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 12345, 0)
5093             ike += 96*'\x00'
5094             return build_ike(ctx['id'], next=33, ike=ike)
5095         idx += 1
5096         if ctx['num'] == idx:
5097             logger.info("Test: EAP-Failure")
5098             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5099
5100         idx += 1
5101         if ctx['num'] == idx:
5102             logger.info("Test: Invalid DH public value length in SAi1")
5103             ike = build_sa(next=34)
5104             ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 5, 0)
5105             ike += 96*'\x00'
5106             return build_ike(ctx['id'], next=33, ike=ike)
5107
5108         def build_ke(next=0):
5109             ke = struct.pack(">BBHHH", next, 0, 4 + 4 + 192, 5, 0)
5110             ke += 192*'\x00'
5111             return ke
5112
5113         idx += 1
5114         if ctx['num'] == idx:
5115             logger.info("Test: Valid proposal and KEi, but no Ni in SAi1")
5116             ike = build_sa(next=34)
5117             ike += build_ke()
5118             return build_ike(ctx['id'], next=33, ike=ike)
5119
5120         idx += 1
5121         if ctx['num'] == idx:
5122             logger.info("Test: Too short Ni in SAi1")
5123             ike = build_sa(next=34)
5124             ike += build_ke(next=40)
5125             ike += struct.pack(">BBH", 0, 0, 4)
5126             return build_ike(ctx['id'], next=33, ike=ike)
5127
5128         idx += 1
5129         if ctx['num'] == idx:
5130             logger.info("Test: Too long Ni in SAi1")
5131             ike = build_sa(next=34)
5132             ike += build_ke(next=40)
5133             ike += struct.pack(">BBH", 0, 0, 4 + 257) + 257*'\x00'
5134             return build_ike(ctx['id'], next=33, ike=ike)
5135
5136         def build_ni(next=0):
5137             return struct.pack(">BBH", next, 0, 4 + 256) + 256*'\x00'
5138
5139         def build_sai1(id):
5140             ike = build_sa(next=34)
5141             ike += build_ke(next=40)
5142             ike += build_ni()
5143             return build_ike(ctx['id'], next=33, ike=ike)
5144
5145         idx += 1
5146         if ctx['num'] == idx:
5147             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
5148             return build_sai1(ctx['id'])
5149         idx += 1
5150         if ctx['num'] == idx:
5151             logger.info("Test: EAP-Failure")
5152             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5153
5154         idx += 1
5155         if ctx['num'] == idx:
5156             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
5157             return build_sai1(ctx['id'])
5158         idx += 1
5159         if ctx['num'] == idx:
5160             logger.info("Test: No integrity checksum")
5161             ike = ''
5162             return build_ike(ctx['id'], next=37, ike=ike)
5163
5164         idx += 1
5165         if ctx['num'] == idx:
5166             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
5167             return build_sai1(ctx['id'])
5168         idx += 1
5169         if ctx['num'] == idx:
5170             logger.info("Test: Truncated integrity checksum")
5171             return struct.pack(">BBHBB",
5172                                EAP_CODE_REQUEST, ctx['id'],
5173                                4 + 1 + 1,
5174                                EAP_TYPE_IKEV2, 0x20)
5175
5176         idx += 1
5177         if ctx['num'] == idx:
5178             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
5179             return build_sai1(ctx['id'])
5180         idx += 1
5181         if ctx['num'] == idx:
5182             logger.info("Test: Invalid integrity checksum")
5183             ike = ''
5184             return build_ike(ctx['id'], next=37, flags=0x20, ike=ike)
5185
5186         idx += 1
5187         if ctx['num'] == idx:
5188             logger.info("No more test responses available - test case completed")
5189             global eap_proto_ikev2_test_done
5190             eap_proto_ikev2_test_done = True
5191             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
5192                                4 + 1,
5193                                EAP_TYPE_IKEV2)
5194         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5195
5196     srv = start_radius_server(ikev2_handler)
5197
5198     try:
5199         hapd = start_ap(apdev[0])
5200
5201         i = 0
5202         while not eap_proto_ikev2_test_done:
5203             i += 1
5204             logger.info("Running connection iteration %d" % i)
5205             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5206                            eap="IKEV2", identity="user",
5207                            password="password",
5208                            wait_connect=False)
5209             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
5210             if ev is None:
5211                 raise Exception("Timeout on EAP start")
5212             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5213                                    timeout=15)
5214             if ev is None:
5215                 raise Exception("Timeout on EAP method start")
5216             if i in [ 41, 46 ]:
5217                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
5218                                        timeout=10)
5219                 if ev is None:
5220                     raise Exception("Timeout on EAP failure")
5221             else:
5222                 time.sleep(0.05)
5223             dev[0].request("REMOVE_NETWORK all")
5224             dev[0].wait_disconnected()
5225             dev[0].dump_monitor()
5226             dev[1].dump_monitor()
5227             dev[2].dump_monitor()
5228     finally:
5229         stop_radius_server(srv)
5230
5231 def NtPasswordHash(password):
5232     pw = password.encode('utf_16_le')
5233     return hashlib.new('md4', pw).digest()
5234
5235 def HashNtPasswordHash(password_hash):
5236     return hashlib.new('md4', password_hash).digest()
5237
5238 def ChallengeHash(peer_challenge, auth_challenge, username):
5239     data = peer_challenge + auth_challenge + username
5240     return hashlib.sha1(data).digest()[0:8]
5241
5242 def GenerateAuthenticatorResponse(password, nt_response, peer_challenge,
5243                                   auth_challenge, username):
5244     magic1 = binascii.unhexlify("4D616769632073657276657220746F20636C69656E74207369676E696E6720636F6E7374616E74")
5245     magic2 = binascii.unhexlify("50616420746F206D616B6520697420646F206D6F7265207468616E206F6E6520697465726174696F6E")
5246
5247     password_hash = NtPasswordHash(password)
5248     password_hash_hash = HashNtPasswordHash(password_hash)
5249     data = password_hash_hash + nt_response + magic1
5250     digest = hashlib.sha1(data).digest()
5251
5252     challenge = ChallengeHash(peer_challenge, auth_challenge, username)
5253
5254     data = digest + challenge + magic2
5255     resp = hashlib.sha1(data).digest()
5256     return resp
5257
5258 def test_eap_proto_ikev2_errors(dev, apdev):
5259     """EAP-IKEv2 local error cases"""
5260     check_eap_capa(dev[0], "IKEV2")
5261     params = hostapd.wpa2_eap_params(ssid="eap-test")
5262     hapd = hostapd.add_ap(apdev[0], params)
5263
5264     for i in range(1, 5):
5265         with alloc_fail(dev[0], i, "eap_ikev2_init"):
5266             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5267                            eap="IKEV2", identity="ikev2 user",
5268                            password="ike password",
5269                            wait_connect=False)
5270             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
5271                                    timeout=15)
5272             if ev is None:
5273                 raise Exception("Timeout on EAP start")
5274             dev[0].request("REMOVE_NETWORK all")
5275             dev[0].wait_disconnected()
5276
5277     tests = [ (1, "ikev2_encr_encrypt"),
5278               (1, "ikev2_encr_decrypt"),
5279               (1, "ikev2_derive_auth_data"),
5280               (2, "ikev2_derive_auth_data"),
5281               (1, "=ikev2_decrypt_payload"),
5282               (1, "ikev2_encr_decrypt;ikev2_decrypt_payload"),
5283               (1, "ikev2_encr_encrypt;ikev2_build_encrypted"),
5284               (1, "ikev2_derive_sk_keys"),
5285               (2, "ikev2_derive_sk_keys"),
5286               (3, "ikev2_derive_sk_keys"),
5287               (4, "ikev2_derive_sk_keys"),
5288               (5, "ikev2_derive_sk_keys"),
5289               (6, "ikev2_derive_sk_keys"),
5290               (7, "ikev2_derive_sk_keys"),
5291               (8, "ikev2_derive_sk_keys"),
5292               (1, "eap_ikev2_derive_keymat;eap_ikev2_peer_keymat"),
5293               (1, "eap_msg_alloc;eap_ikev2_build_msg"),
5294               (1, "eap_ikev2_getKey"),
5295               (1, "eap_ikev2_get_emsk"),
5296               (1, "eap_ikev2_get_session_id"),
5297               (1, "=ikev2_derive_keys"),
5298               (2, "=ikev2_derive_keys"),
5299               (1, "wpabuf_alloc;ikev2_process_kei"),
5300               (1, "=ikev2_process_idi"),
5301               (1, "ikev2_derive_auth_data;ikev2_build_auth"),
5302               (1, "wpabuf_alloc;ikev2_build_sa_init"),
5303               (2, "wpabuf_alloc;ikev2_build_sa_init"),
5304               (3, "wpabuf_alloc;ikev2_build_sa_init"),
5305               (4, "wpabuf_alloc;ikev2_build_sa_init"),
5306               (5, "wpabuf_alloc;ikev2_build_sa_init"),
5307               (6, "wpabuf_alloc;ikev2_build_sa_init"),
5308               (1, "wpabuf_alloc;ikev2_build_sa_auth"),
5309               (2, "wpabuf_alloc;ikev2_build_sa_auth"),
5310               (1, "ikev2_build_auth;ikev2_build_sa_auth") ]
5311     for count, func in tests:
5312         with alloc_fail(dev[0], count, func):
5313             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5314                            eap="IKEV2", identity="ikev2 user",
5315                            password="ike password", erp="1", wait_connect=False)
5316             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5317                                    timeout=15)
5318             if ev is None:
5319                 raise Exception("Timeout on EAP start")
5320             ok = False
5321             for j in range(10):
5322                 state = dev[0].request('GET_ALLOC_FAIL')
5323                 if state.startswith('0:'):
5324                     ok = True
5325                     break
5326                 time.sleep(0.1)
5327             if not ok:
5328                 raise Exception("No allocation failure seen for %d:%s" % (count, func))
5329             dev[0].request("REMOVE_NETWORK all")
5330             dev[0].wait_disconnected()
5331
5332     tests = [ (1, "wpabuf_alloc;ikev2_build_notify"),
5333               (2, "wpabuf_alloc;ikev2_build_notify"),
5334               (1, "ikev2_build_encrypted;ikev2_build_notify") ]
5335     for count, func in tests:
5336         with alloc_fail(dev[0], count, func):
5337             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5338                            eap="IKEV2", identity="ikev2 user",
5339                            password="wrong password", erp="1",
5340                            wait_connect=False)
5341             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5342                                    timeout=15)
5343             if ev is None:
5344                 raise Exception("Timeout on EAP start")
5345             ok = False
5346             for j in range(10):
5347                 state = dev[0].request('GET_ALLOC_FAIL')
5348                 if state.startswith('0:'):
5349                     ok = True
5350                     break
5351                 time.sleep(0.1)
5352             if not ok:
5353                 raise Exception("No allocation failure seen for %d:%s" % (count, func))
5354             dev[0].request("REMOVE_NETWORK all")
5355             dev[0].wait_disconnected()
5356
5357     tests = [ (1, "ikev2_integ_hash"),
5358               (1, "ikev2_integ_hash;ikev2_decrypt_payload"),
5359               (1, "os_get_random;ikev2_build_encrypted"),
5360               (1, "ikev2_prf_plus;ikev2_derive_sk_keys"),
5361               (1, "eap_ikev2_derive_keymat;eap_ikev2_peer_keymat"),
5362               (1, "os_get_random;ikev2_build_sa_init"),
5363               (2, "os_get_random;ikev2_build_sa_init"),
5364               (1, "ikev2_integ_hash;eap_ikev2_validate_icv"),
5365               (1, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_keys"),
5366               (1, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data"),
5367               (2, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data"),
5368               (3, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data") ]
5369     for count, func in tests:
5370         with fail_test(dev[0], count, func):
5371             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5372                            eap="IKEV2", identity="ikev2 user",
5373                            password="ike password", wait_connect=False)
5374             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5375                                    timeout=15)
5376             if ev is None:
5377                 raise Exception("Timeout on EAP start")
5378             ok = False
5379             for j in range(10):
5380                 state = dev[0].request('GET_FAIL')
5381                 if state.startswith('0:'):
5382                     ok = True
5383                     break
5384                 time.sleep(0.1)
5385             if not ok:
5386                 raise Exception("No failure seen for %d:%s" % (count, func))
5387             dev[0].request("REMOVE_NETWORK all")
5388             dev[0].wait_disconnected()
5389
5390     params = { "ssid": "eap-test2", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
5391                "rsn_pairwise": "CCMP", "ieee8021x": "1",
5392                "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
5393                "fragment_size": "50" }
5394     hostapd.add_ap(apdev[1], params)
5395
5396     tests = [ (1, "eap_ikev2_build_frag_ack"),
5397               (1, "wpabuf_alloc;eap_ikev2_process_fragment") ]
5398     for count, func in tests:
5399         with alloc_fail(dev[0], count, func):
5400             dev[0].connect("eap-test2", key_mgmt="WPA-EAP", scan_freq="2412",
5401                            eap="IKEV2", identity="ikev2 user",
5402                            password="ike password", erp="1", wait_connect=False)
5403             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5404                                    timeout=15)
5405             if ev is None:
5406                 raise Exception("Timeout on EAP start")
5407             ok = False
5408             for j in range(10):
5409                 state = dev[0].request('GET_ALLOC_FAIL')
5410                 if state.startswith('0:'):
5411                     ok = True
5412                     break
5413                 time.sleep(0.1)
5414             if not ok:
5415                 raise Exception("No allocation failure seen for %d:%s" % (count, func))
5416             dev[0].request("REMOVE_NETWORK all")
5417             dev[0].wait_disconnected()
5418
5419 def test_eap_proto_mschapv2(dev, apdev):
5420     """EAP-MSCHAPv2 protocol tests"""
5421     check_eap_capa(dev[0], "MSCHAPV2")
5422
5423     def mschapv2_handler(ctx, req):
5424         logger.info("mschapv2_handler - RX " + req.encode("hex"))
5425         if 'num' not in ctx:
5426             ctx['num'] = 0
5427         ctx['num'] = ctx['num'] + 1
5428         if 'id' not in ctx:
5429             ctx['id'] = 1
5430         ctx['id'] = (ctx['id'] + 1) % 256
5431         idx = 0
5432
5433         idx += 1
5434         if ctx['num'] == idx:
5435             logger.info("Test: Missing payload")
5436             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
5437                                4 + 1,
5438                                EAP_TYPE_MSCHAPV2)
5439
5440         idx += 1
5441         if ctx['num'] == idx:
5442             logger.info("Test: Unknown MSCHAPv2 op_code")
5443             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5444                                4 + 1 + 4 + 1,
5445                                EAP_TYPE_MSCHAPV2,
5446                                0, 0, 5, 0)
5447
5448         idx += 1
5449         if ctx['num'] == idx:
5450             logger.info("Test: Invalid ms_len and unknown MSCHAPv2 op_code")
5451             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5452                                4 + 1 + 4 + 1,
5453                                EAP_TYPE_MSCHAPV2,
5454                                255, 0, 0, 0)
5455
5456         idx += 1
5457         if ctx['num'] == idx:
5458             logger.info("Test: Success before challenge")
5459             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5460                                4 + 1 + 4 + 1,
5461                                EAP_TYPE_MSCHAPV2,
5462                                3, 0, 5, 0)
5463
5464         idx += 1
5465         if ctx['num'] == idx:
5466             logger.info("Test: Failure before challenge - required challenge field not present")
5467             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5468                                4 + 1 + 4 + 1,
5469                                EAP_TYPE_MSCHAPV2,
5470                                4, 0, 5, 0)
5471         idx += 1
5472         if ctx['num'] == idx:
5473             logger.info("Test: Failure")
5474             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5475
5476         idx += 1
5477         if ctx['num'] == idx:
5478             logger.info("Test: Failure before challenge - invalid failure challenge len")
5479             payload = 'C=12'
5480             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5481                                4 + 1 + 4 + len(payload),
5482                                EAP_TYPE_MSCHAPV2,
5483                                4, 0, 4 + len(payload)) + payload
5484         idx += 1
5485         if ctx['num'] == idx:
5486             logger.info("Test: Failure")
5487             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5488
5489         idx += 1
5490         if ctx['num'] == idx:
5491             logger.info("Test: Failure before challenge - invalid failure challenge len")
5492             payload = 'C=12 V=3'
5493             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5494                                4 + 1 + 4 + len(payload),
5495                                EAP_TYPE_MSCHAPV2,
5496                                4, 0, 4 + len(payload)) + payload
5497         idx += 1
5498         if ctx['num'] == idx:
5499             logger.info("Test: Failure")
5500             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5501
5502         idx += 1
5503         if ctx['num'] == idx:
5504             logger.info("Test: Failure before challenge - invalid failure challenge")
5505             payload = 'C=00112233445566778899aabbccddeefQ '
5506             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5507                                4 + 1 + 4 + len(payload),
5508                                EAP_TYPE_MSCHAPV2,
5509                                4, 0, 4 + len(payload)) + payload
5510         idx += 1
5511         if ctx['num'] == idx:
5512             logger.info("Test: Failure")
5513             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5514
5515         idx += 1
5516         if ctx['num'] == idx:
5517             logger.info("Test: Failure before challenge - password expired")
5518             payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
5519             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5520                                4 + 1 + 4 + len(payload),
5521                                EAP_TYPE_MSCHAPV2,
5522                                4, 0, 4 + len(payload)) + payload
5523         idx += 1
5524         if ctx['num'] == idx:
5525             logger.info("Test: Success after password change")
5526             payload = "S=1122334455667788990011223344556677889900"
5527             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5528                                4 + 1 + 4 + len(payload),
5529                                EAP_TYPE_MSCHAPV2,
5530                                3, 0, 4 + len(payload)) + payload
5531
5532         idx += 1
5533         if ctx['num'] == idx:
5534             logger.info("Test: Invalid challenge length")
5535             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5536                                4 + 1 + 4 + 1,
5537                                EAP_TYPE_MSCHAPV2,
5538                                1, 0, 4 + 1, 0)
5539
5540         idx += 1
5541         if ctx['num'] == idx:
5542             logger.info("Test: Too short challenge packet")
5543             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5544                                4 + 1 + 4 + 1,
5545                                EAP_TYPE_MSCHAPV2,
5546                                1, 0, 4 + 1, 16)
5547
5548         idx += 1
5549         if ctx['num'] == idx:
5550             logger.info("Test: Challenge")
5551             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5552                                4 + 1 + 4 + 1 + 16 + 6,
5553                                EAP_TYPE_MSCHAPV2,
5554                                1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
5555         idx += 1
5556         if ctx['num'] == idx:
5557             logger.info("Test: Failure - password expired")
5558             payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
5559             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5560                                4 + 1 + 4 + len(payload),
5561                                EAP_TYPE_MSCHAPV2,
5562                                4, 0, 4 + len(payload)) + payload
5563         idx += 1
5564         if ctx['num'] == idx:
5565             logger.info("Test: Success after password change")
5566             if len(req) != 591:
5567                 logger.info("Unexpected Change-Password packet length: %s" % len(req))
5568                 return None
5569             data = req[9:]
5570             enc_pw = data[0:516]
5571             data = data[516:]
5572             enc_hash = data[0:16]
5573             data = data[16:]
5574             peer_challenge = data[0:16]
5575             data = data[16:]
5576             # Reserved
5577             data = data[8:]
5578             nt_response = data[0:24]
5579             data = data[24:]
5580             flags = data
5581             logger.info("enc_hash: " + enc_hash.encode("hex"))
5582             logger.info("peer_challenge: " + peer_challenge.encode("hex"))
5583             logger.info("nt_response: " + nt_response.encode("hex"))
5584             logger.info("flags: " + flags.encode("hex"))
5585
5586             auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
5587             logger.info("auth_challenge: " + auth_challenge.encode("hex"))
5588  
5589             auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
5590                                                       peer_challenge,
5591                                                       auth_challenge, "user")
5592             payload = "S=" + auth_resp.encode('hex').upper()
5593             logger.info("Success message payload: " + payload)
5594             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5595                                4 + 1 + 4 + len(payload),
5596                                EAP_TYPE_MSCHAPV2,
5597                                3, 0, 4 + len(payload)) + payload
5598         idx += 1
5599         if ctx['num'] == idx:
5600             logger.info("Test: EAP-Success")
5601             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
5602
5603         idx += 1
5604         if ctx['num'] == idx:
5605             logger.info("Test: Failure - password expired")
5606             payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
5607             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5608                                4 + 1 + 4 + len(payload),
5609                                EAP_TYPE_MSCHAPV2,
5610                                4, 0, 4 + len(payload)) + payload
5611         idx += 1
5612         if ctx['num'] == idx:
5613             logger.info("Test: Success after password change")
5614             if len(req) != 591:
5615                 logger.info("Unexpected Change-Password packet length: %s" % len(req))
5616                 return None
5617             data = req[9:]
5618             enc_pw = data[0:516]
5619             data = data[516:]
5620             enc_hash = data[0:16]
5621             data = data[16:]
5622             peer_challenge = data[0:16]
5623             data = data[16:]
5624             # Reserved
5625             data = data[8:]
5626             nt_response = data[0:24]
5627             data = data[24:]
5628             flags = data
5629             logger.info("enc_hash: " + enc_hash.encode("hex"))
5630             logger.info("peer_challenge: " + peer_challenge.encode("hex"))
5631             logger.info("nt_response: " + nt_response.encode("hex"))
5632             logger.info("flags: " + flags.encode("hex"))
5633
5634             auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
5635             logger.info("auth_challenge: " + auth_challenge.encode("hex"))
5636  
5637             auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
5638                                                       peer_challenge,
5639                                                       auth_challenge, "user")
5640             payload = "S=" + auth_resp.encode('hex').upper()
5641             logger.info("Success message payload: " + payload)
5642             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5643                                4 + 1 + 4 + len(payload),
5644                                EAP_TYPE_MSCHAPV2,
5645                                3, 0, 4 + len(payload)) + payload
5646         idx += 1
5647         if ctx['num'] == idx:
5648             logger.info("Test: EAP-Success")
5649             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
5650
5651         idx += 1
5652         if ctx['num'] == idx:
5653             logger.info("Test: Challenge")
5654             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5655                                4 + 1 + 4 + 1 + 16 + 6,
5656                                EAP_TYPE_MSCHAPV2,
5657                                1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
5658         idx += 1
5659         if ctx['num'] == idx:
5660             logger.info("Test: Failure - authentication failure")
5661             payload = 'E=691 R=1 C=00112233445566778899aabbccddeeff V=3 M=Authentication failed'
5662             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5663                                4 + 1 + 4 + len(payload),
5664                                EAP_TYPE_MSCHAPV2,
5665                                4, 0, 4 + len(payload)) + payload
5666
5667         idx += 1
5668         if ctx['num'] == idx:
5669             logger.info("Test: Challenge")
5670             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5671                                4 + 1 + 4 + 1 + 16 + 6,
5672                                EAP_TYPE_MSCHAPV2,
5673                                1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
5674         idx += 1
5675         if ctx['num'] == idx:
5676             logger.info("Test: Failure - authentication failure")
5677             payload = 'E=691 R=1 C=00112233445566778899aabbccddeeff V=3 M=Authentication failed (2)'
5678             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5679                                4 + 1 + 4 + len(payload),
5680                                EAP_TYPE_MSCHAPV2,
5681                                4, 0, 4 + len(payload)) + payload
5682         idx += 1
5683         if ctx['num'] == idx:
5684             logger.info("Test: Failure")
5685             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5686
5687         idx += 1
5688         if ctx['num'] == idx:
5689             logger.info("Test: Challenge - invalid ms_len and workaround disabled")
5690             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
5691                                4 + 1 + 4 + 1 + 16 + 6,
5692                                EAP_TYPE_MSCHAPV2,
5693                                1, 0, 4 + 1 + 16 + 6 + 1, 16) + 16*'A' + 'foobar'
5694
5695         return None
5696
5697     srv = start_radius_server(mschapv2_handler)
5698
5699     try:
5700         hapd = start_ap(apdev[0])
5701
5702         for i in range(0, 16):
5703             logger.info("RUN: %d" % i)
5704             if i == 12:
5705                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5706                                eap="MSCHAPV2", identity="user",
5707                                password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
5708                                wait_connect=False)
5709             elif i == 14:
5710                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5711                                eap="MSCHAPV2", identity="user",
5712                                phase2="mschapv2_retry=0",
5713                                password="password", wait_connect=False)
5714             elif i == 15:
5715                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5716                                eap="MSCHAPV2", identity="user",
5717                                eap_workaround="0",
5718                                password="password", wait_connect=False)
5719             else:
5720                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5721                                eap="MSCHAPV2", identity="user",
5722                                password="password", wait_connect=False)
5723             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
5724             if ev is None:
5725                 raise Exception("Timeout on EAP start")
5726
5727             if i in [ 8, 11, 12 ]:
5728                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"],
5729                                        timeout=10)
5730                 if ev is None:
5731                     raise Exception("Timeout on new password request")
5732                 id = ev.split(':')[0].split('-')[-1]
5733                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
5734                 if i in [ 11, 12 ]:
5735                     ev = dev[0].wait_event(["CTRL-EVENT-PASSWORD-CHANGED"],
5736                                        timeout=10)
5737                     if ev is None:
5738                         raise Exception("Timeout on password change")
5739                     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"],
5740                                        timeout=10)
5741                     if ev is None:
5742                         raise Exception("Timeout on EAP success")
5743                 else:
5744                     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
5745                                            timeout=10)
5746                     if ev is None:
5747                         raise Exception("Timeout on EAP failure")
5748
5749             if i in [ 13 ]:
5750                 ev = dev[0].wait_event(["CTRL-REQ-IDENTITY"],
5751                                        timeout=10)
5752                 if ev is None:
5753                     raise Exception("Timeout on identity request")
5754                 id = ev.split(':')[0].split('-')[-1]
5755                 dev[0].request("CTRL-RSP-IDENTITY-" + id + ":user")
5756
5757                 ev = dev[0].wait_event(["CTRL-REQ-PASSWORD"],
5758                                        timeout=10)
5759                 if ev is None:
5760                     raise Exception("Timeout on password request")
5761                 id = ev.split(':')[0].split('-')[-1]
5762                 dev[0].request("CTRL-RSP-PASSWORD-" + id + ":password")
5763
5764                 # TODO: Does this work correctly?
5765
5766                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
5767                                        timeout=10)
5768                 if ev is None:
5769                     raise Exception("Timeout on EAP failure")
5770
5771             if i in [ 4, 5, 6, 7, 14 ]:
5772                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
5773                                        timeout=10)
5774                 if ev is None:
5775                     raise Exception("Timeout on EAP failure")
5776             else:
5777                 time.sleep(0.05)
5778             dev[0].request("REMOVE_NETWORK all")
5779             dev[0].wait_disconnected(timeout=1)
5780     finally:
5781         stop_radius_server(srv)
5782
5783 def test_eap_proto_mschapv2_errors(dev, apdev):
5784     """EAP-MSCHAPv2 protocol tests (error paths)"""
5785     check_eap_capa(dev[0], "MSCHAPV2")
5786
5787     def mschapv2_fail_password_expired(ctx):
5788         logger.info("Test: Failure before challenge - password expired")
5789         payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
5790         return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5791                            4 + 1 + 4 + len(payload),
5792                            EAP_TYPE_MSCHAPV2,
5793                            4, 0, 4 + len(payload)) + payload
5794
5795     def mschapv2_success_after_password_change(ctx, req=None):
5796         logger.info("Test: Success after password change")
5797         if req is None or len(req) != 591:
5798             payload = "S=1122334455667788990011223344556677889900"
5799         else:
5800             data = req[9:]
5801             enc_pw = data[0:516]
5802             data = data[516:]
5803             enc_hash = data[0:16]
5804             data = data[16:]
5805             peer_challenge = data[0:16]
5806             data = data[16:]
5807             # Reserved
5808             data = data[8:]
5809             nt_response = data[0:24]
5810             data = data[24:]
5811             flags = data
5812             logger.info("enc_hash: " + enc_hash.encode("hex"))
5813             logger.info("peer_challenge: " + peer_challenge.encode("hex"))
5814             logger.info("nt_response: " + nt_response.encode("hex"))
5815             logger.info("flags: " + flags.encode("hex"))
5816
5817             auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
5818             logger.info("auth_challenge: " + auth_challenge.encode("hex"))
5819
5820             auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
5821                                                       peer_challenge,
5822                                                       auth_challenge, "user")
5823             payload = "S=" + auth_resp.encode('hex').upper()
5824         return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
5825                            4 + 1 + 4 + len(payload),
5826                            EAP_TYPE_MSCHAPV2,
5827                            3, 0, 4 + len(payload)) + payload
5828
5829     def mschapv2_handler(ctx, req):
5830         logger.info("mschapv2_handler - RX " + req.encode("hex"))
5831         if 'num' not in ctx:
5832             ctx['num'] = 0
5833         ctx['num'] = ctx['num'] + 1
5834         if 'id' not in ctx:
5835             ctx['id'] = 1
5836         ctx['id'] = (ctx['id'] + 1) % 256
5837         idx = 0
5838
5839         idx += 1
5840         if ctx['num'] == idx:
5841             return mschapv2_fail_password_expired(ctx)
5842         idx += 1
5843         if ctx['num'] == idx:
5844             return mschapv2_success_after_password_change(ctx, req)
5845         idx += 1
5846         if ctx['num'] == idx:
5847             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5848
5849         idx += 1
5850         if ctx['num'] == idx:
5851             return mschapv2_fail_password_expired(ctx)
5852         idx += 1
5853         if ctx['num'] == idx:
5854             return mschapv2_success_after_password_change(ctx, req)
5855         idx += 1
5856         if ctx['num'] == idx:
5857             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5858
5859         idx += 1
5860         if ctx['num'] == idx:
5861             return mschapv2_fail_password_expired(ctx)
5862         idx += 1
5863         if ctx['num'] == idx:
5864             return mschapv2_success_after_password_change(ctx, req)
5865         idx += 1
5866         if ctx['num'] == idx:
5867             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5868
5869         idx += 1
5870         if ctx['num'] == idx:
5871             return mschapv2_fail_password_expired(ctx)
5872         idx += 1
5873         if ctx['num'] == idx:
5874             return mschapv2_success_after_password_change(ctx, req)
5875         idx += 1
5876         if ctx['num'] == idx:
5877             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5878
5879         idx += 1
5880         if ctx['num'] == idx:
5881             return mschapv2_fail_password_expired(ctx)
5882         idx += 1
5883         if ctx['num'] == idx:
5884             return mschapv2_success_after_password_change(ctx, req)
5885         idx += 1
5886         if ctx['num'] == idx:
5887             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5888
5889         idx += 1
5890         if ctx['num'] == idx:
5891             return mschapv2_fail_password_expired(ctx)
5892         idx += 1
5893         if ctx['num'] == idx:
5894             return mschapv2_success_after_password_change(ctx, req)
5895         idx += 1
5896         if ctx['num'] == idx:
5897             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5898
5899         idx += 1
5900         if ctx['num'] == idx:
5901             return mschapv2_fail_password_expired(ctx)
5902         idx += 1
5903         if ctx['num'] == idx:
5904             return mschapv2_success_after_password_change(ctx, req)
5905         idx += 1
5906         if ctx['num'] == idx:
5907             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5908
5909         idx += 1
5910         if ctx['num'] == idx:
5911             return mschapv2_fail_password_expired(ctx)
5912         idx += 1
5913         if ctx['num'] == idx:
5914             return mschapv2_success_after_password_change(ctx, req)
5915         idx += 1
5916         if ctx['num'] == idx:
5917             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5918
5919         idx += 1
5920         if ctx['num'] == idx:
5921             return mschapv2_fail_password_expired(ctx)
5922         idx += 1
5923         if ctx['num'] == idx:
5924             return mschapv2_success_after_password_change(ctx, req)
5925         idx += 1
5926         if ctx['num'] == idx:
5927             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5928
5929         return None
5930
5931     srv = start_radius_server(mschapv2_handler)
5932
5933     try:
5934         hapd = start_ap(apdev[0])
5935
5936         tests = [ "os_get_random;eap_mschapv2_change_password",
5937                   "generate_nt_response;eap_mschapv2_change_password",
5938                   "get_master_key;eap_mschapv2_change_password",
5939                   "nt_password_hash;eap_mschapv2_change_password",
5940                   "old_nt_password_hash_encrypted_with_new_nt_password_hash" ]
5941         for func in tests:
5942             with fail_test(dev[0], 1, func):
5943                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5944                                eap="MSCHAPV2", identity="user",
5945                                password="password", wait_connect=False)
5946                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
5947                 if ev is None:
5948                     raise Exception("Timeout on new password request")
5949                 id = ev.split(':')[0].split('-')[-1]
5950                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
5951                 time.sleep(0.1)
5952                 wait_fail_trigger(dev[0], "GET_FAIL")
5953                 dev[0].request("REMOVE_NETWORK all")
5954                 dev[0].wait_disconnected(timeout=1)
5955
5956         tests = [ "encrypt_pw_block_with_password_hash;eap_mschapv2_change_password",
5957                   "nt_password_hash;eap_mschapv2_change_password",
5958                   "nt_password_hash;eap_mschapv2_success" ]
5959         for func in tests:
5960             with fail_test(dev[0], 1, func):
5961                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5962                                eap="MSCHAPV2", identity="user",
5963                                password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
5964                                wait_connect=False)
5965                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
5966                 if ev is None:
5967                     raise Exception("Timeout on new password request")
5968                 id = ev.split(':')[0].split('-')[-1]
5969                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
5970                 time.sleep(0.1)
5971                 wait_fail_trigger(dev[0], "GET_FAIL")
5972                 dev[0].request("REMOVE_NETWORK all")
5973                 dev[0].wait_disconnected(timeout=1)
5974
5975         tests = [ "eap_msg_alloc;eap_mschapv2_change_password" ]
5976         for func in tests:
5977             with alloc_fail(dev[0], 1, func):
5978                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5979                                eap="MSCHAPV2", identity="user",
5980                                password="password", wait_connect=False)
5981                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
5982                 if ev is None:
5983                     raise Exception("Timeout on new password request")
5984                 id = ev.split(':')[0].split('-')[-1]
5985                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
5986                 time.sleep(0.1)
5987                 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5988                 dev[0].request("REMOVE_NETWORK all")
5989                 dev[0].wait_disconnected(timeout=1)
5990     finally:
5991         stop_radius_server(srv)
5992
5993 def test_eap_proto_pwd(dev, apdev):
5994     """EAP-pwd protocol tests"""
5995     check_eap_capa(dev[0], "PWD")
5996
5997     global eap_proto_pwd_test_done, eap_proto_pwd_test_wait
5998     eap_proto_pwd_test_done = False
5999     eap_proto_pwd_test_wait = False
6000
6001     def pwd_handler(ctx, req):
6002         logger.info("pwd_handler - RX " + req.encode("hex"))
6003         if 'num' not in ctx:
6004             ctx['num'] = 0
6005         ctx['num'] = ctx['num'] + 1
6006         if 'id' not in ctx:
6007             ctx['id'] = 1
6008         ctx['id'] = (ctx['id'] + 1) % 256
6009         idx = 0
6010
6011         global eap_proto_pwd_test_wait
6012         eap_proto_pwd_test_wait = False
6013
6014         idx += 1
6015         if ctx['num'] == idx:
6016             logger.info("Test: Missing payload")
6017             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
6018                                EAP_TYPE_PWD)
6019
6020         idx += 1
6021         if ctx['num'] == idx:
6022             logger.info("Test: Missing Total-Length field")
6023             payload = struct.pack("B", 0x80)
6024             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6025                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6026
6027         idx += 1
6028         if ctx['num'] == idx:
6029             logger.info("Test: Too large Total-Length")
6030             payload = struct.pack(">BH", 0x80, 65535)
6031             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6032                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6033
6034         idx += 1
6035         if ctx['num'] == idx:
6036             eap_proto_pwd_test_wait = True
6037             logger.info("Test: First fragment")
6038             payload = struct.pack(">BH", 0xc0, 10)
6039             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6040                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6041         idx += 1
6042         if ctx['num'] == idx:
6043             logger.info("Test: Unexpected Total-Length value in the second fragment")
6044             payload = struct.pack(">BH", 0x80, 0)
6045             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6046                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6047
6048         idx += 1
6049         if ctx['num'] == idx:
6050             logger.info("Test: First and only fragment")
6051             payload = struct.pack(">BH", 0x80, 0)
6052             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6053                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6054
6055         idx += 1
6056         if ctx['num'] == idx:
6057             logger.info("Test: First and only fragment with extra data")
6058             payload = struct.pack(">BHB", 0x80, 0, 0)
6059             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6060                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6061
6062         idx += 1
6063         if ctx['num'] == idx:
6064             eap_proto_pwd_test_wait = True
6065             logger.info("Test: First fragment")
6066             payload = struct.pack(">BHB", 0xc0, 2, 1)
6067             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6068                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6069         idx += 1
6070         if ctx['num'] == idx:
6071             logger.info("Test: Extra data in the second fragment")
6072             payload = struct.pack(">BBB", 0x0, 2, 3)
6073             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6074                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6075
6076         idx += 1
6077         if ctx['num'] == idx:
6078             logger.info("Test: Too short id exchange")
6079             payload = struct.pack(">B", 0x01)
6080             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6081                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6082
6083         idx += 1
6084         if ctx['num'] == idx:
6085             logger.info("Test: Unsupported rand func in id exchange")
6086             payload = struct.pack(">BHBBLB", 0x01, 0, 0, 0, 0, 0)
6087             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6088                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6089
6090         idx += 1
6091         if ctx['num'] == idx:
6092             logger.info("Test: Unsupported prf in id exchange")
6093             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 0, 0, 0)
6094             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6095                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6096
6097         idx += 1
6098         if ctx['num'] == idx:
6099             logger.info("Test: Unsupported password pre-processing technique in id exchange")
6100             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 255)
6101             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6102                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6103
6104         idx += 1
6105         if ctx['num'] == idx:
6106             eap_proto_pwd_test_wait = True
6107             logger.info("Test: Valid id exchange")
6108             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
6109             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6110                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6111         idx += 1
6112         if ctx['num'] == idx:
6113             logger.info("Test: Unexpected id exchange")
6114             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
6115             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6116                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6117
6118         idx += 1
6119         if ctx['num'] == idx:
6120             logger.info("Test: Unexpected commit exchange")
6121             payload = struct.pack(">B", 0x02)
6122             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6123                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6124
6125         idx += 1
6126         if ctx['num'] == idx:
6127             eap_proto_pwd_test_wait = True
6128             logger.info("Test: Valid id exchange")
6129             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
6130             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6131                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6132         idx += 1
6133         if ctx['num'] == idx:
6134             logger.info("Test: Unexpected Commit payload length")
6135             payload = struct.pack(">B", 0x02)
6136             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6137                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6138
6139         idx += 1
6140         if ctx['num'] == idx:
6141             eap_proto_pwd_test_wait = True
6142             logger.info("Test: Valid id exchange")
6143             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
6144             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6145                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6146         idx += 1
6147         if ctx['num'] == idx:
6148             logger.info("Test: Commit payload with all zeros values --> Shared key at infinity")
6149             payload = struct.pack(">B", 0x02) + 96*'\0'
6150             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6151                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6152
6153         idx += 1
6154         if ctx['num'] == idx:
6155             eap_proto_pwd_test_wait = True
6156             logger.info("Test: Valid id exchange")
6157             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
6158             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6159                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6160         idx += 1
6161         if ctx['num'] == idx:
6162             eap_proto_pwd_test_wait = True
6163             logger.info("Test: Commit payload with valid values")
6164             element = binascii.unhexlify("8dcab2862c5396839a6bac0c689ff03d962863108e7c275bbf1d6eedf634ee832a214db99f0d0a1a6317733eecdd97f0fc4cda19f57e1bb9bb9c8dcf8c60ba6f")
6165             scalar = binascii.unhexlify("450f31e058cf2ac2636a5d6e2b3c70b1fcc301957f0716e77f13aa69f9a2e5bd")
6166             payload = struct.pack(">B", 0x02) + element + scalar
6167             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6168                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6169         idx += 1
6170         if ctx['num'] == idx:
6171             logger.info("Test: Unexpected Confirm payload length 0")
6172             payload = struct.pack(">B", 0x03)
6173             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6174                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6175
6176         idx += 1
6177         if ctx['num'] == idx:
6178             eap_proto_pwd_test_wait = True
6179             logger.info("Test: Valid id exchange")
6180             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
6181             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6182                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6183         idx += 1
6184         if ctx['num'] == idx:
6185             eap_proto_pwd_test_wait = True
6186             logger.info("Test: Commit payload with valid values")
6187             element = binascii.unhexlify("8dcab2862c5396839a6bac0c689ff03d962863108e7c275bbf1d6eedf634ee832a214db99f0d0a1a6317733eecdd97f0fc4cda19f57e1bb9bb9c8dcf8c60ba6f")
6188             scalar = binascii.unhexlify("450f31e058cf2ac2636a5d6e2b3c70b1fcc301957f0716e77f13aa69f9a2e5bd")
6189             payload = struct.pack(">B", 0x02) + element + scalar
6190             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6191                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6192         idx += 1
6193         if ctx['num'] == idx:
6194             logger.info("Test: Confirm payload with incorrect value")
6195             payload = struct.pack(">B", 0x03) + 32*'\0'
6196             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6197                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6198
6199         idx += 1
6200         if ctx['num'] == idx:
6201             logger.info("Test: Unexpected confirm exchange")
6202             payload = struct.pack(">B", 0x03)
6203             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6204                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
6205
6206         logger.info("No more test responses available - test case completed")
6207         global eap_proto_pwd_test_done
6208         eap_proto_pwd_test_done = True
6209         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6210
6211     srv = start_radius_server(pwd_handler)
6212
6213     try:
6214         hapd = start_ap(apdev[0])
6215
6216         i = 0
6217         while not eap_proto_pwd_test_done:
6218             i += 1
6219             logger.info("Running connection iteration %d" % i)
6220             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6221                            eap="PWD", identity="pwd user",
6222                            password="secret password",
6223                            wait_connect=False)
6224             ok = False
6225             for j in range(5):
6226                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS",
6227                                         "CTRL-EVENT-EAP-PROPOSED-METHOD"],
6228                                        timeout=5)
6229                 if ev is None:
6230                     raise Exception("Timeout on EAP start")
6231                 if "CTRL-EVENT-EAP-PROPOSED-METHOD" in ev:
6232                     ok = True
6233                     break
6234                 if "CTRL-EVENT-EAP-STATUS" in ev and "status='completion' parameter='failure'" in ev:
6235                     ok = True
6236                     break
6237             if not ok:
6238                 raise Exception("Expected EAP event not seen")
6239             if eap_proto_pwd_test_wait:
6240                 for k in range(10):
6241                     time.sleep(0.1)
6242                     if not eap_proto_pwd_test_wait:
6243                         break
6244             dev[0].request("REMOVE_NETWORK all")
6245             dev[0].wait_disconnected(timeout=1)
6246             dev[0].dump_monitor()
6247     finally:
6248         stop_radius_server(srv)
6249
6250 def test_eap_proto_pwd_errors(dev, apdev):
6251     """EAP-pwd local error cases"""
6252     check_eap_capa(dev[0], "PWD")
6253     params = hostapd.wpa2_eap_params(ssid="eap-test")
6254     hapd = hostapd.add_ap(apdev[0], params)
6255
6256     for i in range(1, 4):
6257         with alloc_fail(dev[0], i, "eap_pwd_init"):
6258             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6259                            eap="PWD", identity="pwd user",
6260                            password="secret password",
6261                            wait_connect=False)
6262             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
6263                                    timeout=15)
6264             if ev is None:
6265                 raise Exception("Timeout on EAP start")
6266             dev[0].request("REMOVE_NETWORK all")
6267             dev[0].wait_disconnected()
6268
6269     with alloc_fail(dev[0], 1, "eap_pwd_get_session_id"):
6270         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6271                        eap="PWD", identity="pwd user",
6272                        fragment_size="0",
6273                        password="secret password")
6274         dev[0].request("REMOVE_NETWORK all")
6275         dev[0].wait_disconnected()
6276
6277     funcs = [ "eap_pwd_getkey", "eap_pwd_get_emsk" ]
6278     for func in funcs:
6279         with alloc_fail(dev[0], 1, func):
6280             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6281                            eap="PWD", identity="pwd user",
6282                            password="secret password", erp="1",
6283                            wait_connect=False)
6284             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6285             dev[0].request("REMOVE_NETWORK all")
6286             dev[0].wait_disconnected()
6287
6288     for i in range(1, 7):
6289         with alloc_fail(dev[0], i, "eap_pwd_perform_id_exchange"):
6290             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6291                            eap="PWD", identity="pwd user",
6292                            password="secret password",
6293                            wait_connect=False)
6294             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6295                                    timeout=15)
6296             if ev is None:
6297                 raise Exception("Timeout on EAP start")
6298             ok = False
6299             for j in range(10):
6300                 state = dev[0].request('GET_ALLOC_FAIL')
6301                 if state.startswith('0:'):
6302                     ok = True
6303                     break
6304                 time.sleep(0.1)
6305             if not ok:
6306                 raise Exception("No allocation failure seen")
6307             dev[0].request("REMOVE_NETWORK all")
6308             dev[0].wait_disconnected()
6309
6310     with alloc_fail(dev[0], 1, "wpabuf_alloc;eap_pwd_perform_id_exchange"):
6311         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6312                        eap="PWD", identity="pwd user",
6313                        password="secret password",
6314                        wait_connect=False)
6315         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6316                                timeout=15)
6317         if ev is None:
6318             raise Exception("Timeout on EAP start")
6319         dev[0].request("REMOVE_NETWORK all")
6320         dev[0].wait_disconnected()
6321
6322     for i in range(1, 4):
6323         with alloc_fail(dev[0], i, "eap_pwd_perform_commit_exchange"):
6324             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6325                            eap="PWD", identity="pwd user",
6326                            password="secret password",
6327                            wait_connect=False)
6328             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6329                                    timeout=15)
6330             if ev is None:
6331                 raise Exception("Timeout on EAP start")
6332             ok = False
6333             for j in range(10):
6334                 state = dev[0].request('GET_ALLOC_FAIL')
6335                 if state.startswith('0:'):
6336                     ok = True
6337                     break
6338                 time.sleep(0.1)
6339             if not ok:
6340                 raise Exception("No allocation failure seen")
6341             dev[0].request("REMOVE_NETWORK all")
6342             dev[0].wait_disconnected()
6343
6344     for i in range(1, 12):
6345         with alloc_fail(dev[0], i, "eap_pwd_perform_confirm_exchange"):
6346             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6347                            eap="PWD", identity="pwd user",
6348                            password="secret password",
6349                            wait_connect=False)
6350             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6351                                    timeout=15)
6352             if ev is None:
6353                 raise Exception("Timeout on EAP start")
6354             ok = False
6355             for j in range(10):
6356                 state = dev[0].request('GET_ALLOC_FAIL')
6357                 if state.startswith('0:'):
6358                     ok = True
6359                     break
6360                 time.sleep(0.1)
6361             if not ok:
6362                 raise Exception("No allocation failure seen")
6363             dev[0].request("REMOVE_NETWORK all")
6364             dev[0].wait_disconnected()
6365
6366     for i in range(1, 5):
6367         with alloc_fail(dev[0], i, "eap_msg_alloc;=eap_pwd_process"):
6368             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6369                            eap="PWD", identity="pwd user",
6370                            password="secret password", fragment_size="50",
6371                            wait_connect=False)
6372             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6373                                    timeout=15)
6374             if ev is None:
6375                 raise Exception("Timeout on EAP start")
6376             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6377             dev[0].request("REMOVE_NETWORK all")
6378             dev[0].wait_disconnected()
6379
6380     # No password configured
6381     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6382                    eap="PWD", identity="pwd user",
6383                    wait_connect=False)
6384     ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=52"],
6385                            timeout=15)
6386     if ev is None:
6387         raise Exception("EAP-pwd not started")
6388     dev[0].request("REMOVE_NETWORK all")
6389     dev[0].wait_disconnected()
6390
6391     with fail_test(dev[0], 1,
6392                    "hash_nt_password_hash;eap_pwd_perform_id_exchange"):
6393         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6394                        eap="PWD", identity="pwd-hash",
6395                        password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a",
6396                        wait_connect=False)
6397         ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
6398         if ev is None:
6399             raise Exception("No EAP-Failure reported")
6400         dev[0].request("REMOVE_NETWORK all")
6401         dev[0].wait_disconnected()
6402
6403     params = { "ssid": "eap-test2", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
6404                "rsn_pairwise": "CCMP", "ieee8021x": "1",
6405                "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
6406                "pwd_group": "19", "fragment_size": "40" }
6407     hostapd.add_ap(apdev[1], params)
6408
6409     with alloc_fail(dev[0], 1, "wpabuf_alloc;=eap_pwd_process"):
6410         dev[0].connect("eap-test2", key_mgmt="WPA-EAP", scan_freq="2412",
6411                        eap="PWD", identity="pwd user",
6412                        password="secret password",
6413                        wait_connect=False)
6414         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6415         dev[0].request("REMOVE_NETWORK all")
6416         dev[0].wait_disconnected()
6417
6418 def test_eap_proto_erp(dev, apdev):
6419     """ERP protocol tests"""
6420     check_erp_capa(dev[0])
6421
6422     global eap_proto_erp_test_done
6423     eap_proto_erp_test_done = False
6424
6425     def erp_handler(ctx, req):
6426         logger.info("erp_handler - RX " + req.encode("hex"))
6427         if 'num' not in ctx:
6428             ctx['num'] = 0
6429         ctx['num'] += 1
6430         if 'id' not in ctx:
6431             ctx['id'] = 1
6432         ctx['id'] = (ctx['id'] + 1) % 256
6433         idx = 0
6434
6435         idx += 1
6436         if ctx['num'] == idx:
6437             logger.info("Test: Missing type")
6438             return struct.pack(">BBH", EAP_CODE_INITIATE, ctx['id'], 4)
6439
6440         idx += 1
6441         if ctx['num'] == idx:
6442             logger.info("Test: Unexpected type")
6443             return struct.pack(">BBHB", EAP_CODE_INITIATE, ctx['id'], 4 + 1,
6444                                255)
6445
6446         idx += 1
6447         if ctx['num'] == idx:
6448             logger.info("Test: Missing Reserved field")
6449             return struct.pack(">BBHB", EAP_CODE_INITIATE, ctx['id'], 4 + 1,
6450                                EAP_ERP_TYPE_REAUTH_START)
6451
6452         idx += 1
6453         if ctx['num'] == idx:
6454             logger.info("Test: Zero-length TVs/TLVs")
6455             payload = ""
6456             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6457                                4 + 1 + 1 + len(payload),
6458                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6459
6460         idx += 1
6461         if ctx['num'] == idx:
6462             logger.info("Test: Too short TLV")
6463             payload = struct.pack("B", 191)
6464             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6465                                4 + 1 + 1 + len(payload),
6466                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6467
6468         idx += 1
6469         if ctx['num'] == idx:
6470             logger.info("Test: Truncated TLV")
6471             payload = struct.pack("BB", 191, 1)
6472             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6473                                4 + 1 + 1 + len(payload),
6474                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6475
6476         idx += 1
6477         if ctx['num'] == idx:
6478             logger.info("Test: Ignored unknown TLV and unknown TV/TLV terminating parsing")
6479             payload = struct.pack("BBB", 191, 0, 192)
6480             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6481                                4 + 1 + 1 + len(payload),
6482                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6483
6484         idx += 1
6485         if ctx['num'] == idx:
6486             logger.info("Test: More than one keyName-NAI")
6487             payload = struct.pack("BBBB", EAP_ERP_TLV_KEYNAME_NAI, 0,
6488                                   EAP_ERP_TLV_KEYNAME_NAI, 0)
6489             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6490                                4 + 1 + 1 + len(payload),
6491                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6492
6493         idx += 1
6494         if ctx['num'] == idx:
6495             logger.info("Test: Too short TLV keyName-NAI")
6496             payload = struct.pack("B", EAP_ERP_TLV_KEYNAME_NAI)
6497             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6498                                4 + 1 + 1 + len(payload),
6499                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6500
6501         idx += 1
6502         if ctx['num'] == idx:
6503             logger.info("Test: Truncated TLV keyName-NAI")
6504             payload = struct.pack("BB", EAP_ERP_TLV_KEYNAME_NAI, 1)
6505             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6506                                4 + 1 + 1 + len(payload),
6507                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6508
6509         idx += 1
6510         if ctx['num'] == idx:
6511             logger.info("Test: Valid rRK lifetime TV followed by too short rMSK lifetime TV")
6512             payload = struct.pack(">BLBH", EAP_ERP_TV_RRK_LIFETIME, 0,
6513                                   EAP_ERP_TV_RMSK_LIFETIME, 0)
6514             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
6515                                4 + 1 + 1 + len(payload),
6516                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
6517
6518         idx += 1
6519         if ctx['num'] == idx:
6520             logger.info("Test: Missing type (Finish)")
6521             return struct.pack(">BBH", EAP_CODE_FINISH, ctx['id'], 4)
6522
6523         idx += 1
6524         if ctx['num'] == idx:
6525             logger.info("Test: Unexpected type (Finish)")
6526             return struct.pack(">BBHB", EAP_CODE_FINISH, ctx['id'], 4 + 1,
6527                                255)
6528
6529         idx += 1
6530         if ctx['num'] == idx:
6531             logger.info("Test: Missing fields (Finish)")
6532             return struct.pack(">BBHB", EAP_CODE_FINISH, ctx['id'], 4 + 1,
6533                                EAP_ERP_TYPE_REAUTH)
6534
6535         idx += 1
6536         if ctx['num'] == idx:
6537             logger.info("Test: Unexpected SEQ (Finish)")
6538             return struct.pack(">BBHBBHB", EAP_CODE_FINISH, ctx['id'],
6539                                4 + 1 + 4,
6540                                EAP_ERP_TYPE_REAUTH, 0, 0xffff, 0)
6541
6542         logger.info("No more test responses available - test case completed")
6543         global eap_proto_erp_test_done
6544         eap_proto_erp_test_done = True
6545         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6546
6547     srv = start_radius_server(erp_handler)
6548
6549     try:
6550         hapd = start_ap(apdev[0])
6551
6552         i = 0
6553         while not eap_proto_erp_test_done:
6554             i += 1
6555             logger.info("Running connection iteration %d" % i)
6556             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6557                            eap="PAX", identity="pax.user@example.com",
6558                            password_hex="0123456789abcdef0123456789abcdef",
6559                            wait_connect=False)
6560             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
6561             if ev is None:
6562                 raise Exception("Timeout on EAP start")
6563             time.sleep(0.1)
6564             dev[0].request("REMOVE_NETWORK all")
6565             dev[0].wait_disconnected(timeout=1)
6566             dev[0].dump_monitor()
6567     finally:
6568         stop_radius_server(srv)
6569
6570 def test_eap_proto_fast_errors(dev, apdev):
6571     """EAP-FAST local error cases"""
6572     check_eap_capa(dev[0], "FAST")
6573     params = hostapd.wpa2_eap_params(ssid="eap-test")
6574     hapd = hostapd.add_ap(apdev[0], params)
6575
6576     for i in range(1, 5):
6577         with alloc_fail(dev[0], i, "eap_fast_init"):
6578             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6579                            eap="FAST", anonymous_identity="FAST",
6580                            identity="user", password="password",
6581                            ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
6582                            phase1="fast_provisioning=2",
6583                            pac_file="blob://fast_pac_auth",
6584                            wait_connect=False)
6585             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
6586                                    timeout=5)
6587             if ev is None:
6588                 raise Exception("Timeout on EAP start")
6589             dev[0].request("REMOVE_NETWORK all")
6590             dev[0].wait_disconnected()
6591
6592     tests = [ (1, "wpabuf_alloc;eap_fast_tlv_eap_payload"),
6593               (1, "eap_fast_derive_key;eap_fast_derive_key_auth"),
6594               (1, "eap_msg_alloc;eap_peer_tls_phase2_nak"),
6595               (1, "wpabuf_alloc;eap_fast_tlv_result"),
6596               (1, "wpabuf_alloc;eap_fast_tlv_pac_ack"),
6597               (1, "=eap_peer_tls_derive_session_id;eap_fast_process_crypto_binding"),
6598               (1, "eap_peer_tls_decrypt;eap_fast_decrypt"),
6599               (1, "eap_fast_getKey"),
6600               (1, "eap_fast_get_session_id"),
6601               (1, "eap_fast_get_emsk") ]
6602     for count, func in tests:
6603         dev[0].request("SET blob fast_pac_auth_errors ")
6604         with alloc_fail(dev[0], count, func):
6605             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6606                            eap="FAST", anonymous_identity="FAST",
6607                            identity="user", password="password",
6608                            ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
6609                            phase1="fast_provisioning=2",
6610                            pac_file="blob://fast_pac_auth_errors",
6611                            erp="1",
6612                            wait_connect=False)
6613             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6614                                    timeout=15)
6615             if ev is None:
6616                 raise Exception("Timeout on EAP start")
6617             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6618             dev[0].request("REMOVE_NETWORK all")
6619             dev[0].wait_disconnected()
6620
6621     tests = [ (1, "eap_fast_derive_key;eap_fast_derive_key_provisioning"),
6622               (1, "eap_mschapv2_getKey;eap_fast_get_phase2_key"),
6623               (1, "=eap_fast_use_pac_opaque"),
6624               (1, "eap_fast_copy_buf"),
6625               (1, "=eap_fast_add_pac"),
6626               (1, "=eap_fast_init_pac_data"),
6627               (1, "=eap_fast_write_pac"),
6628               (2, "=eap_fast_write_pac") ]
6629     for count, func in tests:
6630         dev[0].request("SET blob fast_pac_errors ")
6631         with alloc_fail(dev[0], count, func):
6632             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6633                            eap="FAST", anonymous_identity="FAST",
6634                            identity="user", password="password",
6635                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6636                            phase1="fast_provisioning=1",
6637                            pac_file="blob://fast_pac_errors",
6638                            erp="1",
6639                            wait_connect=False)
6640             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6641                                    timeout=15)
6642             if ev is None:
6643                 raise Exception("Timeout on EAP start")
6644             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6645             dev[0].request("REMOVE_NETWORK all")
6646             dev[0].wait_disconnected()
6647
6648     tests = [ (1, "eap_fast_get_cmk;eap_fast_process_crypto_binding"),
6649               (1, "eap_fast_derive_eap_msk;eap_fast_process_crypto_binding"),
6650               (1, "eap_fast_derive_eap_emsk;eap_fast_process_crypto_binding") ]
6651     for count, func in tests:
6652         dev[0].request("SET blob fast_pac_auth_errors ")
6653         with fail_test(dev[0], count, func):
6654             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6655                            eap="FAST", anonymous_identity="FAST",
6656                            identity="user", password="password",
6657                            ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
6658                            phase1="fast_provisioning=2",
6659                            pac_file="blob://fast_pac_auth_errors",
6660                            erp="1",
6661                            wait_connect=False)
6662             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6663                                    timeout=15)
6664             if ev is None:
6665                 raise Exception("Timeout on EAP start")
6666             wait_fail_trigger(dev[0], "GET_FAIL")
6667             dev[0].request("REMOVE_NETWORK all")
6668             dev[0].wait_disconnected()
6669
6670     dev[0].request("SET blob fast_pac_errors ")
6671     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6672                    eap="FAST", anonymous_identity="FAST",
6673                    identity="user", password="password",
6674                    ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
6675                    phase1="fast_provisioning=1",
6676                    pac_file="blob://fast_pac_errors",
6677                    wait_connect=False)
6678     ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
6679     if ev is None:
6680         raise Exception("Timeout on EAP start")
6681     # EAP-FAST: Only EAP-MSCHAPv2 is allowed during unauthenticated
6682     # provisioning; reject phase2 type 6
6683     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
6684     if ev is None:
6685         raise Exception("Timeout on EAP failure")
6686     dev[0].request("REMOVE_NETWORK all")
6687     dev[0].wait_disconnected()
6688
6689     logger.info("Wrong password in Phase 2")
6690     dev[0].request("SET blob fast_pac_errors ")
6691     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6692                    eap="FAST", anonymous_identity="FAST",
6693                    identity="user", password="wrong password",
6694                    ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6695                    phase1="fast_provisioning=1",
6696                    pac_file="blob://fast_pac_errors",
6697                    wait_connect=False)
6698     ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
6699     if ev is None:
6700         raise Exception("Timeout on EAP start")
6701     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
6702     if ev is None:
6703         raise Exception("Timeout on EAP failure")
6704     dev[0].request("REMOVE_NETWORK all")
6705     dev[0].wait_disconnected()
6706
6707     tests = [ "FOOBAR\n",
6708               "wpa_supplicant EAP-FAST PAC file - version 1\nFOOBAR\n",
6709               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\n",
6710               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nSTART\n",
6711               "wpa_supplicant EAP-FAST PAC file - version 1\nEND\n",
6712               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Type=12345\nEND\n"
6713               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=12\nEND\n",
6714               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=1\nEND\n",
6715               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=1q\nEND\n",
6716               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Opaque=1\nEND\n",
6717               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nA-ID=1\nEND\n",
6718               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nI-ID=1\nEND\n",
6719               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nA-ID-Info=1\nEND\n" ]
6720     for pac in tests:
6721         blob = binascii.hexlify(pac)
6722         dev[0].request("SET blob fast_pac_errors " + blob)
6723         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6724                        eap="FAST", anonymous_identity="FAST",
6725                        identity="user", password="password",
6726                        ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
6727                        phase1="fast_provisioning=2",
6728                        pac_file="blob://fast_pac_errors",
6729                        wait_connect=False)
6730         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
6731                                timeout=5)
6732         if ev is None:
6733             raise Exception("Timeout on EAP start")
6734         dev[0].request("REMOVE_NETWORK all")
6735         dev[0].wait_disconnected()
6736
6737     tests = [ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nEND\n",
6738               "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nEND\nSTART\nEND\nSTART\nEND\n" ]
6739     for pac in tests:
6740         blob = binascii.hexlify(pac)
6741         dev[0].request("SET blob fast_pac_errors " + blob)
6742         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6743                        eap="FAST", anonymous_identity="FAST",
6744                        identity="user", password="password",
6745                        ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
6746                        phase1="fast_provisioning=2",
6747                        pac_file="blob://fast_pac_errors")
6748         dev[0].request("REMOVE_NETWORK all")
6749         dev[0].wait_disconnected()
6750
6751     dev[0].request("SET blob fast_pac_errors ")
6752
6753 def test_eap_proto_peap_errors(dev, apdev):
6754     """EAP-PEAP local error cases"""
6755     check_eap_capa(dev[0], "PEAP")
6756     check_eap_capa(dev[0], "MSCHAPV2")
6757     params = hostapd.wpa2_eap_params(ssid="eap-test")
6758     hapd = hostapd.add_ap(apdev[0], params)
6759
6760     for i in range(1, 5):
6761         with alloc_fail(dev[0], i, "eap_peap_init"):
6762             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6763                            eap="PEAP", anonymous_identity="peap",
6764                            identity="user", password="password",
6765                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6766                            wait_connect=False)
6767             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
6768                                    timeout=5)
6769             if ev is None:
6770                 raise Exception("Timeout on EAP start")
6771             dev[0].request("REMOVE_NETWORK all")
6772             dev[0].wait_disconnected()
6773
6774     tests = [ (1, "eap_mschapv2_getKey;eap_peap_get_isk;eap_peap_derive_cmk"),
6775               (1, "eap_msg_alloc;eap_tlv_build_result"),
6776               (1, "eap_mschapv2_init;eap_peap_phase2_request"),
6777               (1, "eap_peer_tls_decrypt;eap_peap_decrypt"),
6778               (1, "wpabuf_alloc;=eap_peap_decrypt"),
6779               (1, "eap_peer_tls_encrypt;eap_peap_decrypt"),
6780               (1, "eap_peer_tls_process_helper;eap_peap_process"),
6781               (1, "eap_peer_tls_derive_key;eap_peap_process"),
6782               (1, "eap_peer_tls_derive_session_id;eap_peap_process"),
6783               (1, "eap_peap_getKey"),
6784               (1, "eap_peap_get_session_id") ]
6785     for count, func in tests:
6786         with alloc_fail(dev[0], count, func):
6787             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6788                            eap="PEAP", anonymous_identity="peap",
6789                            identity="user", password="password",
6790                            phase1="peapver=0 crypto_binding=2",
6791                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6792                            erp="1", wait_connect=False)
6793             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6794                                    timeout=15)
6795             if ev is None:
6796                 raise Exception("Timeout on EAP start")
6797             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6798             dev[0].request("REMOVE_NETWORK all")
6799             dev[0].wait_disconnected()
6800
6801     tests = [ (1, "peap_prfplus;eap_peap_derive_cmk"),
6802               (1, "eap_tlv_add_cryptobinding;eap_tlv_build_result"),
6803               (1, "peap_prfplus;eap_peap_getKey") ]
6804     for count, func in tests:
6805         with fail_test(dev[0], count, func):
6806             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6807                            eap="PEAP", anonymous_identity="peap",
6808                            identity="user", password="password",
6809                            phase1="peapver=0 crypto_binding=2",
6810                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6811                            erp="1", wait_connect=False)
6812             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6813                                    timeout=15)
6814             if ev is None:
6815                 raise Exception("Timeout on EAP start")
6816             wait_fail_trigger(dev[0], "GET_FAIL")
6817             dev[0].request("REMOVE_NETWORK all")
6818             dev[0].wait_disconnected()
6819
6820     with alloc_fail(dev[0], 1,
6821                     "eap_peer_tls_phase2_nak;eap_peap_phase2_request"):
6822         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6823                        eap="PEAP", anonymous_identity="peap",
6824                        identity="cert user", password="password",
6825                        ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6826                        wait_connect=False)
6827         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
6828         dev[0].request("REMOVE_NETWORK all")
6829         dev[0].wait_disconnected()
6830
6831 def test_eap_proto_ttls_errors(dev, apdev):
6832     """EAP-TTLS local error cases"""
6833     check_eap_capa(dev[0], "TTLS")
6834     check_eap_capa(dev[0], "MSCHAPV2")
6835     params = hostapd.wpa2_eap_params(ssid="eap-test")
6836     hapd = hostapd.add_ap(apdev[0], params)
6837
6838     for i in range(1, 5):
6839         with alloc_fail(dev[0], i, "eap_ttls_init"):
6840             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6841                            eap="TTLS", anonymous_identity="ttls",
6842                            identity="user", password="password",
6843                            ca_cert="auth_serv/ca.pem",
6844                            phase2="autheap=MSCHAPV2",
6845                            wait_connect=False)
6846             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
6847                                    timeout=5)
6848             if ev is None:
6849                 raise Exception("Timeout on EAP start")
6850             dev[0].request("REMOVE_NETWORK all")
6851             dev[0].wait_disconnected()
6852
6853     tests = [ (1, "eap_peer_tls_derive_key;eap_ttls_v0_derive_key",
6854                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6855               (1, "eap_peer_tls_derive_session_id;eap_ttls_v0_derive_key",
6856                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6857               (1, "wpabuf_alloc;eap_ttls_phase2_request_mschapv2",
6858                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6859               (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_mschapv2",
6860                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6861               (1, "eap_peer_tls_encrypt;eap_ttls_encrypt_response;eap_ttls_implicit_identity_request",
6862                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6863               (1, "eap_peer_tls_decrypt;eap_ttls_decrypt",
6864                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6865               (1, "eap_ttls_getKey",
6866                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6867               (1, "eap_ttls_get_session_id",
6868                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6869               (1, "eap_ttls_get_emsk",
6870                "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
6871               (1, "wpabuf_alloc;eap_ttls_phase2_request_mschap",
6872                "mschap user", "auth=MSCHAP"),
6873               (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_mschap",
6874                "mschap user", "auth=MSCHAP"),
6875               (1, "wpabuf_alloc;eap_ttls_phase2_request_chap",
6876                "chap user", "auth=CHAP"),
6877               (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_chap",
6878                "chap user", "auth=CHAP"),
6879               (1, "wpabuf_alloc;eap_ttls_phase2_request_pap",
6880                "pap user", "auth=PAP"),
6881               (1, "wpabuf_alloc;eap_ttls_avp_encapsulate",
6882                "user", "autheap=MSCHAPV2"),
6883               (1, "eap_mschapv2_init;eap_ttls_phase2_request_eap_method",
6884                "user", "autheap=MSCHAPV2"),
6885               (1, "eap_sm_buildIdentity;eap_ttls_phase2_request_eap",
6886                "user", "autheap=MSCHAPV2"),
6887               (1, "eap_ttls_avp_encapsulate;eap_ttls_phase2_request_eap",
6888                "user", "autheap=MSCHAPV2"),
6889               (1, "eap_ttls_parse_attr_eap",
6890                "user", "autheap=MSCHAPV2"),
6891               (1, "eap_peer_tls_encrypt;eap_ttls_encrypt_response;eap_ttls_process_decrypted",
6892                "user", "autheap=MSCHAPV2"),
6893               (1, "eap_ttls_fake_identity_request",
6894                "user", "autheap=MSCHAPV2"),
6895               (1, "eap_msg_alloc;eap_tls_process_output",
6896                "user", "autheap=MSCHAPV2"),
6897               (1, "eap_msg_alloc;eap_peer_tls_build_ack",
6898                "user", "autheap=MSCHAPV2"),
6899               (1, "tls_connection_decrypt;eap_peer_tls_decrypt",
6900                "user", "autheap=MSCHAPV2"),
6901               (1, "eap_peer_tls_phase2_nak;eap_ttls_phase2_request_eap_method",
6902                "cert user", "autheap=MSCHAPV2") ]
6903     for count, func, identity, phase2 in tests:
6904         with alloc_fail(dev[0], count, func):
6905             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6906                            eap="TTLS", anonymous_identity="ttls",
6907                            identity=identity, password="password",
6908                            ca_cert="auth_serv/ca.pem", phase2=phase2,
6909                            erp="1", wait_connect=False)
6910             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6911                                    timeout=15)
6912             if ev is None:
6913                 raise Exception("Timeout on EAP start")
6914             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
6915                               note="Allocation failure not triggered for: %d:%s" % (count, func))
6916             dev[0].request("REMOVE_NETWORK all")
6917             dev[0].wait_disconnected()
6918
6919     tests = [ (1, "os_get_random;eap_ttls_phase2_request_mschapv2"),
6920               (1, "mschapv2_derive_response;eap_ttls_phase2_request_mschapv2") ]
6921     for count, func in tests:
6922         with fail_test(dev[0], count, func):
6923             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6924                            eap="TTLS", anonymous_identity="ttls",
6925                            identity="DOMAIN\mschapv2 user", password="password",
6926                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
6927                            erp="1", wait_connect=False)
6928             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6929                                    timeout=15)
6930             if ev is None:
6931                 raise Exception("Timeout on EAP start")
6932             wait_fail_trigger(dev[0], "GET_FAIL",
6933                               note="Test failure not triggered for: %d:%s" % (count, func))
6934             dev[0].request("REMOVE_NETWORK all")
6935             dev[0].wait_disconnected()
6936
6937 def test_eap_proto_expanded(dev, apdev):
6938     """EAP protocol tests with expanded header"""
6939     global eap_proto_expanded_test_done
6940     eap_proto_expanded_test_done = False
6941
6942     def expanded_handler(ctx, req):
6943         logger.info("expanded_handler - RX " + req.encode("hex"))
6944         if 'num' not in ctx:
6945             ctx['num'] = 0
6946         ctx['num'] += 1
6947         if 'id' not in ctx:
6948             ctx['id'] = 1
6949         ctx['id'] = (ctx['id'] + 1) % 256
6950         idx = 0
6951
6952         idx += 1
6953         if ctx['num'] == idx:
6954             logger.info("Test: MD5 challenge in expanded header")
6955             return struct.pack(">BBHB3BLBBB", EAP_CODE_REQUEST, ctx['id'],
6956                                4 + 1 + 3 + 4 + 3,
6957                                EAP_TYPE_EXPANDED, 0, 0, 0, EAP_TYPE_MD5,
6958                                1, 0xaa, ord('n'))
6959         idx += 1
6960         if ctx['num'] == idx:
6961             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6962
6963         idx += 1
6964         if ctx['num'] == idx:
6965             logger.info("Test: Invalid expanded EAP length")
6966             return struct.pack(">BBHB3BH", EAP_CODE_REQUEST, ctx['id'],
6967                                4 + 1 + 3 + 2,
6968                                EAP_TYPE_EXPANDED, 0, 0, 0, EAP_TYPE_MD5)
6969         idx += 1
6970         if ctx['num'] == idx:
6971             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6972
6973         idx += 1
6974         if ctx['num'] == idx:
6975             logger.info("Test: Invalid expanded frame type")
6976             return struct.pack(">BBHB3BL", EAP_CODE_REQUEST, ctx['id'],
6977                                4 + 1 + 3 + 4,
6978                                EAP_TYPE_EXPANDED, 0, 0, 1, EAP_TYPE_MD5)
6979         idx += 1
6980         if ctx['num'] == idx:
6981             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6982
6983         idx += 1
6984         if ctx['num'] == idx:
6985             logger.info("Test: MSCHAPv2 Challenge")
6986             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6987                                4 + 1 + 4 + 1 + 16 + 6,
6988                                EAP_TYPE_MSCHAPV2,
6989                                1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
6990         idx += 1
6991         if ctx['num'] == idx:
6992             logger.info("Test: Invalid expanded frame type")
6993             return struct.pack(">BBHB3BL", EAP_CODE_REQUEST, ctx['id'],
6994                                4 + 1 + 3 + 4,
6995                                EAP_TYPE_EXPANDED, 0, 0, 1, EAP_TYPE_MSCHAPV2)
6996
6997         logger.info("No more test responses available - test case completed")
6998         global eap_proto_expanded_test_done
6999         eap_proto_expanded_test_done = True
7000         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7001
7002     srv = start_radius_server(expanded_handler)
7003
7004     try:
7005         hapd = start_ap(apdev[0])
7006
7007         i = 0
7008         while not eap_proto_expanded_test_done:
7009             i += 1
7010             logger.info("Running connection iteration %d" % i)
7011             if i == 4:
7012                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7013                                eap="MSCHAPV2", identity="user",
7014                                password="password",
7015                                wait_connect=False)
7016             else:
7017                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7018                                eap="MD5", identity="user", password="password",
7019                                wait_connect=False)
7020             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
7021             if ev is None:
7022                 raise Exception("Timeout on EAP start")
7023             if i in [ 1 ]:
7024                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
7025                 if ev is None:
7026                     raise Exception("Timeout on EAP method start")
7027                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
7028                 if ev is None:
7029                     raise Exception("Timeout on EAP failure")
7030             elif i in [ 2, 3 ]:
7031                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
7032                                        timeout=5)
7033                 if ev is None:
7034                     raise Exception("Timeout on EAP proposed method")
7035                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
7036                 if ev is None:
7037                     raise Exception("Timeout on EAP failure")
7038             else:
7039                 time.sleep(0.1)
7040             dev[0].request("REMOVE_NETWORK all")
7041             dev[0].wait_disconnected(timeout=1)
7042             dev[0].dump_monitor()
7043     finally:
7044         stop_radius_server(srv)
7045
7046 def test_eap_proto_tls(dev, apdev):
7047     """EAP-TLS protocol tests"""
7048     check_eap_capa(dev[0], "TLS")
7049     global eap_proto_tls_test_done, eap_proto_tls_test_wait
7050     eap_proto_tls_test_done = False
7051     eap_proto_tls_test_wait = False
7052
7053     def tls_handler(ctx, req):
7054         logger.info("tls_handler - RX " + req.encode("hex"))
7055         if 'num' not in ctx:
7056             ctx['num'] = 0
7057         ctx['num'] += 1
7058         if 'id' not in ctx:
7059             ctx['id'] = 1
7060         ctx['id'] = (ctx['id'] + 1) % 256
7061         idx = 0
7062
7063         global eap_proto_tls_test_wait
7064
7065         idx += 1
7066         if ctx['num'] == idx:
7067             logger.info("Test: Too much payload in TLS/Start: TLS Message Length (0 bytes) smaller than this fragment (1 bytes)")
7068             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
7069                                4 + 1 + 1 + 4 + 1,
7070                                EAP_TYPE_TLS, 0xa0, 0, 1)
7071
7072         idx += 1
7073         if ctx['num'] == idx:
7074             logger.info("Test: Fragmented TLS/Start")
7075             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
7076                                4 + 1 + 1 + 4 + 1,
7077                                EAP_TYPE_TLS, 0xe0, 2, 1)
7078         idx += 1
7079         if ctx['num'] == idx:
7080             logger.info("Test: Too long fragment of TLS/Start: Invalid reassembly state: tls_in_left=2 tls_in_len=0 in_len=0")
7081             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
7082                                4 + 1 + 1 + 2,
7083                                EAP_TYPE_TLS, 0x00, 2, 3)
7084         idx += 1
7085         if ctx['num'] == idx:
7086             logger.info("Test: EAP-Failure")
7087             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7088
7089         idx += 1
7090         if ctx['num'] == idx:
7091             logger.info("Test: TLS/Start")
7092             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7093                                4 + 1 + 1,
7094                                EAP_TYPE_TLS, 0x20)
7095         idx += 1
7096         if ctx['num'] == idx:
7097             logger.info("Test: Fragmented TLS message")
7098             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
7099                                4 + 1 + 1 + 4 + 1,
7100                                EAP_TYPE_TLS, 0xc0, 2, 1)
7101         idx += 1
7102         if ctx['num'] == idx:
7103             logger.info("Test: Invalid TLS message: no Flags octet included + workaround")
7104             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7105                                4 + 1,
7106                                EAP_TYPE_TLS)
7107         idx += 1
7108         if ctx['num'] == idx:
7109             logger.info("Test: Too long fragment of TLS message: more data than TLS message length indicated")
7110             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
7111                                4 + 1 + 1 + 2,
7112                                EAP_TYPE_TLS, 0x00, 2, 3)
7113         idx += 1
7114         if ctx['num'] == idx:
7115             logger.info("Test: EAP-Failure")
7116             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7117
7118         idx += 1
7119         if ctx['num'] == idx:
7120             logger.info("Test: Fragmented TLS/Start and truncated Message Length field")
7121             return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
7122                                4 + 1 + 1 + 3,
7123                                EAP_TYPE_TLS, 0xe0, 1, 2, 3)
7124
7125         idx += 1
7126         if ctx['num'] == idx:
7127             logger.info("Test: TLS/Start")
7128             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7129                                4 + 1 + 1,
7130                                EAP_TYPE_TLS, 0x20)
7131         idx += 1
7132         if ctx['num'] == idx:
7133             logger.info("Test: Fragmented TLS message")
7134             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
7135                                4 + 1 + 1 + 4 + 1,
7136                                EAP_TYPE_TLS, 0xc0, 2, 1)
7137         idx += 1
7138         if ctx['num'] == idx:
7139             logger.info("Test: Invalid TLS message: no Flags octet included + workaround disabled")
7140             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7141                                4 + 1,
7142                                EAP_TYPE_TLS)
7143
7144         idx += 1
7145         if ctx['num'] == idx:
7146             logger.info("Test: TLS/Start")
7147             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7148                                4 + 1 + 1,
7149                                EAP_TYPE_TLS, 0x20)
7150         idx += 1
7151         if ctx['num'] == idx:
7152             logger.info("Test: Fragmented TLS message (long; first)")
7153             payload = 1450*'A'
7154             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
7155                                4 + 1 + 1 + 4 + len(payload),
7156                                EAP_TYPE_TLS, 0xc0, 65536) + payload
7157         # "Too long TLS fragment (size over 64 kB)" on the last one
7158         for i in range(44):
7159             idx += 1
7160             if ctx['num'] == idx:
7161                 logger.info("Test: Fragmented TLS message (long; cont %d)" % i)
7162                 eap_proto_tls_test_wait = True
7163                 payload = 1470*'A'
7164                 return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7165                                    4 + 1 + 1 + len(payload),
7166                                    EAP_TYPE_TLS, 0x40) + payload
7167         eap_proto_tls_test_wait = False
7168         idx += 1
7169         if ctx['num'] == idx:
7170             logger.info("Test: EAP-Failure")
7171             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7172
7173         idx += 1
7174         if ctx['num'] == idx:
7175             logger.info("Test: TLS/Start")
7176             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7177                                4 + 1 + 1,
7178                                EAP_TYPE_TLS, 0x20)
7179         idx += 1
7180         if ctx['num'] == idx:
7181             logger.info("Test: Non-ACK to more-fragment message")
7182             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
7183                                4 + 1 + 1 + 1,
7184                                EAP_TYPE_TLS, 0x00, 255)
7185         idx += 1
7186         if ctx['num'] == idx:
7187             logger.info("Test: EAP-Failure")
7188             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7189
7190         logger.info("No more test responses available - test case completed")
7191         global eap_proto_tls_test_done
7192         eap_proto_tls_test_done = True
7193         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7194
7195     srv = start_radius_server(tls_handler)
7196
7197     try:
7198         hapd = start_ap(apdev[0])
7199
7200         i = 0
7201         while not eap_proto_tls_test_done:
7202             i += 1
7203             logger.info("Running connection iteration %d" % i)
7204             workaround = "0" if i == 6 else "1"
7205             fragment_size = "100" if i == 8 else "1400"
7206             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7207                            eap="TLS", identity="tls user",
7208                            ca_cert="auth_serv/ca.pem",
7209                            client_cert="auth_serv/user.pem",
7210                            private_key="auth_serv/user.key",
7211                            eap_workaround=workaround,
7212                            fragment_size=fragment_size,
7213                            wait_connect=False)
7214             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
7215             if ev is None:
7216                 raise Exception("Timeout on EAP start")
7217             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD",
7218                                     "CTRL-EVENT-EAP-STATUS"], timeout=5)
7219             if ev is None:
7220                 raise Exception("Timeout on EAP method start")
7221             time.sleep(0.1)
7222             start = os.times()[4]
7223             while eap_proto_tls_test_wait:
7224                 now = os.times()[4]
7225                 if now - start > 10:
7226                     break
7227                 time.sleep(0.1)
7228             dev[0].request("REMOVE_NETWORK all")
7229             dev[0].wait_disconnected(timeout=1)
7230             dev[0].dump_monitor()
7231     finally:
7232         stop_radius_server(srv)
7233
7234 def test_eap_proto_tnc(dev, apdev):
7235     """EAP-TNC protocol tests"""
7236     check_eap_capa(dev[0], "TNC")
7237     global eap_proto_tnc_test_done
7238     eap_proto_tnc_test_done = False
7239
7240     def tnc_handler(ctx, req):
7241         logger.info("tnc_handler - RX " + req.encode("hex"))
7242         if 'num' not in ctx:
7243             ctx['num'] = 0
7244         ctx['num'] += 1
7245         if 'id' not in ctx:
7246             ctx['id'] = 1
7247         ctx['id'] = (ctx['id'] + 1) % 256
7248         idx = 0
7249
7250         idx += 1
7251         if ctx['num'] == idx:
7252             logger.info("Test: TNC start with unsupported version")
7253             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7254                                4 + 1 + 1,
7255                                EAP_TYPE_TNC, 0x20)
7256
7257         idx += 1
7258         if ctx['num'] == idx:
7259             logger.info("Test: TNC without Flags field")
7260             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7261                                4 + 1,
7262                                EAP_TYPE_TNC)
7263
7264         idx += 1
7265         if ctx['num'] == idx:
7266             logger.info("Test: Message underflow due to missing Message Length")
7267             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7268                                4 + 1 + 1,
7269                                EAP_TYPE_TNC, 0xa1)
7270
7271         idx += 1
7272         if ctx['num'] == idx:
7273             logger.info("Test: Invalid Message Length")
7274             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
7275                                4 + 1 + 1 + 4 + 1,
7276                                EAP_TYPE_TNC, 0xa1, 0, 0)
7277
7278         idx += 1
7279         if ctx['num'] == idx:
7280             logger.info("Test: Invalid Message Length")
7281             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
7282                                4 + 1 + 1 + 4,
7283                                EAP_TYPE_TNC, 0xe1, 75001)
7284
7285         idx += 1
7286         if ctx['num'] == idx:
7287             logger.info("Test: Start with Message Length")
7288             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
7289                                4 + 1 + 1 + 4,
7290                                EAP_TYPE_TNC, 0xa1, 1)
7291         idx += 1
7292         if ctx['num'] == idx:
7293             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7294
7295         idx += 1
7296         if ctx['num'] == idx:
7297             logger.info("Test: Server used start flag again")
7298             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7299                                4 + 1 + 1,
7300                                EAP_TYPE_TNC, 0x21)
7301         idx += 1
7302         if ctx['num'] == idx:
7303             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7304                                4 + 1 + 1,
7305                                EAP_TYPE_TNC, 0x21)
7306
7307         idx += 1
7308         if ctx['num'] == idx:
7309             logger.info("Test: Fragmentation and unexpected payload in ack")
7310             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7311                                4 + 1 + 1,
7312                                EAP_TYPE_TNC, 0x21)
7313         idx += 1
7314         if ctx['num'] == idx:
7315             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7316                                4 + 1 + 1,
7317                                EAP_TYPE_TNC, 0x01)
7318         idx += 1
7319         if ctx['num'] == idx:
7320             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
7321                                4 + 1 + 1 + 1,
7322                                EAP_TYPE_TNC, 0x01, 0)
7323
7324         idx += 1
7325         if ctx['num'] == idx:
7326             logger.info("Test: Server fragmenting and fragment overflow")
7327             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
7328                                4 + 1 + 1 + 4 + 1,
7329                                EAP_TYPE_TNC, 0xe1, 2, 1)
7330         idx += 1
7331         if ctx['num'] == idx:
7332             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
7333                                4 + 1 + 1 + 2,
7334                                EAP_TYPE_TNC, 0x01, 2, 3)
7335
7336         idx += 1
7337         if ctx['num'] == idx:
7338             logger.info("Test: Server fragmenting and no message length in a fragment")
7339             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
7340                                4 + 1 + 1 + 1,
7341                                EAP_TYPE_TNC, 0x61, 2)
7342
7343         idx += 1
7344         if ctx['num'] == idx:
7345             logger.info("Test: TNC start followed by invalid TNCCS-Batch")
7346             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7347                                4 + 1 + 1,
7348                                EAP_TYPE_TNC, 0x21)
7349         idx += 1
7350         if ctx['num'] == idx:
7351             logger.info("Received TNCCS-Batch: " + req[6:])
7352             resp = "FOO"
7353             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7354                                4 + 1 + 1 + len(resp),
7355                                EAP_TYPE_TNC, 0x01) + resp
7356
7357         idx += 1
7358         if ctx['num'] == idx:
7359             logger.info("Test: TNC start followed by invalid TNCCS-Batch (2)")
7360             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7361                                4 + 1 + 1,
7362                                EAP_TYPE_TNC, 0x21)
7363         idx += 1
7364         if ctx['num'] == idx:
7365             logger.info("Received TNCCS-Batch: " + req[6:])
7366             resp = "</TNCCS-Batch><TNCCS-Batch>"
7367             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7368                                4 + 1 + 1 + len(resp),
7369                                EAP_TYPE_TNC, 0x01) + resp
7370
7371         idx += 1
7372         if ctx['num'] == idx:
7373             logger.info("Test: TNCCS-Batch missing BatchId attribute")
7374             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7375                                4 + 1 + 1,
7376                                EAP_TYPE_TNC, 0x21)
7377         idx += 1
7378         if ctx['num'] == idx:
7379             logger.info("Received TNCCS-Batch: " + req[6:])
7380             resp = "<TNCCS-Batch    foo=3></TNCCS-Batch>"
7381             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7382                                4 + 1 + 1 + len(resp),
7383                                EAP_TYPE_TNC, 0x01) + resp
7384
7385         idx += 1
7386         if ctx['num'] == idx:
7387             logger.info("Test: Unexpected IF-TNCCS BatchId")
7388             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7389                                4 + 1 + 1,
7390                                EAP_TYPE_TNC, 0x21)
7391         idx += 1
7392         if ctx['num'] == idx:
7393             logger.info("Received TNCCS-Batch: " + req[6:])
7394             resp = "<TNCCS-Batch    BatchId=123456789></TNCCS-Batch>"
7395             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7396                                4 + 1 + 1 + len(resp),
7397                                EAP_TYPE_TNC, 0x01) + resp
7398
7399         idx += 1
7400         if ctx['num'] == idx:
7401             logger.info("Test: Missing IMC-IMV-Message and TNCC-TNCS-Message end tags")
7402             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7403                                4 + 1 + 1,
7404                                EAP_TYPE_TNC, 0x21)
7405         idx += 1
7406         if ctx['num'] == idx:
7407             logger.info("Received TNCCS-Batch: " + req[6:])
7408             resp = "<TNCCS-Batch BatchId=2><IMC-IMV-Message><TNCC-TNCS-Message></TNCCS-Batch>"
7409             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7410                                4 + 1 + 1 + len(resp),
7411                                EAP_TYPE_TNC, 0x01) + resp
7412         idx += 1
7413         if ctx['num'] == idx:
7414             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7415
7416         idx += 1
7417         if ctx['num'] == idx:
7418             logger.info("Test: Missing IMC-IMV-Message and TNCC-TNCS-Message Type")
7419             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7420                                4 + 1 + 1,
7421                                EAP_TYPE_TNC, 0x21)
7422         idx += 1
7423         if ctx['num'] == idx:
7424             logger.info("Received TNCCS-Batch: " + req[6:])
7425             resp = "<TNCCS-Batch BatchId=2><IMC-IMV-Message></IMC-IMV-Message><TNCC-TNCS-Message></TNCC-TNCS-Message></TNCCS-Batch>"
7426             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7427                                4 + 1 + 1 + len(resp),
7428                                EAP_TYPE_TNC, 0x01) + resp
7429         idx += 1
7430         if ctx['num'] == idx:
7431             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7432
7433         idx += 1
7434         if ctx['num'] == idx:
7435             logger.info("Test: Missing TNCC-TNCS-Message XML end tag")
7436             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7437                                4 + 1 + 1,
7438                                EAP_TYPE_TNC, 0x21)
7439         idx += 1
7440         if ctx['num'] == idx:
7441             logger.info("Received TNCCS-Batch: " + req[6:])
7442             resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML></TNCC-TNCS-Message></TNCCS-Batch>"
7443             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7444                                4 + 1 + 1 + len(resp),
7445                                EAP_TYPE_TNC, 0x01) + resp
7446         idx += 1
7447         if ctx['num'] == idx:
7448             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7449
7450         idx += 1
7451         if ctx['num'] == idx:
7452             logger.info("Test: Missing TNCC-TNCS-Message Base64 start tag")
7453             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7454                                4 + 1 + 1,
7455                                EAP_TYPE_TNC, 0x21)
7456         idx += 1
7457         if ctx['num'] == idx:
7458             logger.info("Received TNCCS-Batch: " + req[6:])
7459             resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type></TNCC-TNCS-Message></TNCCS-Batch>"
7460             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7461                                4 + 1 + 1 + len(resp),
7462                                EAP_TYPE_TNC, 0x01) + resp
7463         idx += 1
7464         if ctx['num'] == idx:
7465             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7466
7467         idx += 1
7468         if ctx['num'] == idx:
7469             logger.info("Test: Missing TNCC-TNCS-Message Base64 end tag")
7470             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7471                                4 + 1 + 1,
7472                                EAP_TYPE_TNC, 0x21)
7473         idx += 1
7474         if ctx['num'] == idx:
7475             logger.info("Received TNCCS-Batch: " + req[6:])
7476             resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><Base64>abc</TNCC-TNCS-Message></TNCCS-Batch>"
7477             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7478                                4 + 1 + 1 + len(resp),
7479                                EAP_TYPE_TNC, 0x01) + resp
7480         idx += 1
7481         if ctx['num'] == idx:
7482             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7483
7484         idx += 1
7485         if ctx['num'] == idx:
7486             logger.info("Test: TNCC-TNCS-Message Base64 message")
7487             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7488                                4 + 1 + 1,
7489                                EAP_TYPE_TNC, 0x21)
7490         idx += 1
7491         if ctx['num'] == idx:
7492             logger.info("Received TNCCS-Batch: " + req[6:])
7493             resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><Base64>aGVsbG8=</Base64></TNCC-TNCS-Message></TNCCS-Batch>"
7494             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7495                                4 + 1 + 1 + len(resp),
7496                                EAP_TYPE_TNC, 0x01) + resp
7497         idx += 1
7498         if ctx['num'] == idx:
7499             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7500
7501         idx += 1
7502         if ctx['num'] == idx:
7503             logger.info("Test: Invalid TNCC-TNCS-Message XML message")
7504             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7505                                4 + 1 + 1,
7506                                EAP_TYPE_TNC, 0x21)
7507         idx += 1
7508         if ctx['num'] == idx:
7509             logger.info("Received TNCCS-Batch: " + req[6:])
7510             resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML>hello</XML></TNCC-TNCS-Message></TNCCS-Batch>"
7511             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7512                                4 + 1 + 1 + len(resp),
7513                                EAP_TYPE_TNC, 0x01) + resp
7514         idx += 1
7515         if ctx['num'] == idx:
7516             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7517
7518         idx += 1
7519         if ctx['num'] == idx:
7520             logger.info("Test: Missing TNCCS-Recommendation type")
7521             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7522                                4 + 1 + 1,
7523                                EAP_TYPE_TNC, 0x21)
7524         idx += 1
7525         if ctx['num'] == idx:
7526             logger.info("Received TNCCS-Batch: " + req[6:])
7527             resp = '<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation foo=1></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
7528             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7529                                4 + 1 + 1 + len(resp),
7530                                EAP_TYPE_TNC, 0x01) + resp
7531         idx += 1
7532         if ctx['num'] == idx:
7533             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7534
7535         idx += 1
7536         if ctx['num'] == idx:
7537             logger.info("Test: TNCCS-Recommendation type=none")
7538             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7539                                4 + 1 + 1,
7540                                EAP_TYPE_TNC, 0x21)
7541         idx += 1
7542         if ctx['num'] == idx:
7543             logger.info("Received TNCCS-Batch: " + req[6:])
7544             resp = '<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation type="none"></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
7545             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7546                                4 + 1 + 1 + len(resp),
7547                                EAP_TYPE_TNC, 0x01) + resp
7548         idx += 1
7549         if ctx['num'] == idx:
7550             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7551
7552         idx += 1
7553         if ctx['num'] == idx:
7554             logger.info("Test: TNCCS-Recommendation type=isolate")
7555             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7556                                4 + 1 + 1,
7557                                EAP_TYPE_TNC, 0x21)
7558         idx += 1
7559         if ctx['num'] == idx:
7560             logger.info("Received TNCCS-Batch: " + req[6:])
7561             resp = '<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation type="isolate"></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
7562             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7563                                4 + 1 + 1 + len(resp),
7564                                EAP_TYPE_TNC, 0x01) + resp
7565         idx += 1
7566         if ctx['num'] == idx:
7567             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7568
7569         logger.info("No more test responses available - test case completed")
7570         global eap_proto_tnc_test_done
7571         eap_proto_tnc_test_done = True
7572         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7573
7574     srv = start_radius_server(tnc_handler)
7575
7576     try:
7577         hapd = start_ap(apdev[0])
7578
7579         i = 0
7580         while not eap_proto_tnc_test_done:
7581             i += 1
7582             logger.info("Running connection iteration %d" % i)
7583             frag = 1400
7584             if i == 8:
7585                 frag = 150
7586             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7587                            eap="TNC", identity="tnc", fragment_size=str(frag),
7588                            wait_connect=False)
7589             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
7590             if ev is None:
7591                 raise Exception("Timeout on EAP start")
7592             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD",
7593                                     "CTRL-EVENT-EAP-STATUS"], timeout=5)
7594             if ev is None:
7595                 raise Exception("Timeout on EAP method start")
7596             time.sleep(0.1)
7597             dev[0].request("REMOVE_NETWORK all")
7598             dev[0].wait_disconnected(timeout=1)
7599             dev[0].dump_monitor()
7600     finally:
7601         stop_radius_server(srv)
7602
7603 def test_eap_canned_success_after_identity(dev, apdev):
7604     """EAP protocol tests for canned EAP-Success after identity"""
7605     check_eap_capa(dev[0], "MD5")
7606     def eap_canned_success_handler(ctx, req):
7607         logger.info("eap_canned_success_handler - RX " + req.encode("hex"))
7608         if 'num' not in ctx:
7609             ctx['num'] = 0
7610         ctx['num'] = ctx['num'] + 1
7611         if 'id' not in ctx:
7612             ctx['id'] = 1
7613         ctx['id'] = (ctx['id'] + 1) % 256
7614         idx = 0
7615
7616         idx += 1
7617         if ctx['num'] == idx:
7618             logger.info("Test: EAP-Success")
7619             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
7620
7621         idx += 1
7622         if ctx['num'] == idx:
7623             logger.info("Test: EAP-Success")
7624             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
7625
7626         return None
7627
7628     srv = start_radius_server(eap_canned_success_handler)
7629
7630     try:
7631         hapd = start_ap(apdev[0])
7632
7633         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7634                        phase1="allow_canned_success=1",
7635                        eap="MD5", identity="user", password="password",
7636                        wait_connect=False)
7637         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
7638         if ev is None:
7639             raise Exception("Timeout on EAP success")
7640         dev[0].request("REMOVE_NETWORK all")
7641         dev[0].wait_disconnected()
7642
7643         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7644                        eap="MD5", identity="user", password="password",
7645                        wait_connect=False)
7646         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
7647         if ev is None:
7648             raise Exception("Timeout on EAP start")
7649         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=0.1)
7650         if ev is not None:
7651             raise Exception("Unexpected EAP success")
7652         dev[0].request("REMOVE_NETWORK all")
7653         dev[0].wait_disconnected()
7654     finally:
7655         stop_radius_server(srv)
7656
7657 def test_eap_proto_wsc(dev, apdev):
7658     """EAP-WSC protocol tests"""
7659     global eap_proto_wsc_test_done, eap_proto_wsc_wait_failure
7660     eap_proto_wsc_test_done = False
7661
7662     def wsc_handler(ctx, req):
7663         logger.info("wsc_handler - RX " + req.encode("hex"))
7664         if 'num' not in ctx:
7665             ctx['num'] = 0
7666         ctx['num'] += 1
7667         if 'id' not in ctx:
7668             ctx['id'] = 1
7669         ctx['id'] = (ctx['id'] + 1) % 256
7670         idx = 0
7671
7672         global eap_proto_wsc_wait_failure
7673         eap_proto_wsc_wait_failure = False
7674
7675         idx += 1
7676         if ctx['num'] == idx:
7677             logger.info("Test: Missing Flags field")
7678             return struct.pack(">BBHB3BLB", EAP_CODE_REQUEST, ctx['id'],
7679                                4 + 1 + 3 + 4 + 1,
7680                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7681                                1)
7682
7683         idx += 1
7684         if ctx['num'] == idx:
7685             logger.info("Test: Message underflow (missing Message Length field)")
7686             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7687                                4 + 1 + 3 + 4 + 2,
7688                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7689                                1, 0x02)
7690
7691         idx += 1
7692         if ctx['num'] == idx:
7693             logger.info("Test: Invalid Message Length (> 50000)")
7694             return struct.pack(">BBHB3BLBBH", EAP_CODE_REQUEST, ctx['id'],
7695                                4 + 1 + 3 + 4 + 4,
7696                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7697                                1, 0x02, 65535)
7698
7699         idx += 1
7700         if ctx['num'] == idx:
7701             logger.info("Test: Invalid Message Length (< current payload)")
7702             return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
7703                                4 + 1 + 3 + 4 + 5,
7704                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7705                                1, 0x02, 0, 0xff)
7706
7707         idx += 1
7708         if ctx['num'] == idx:
7709             logger.info("Test: Unexpected Op-Code 5 in WAIT_START state")
7710             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7711                                4 + 1 + 3 + 4 + 2,
7712                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7713                                5, 0x00)
7714
7715         idx += 1
7716         if ctx['num'] == idx:
7717             logger.info("Test: Valid WSC Start to start the sequence")
7718             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7719                                4 + 1 + 3 + 4 + 2,
7720                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7721                                1, 0x00)
7722         idx += 1
7723         if ctx['num'] == idx:
7724             logger.info("Test: No Message Length field in a fragmented packet")
7725             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7726                                4 + 1 + 3 + 4 + 2,
7727                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7728                                4, 0x01)
7729
7730         idx += 1
7731         if ctx['num'] == idx:
7732             logger.info("Test: Valid WSC Start to start the sequence")
7733             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7734                                4 + 1 + 3 + 4 + 2,
7735                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7736                                1, 0x00)
7737         idx += 1
7738         if ctx['num'] == idx:
7739             logger.info("Test: Valid first fragmented packet")
7740             return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
7741                                4 + 1 + 3 + 4 + 5,
7742                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7743                                4, 0x03, 10, 1)
7744         idx += 1
7745         if ctx['num'] == idx:
7746             logger.info("Test: Unexpected Op-Code 5 in fragment (expected 4)")
7747             return struct.pack(">BBHB3BLBBB", EAP_CODE_REQUEST, ctx['id'],
7748                                4 + 1 + 3 + 4 + 3,
7749                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7750                                5, 0x01, 2)
7751
7752         idx += 1
7753         if ctx['num'] == idx:
7754             logger.info("Test: Valid WSC Start to start the sequence")
7755             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7756                                4 + 1 + 3 + 4 + 2,
7757                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7758                                1, 0x00)
7759         idx += 1
7760         if ctx['num'] == idx:
7761             logger.info("Test: Valid first fragmented packet")
7762             return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
7763                                4 + 1 + 3 + 4 + 5,
7764                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7765                                4, 0x03, 2, 1)
7766         idx += 1
7767         if ctx['num'] == idx:
7768             logger.info("Test: Fragment overflow")
7769             return struct.pack(">BBHB3BLBBBB", EAP_CODE_REQUEST, ctx['id'],
7770                                4 + 1 + 3 + 4 + 4,
7771                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7772                                4, 0x01, 2, 3)
7773
7774         idx += 1
7775         if ctx['num'] == idx:
7776             logger.info("Test: Valid WSC Start to start the sequence")
7777             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7778                                4 + 1 + 3 + 4 + 2,
7779                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7780                                1, 0x00)
7781         idx += 1
7782         if ctx['num'] == idx:
7783             logger.info("Test: Unexpected Op-Code 5 in WAIT_FRAG_ACK state")
7784             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7785                                4 + 1 + 3 + 4 + 2,
7786                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7787                                5, 0x00)
7788
7789         idx += 1
7790         if ctx['num'] == idx:
7791             logger.info("Test: Valid WSC Start")
7792             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
7793                                4 + 1 + 3 + 4 + 2,
7794                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
7795                                1, 0x00)
7796         idx += 1
7797         if ctx['num'] == idx:
7798             logger.info("No more test responses available - test case completed")
7799             global eap_proto_wsc_test_done
7800             eap_proto_wsc_test_done = True
7801             eap_proto_wsc_wait_failure = True
7802             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7803
7804         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7805
7806     srv = start_radius_server(wsc_handler)
7807
7808     try:
7809         hapd = start_ap(apdev[0])
7810
7811         i = 0
7812         while not eap_proto_wsc_test_done:
7813             i += 1
7814             logger.info("Running connection iteration %d" % i)
7815             fragment_size = 1398 if i != 9 else 50
7816             dev[0].connect("eap-test", key_mgmt="WPA-EAP", eap="WSC",
7817                            fragment_size=str(fragment_size),
7818                            identity="WFA-SimpleConfig-Enrollee-1-0",
7819                            phase1="pin=12345670",
7820                            scan_freq="2412", wait_connect=False)
7821             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
7822             if ev is None:
7823                 raise Exception("Timeout on EAP method start")
7824             if eap_proto_wsc_wait_failure:
7825                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
7826                 if ev is None:
7827                     raise Exception("Timeout on EAP failure")
7828             else:
7829                 time.sleep(0.1)
7830             dev[0].request("REMOVE_NETWORK all")
7831             dev[0].wait_disconnected(timeout=1)
7832             dev[0].dump_monitor()
7833     finally:
7834         stop_radius_server(srv)
7835
7836 def test_eap_canned_success_before_method(dev, apdev):
7837     """EAP protocol tests for canned EAP-Success before any method"""
7838     params = int_eap_server_params()
7839     hapd = hostapd.add_ap(apdev[0], params)
7840     bssid = apdev[0]['bssid']
7841     hapd.request("SET ext_eapol_frame_io 1")
7842
7843     dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
7844                    phase1="allow_canned_success=1",
7845                    eap="MD5", identity="user", password="password",
7846                    wait_connect=False)
7847
7848     ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
7849     if ev is None:
7850         raise Exception("Timeout on EAPOL-TX from hostapd")
7851
7852     res = dev[0].request("EAPOL_RX " + bssid + " 0200000403020004")
7853     if "OK" not in res:
7854         raise Exception("EAPOL_RX to wpa_supplicant failed")
7855
7856     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
7857     if ev is None:
7858         raise Exception("Timeout on EAP success")
7859     dev[0].request("REMOVE_NETWORK all")
7860     dev[0].wait_disconnected()
7861
7862 def test_eap_canned_failure_before_method(dev, apdev):
7863     """EAP protocol tests for canned EAP-Failure before any method"""
7864     params = int_eap_server_params()
7865     hapd = hostapd.add_ap(apdev[0], params)
7866     bssid = apdev[0]['bssid']
7867     hapd.request("SET ext_eapol_frame_io 1")
7868     dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
7869                    phase1="allow_canned_success=1",
7870                    eap="MD5", identity="user", password="password",
7871                    wait_connect=False)
7872
7873     ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
7874     if ev is None:
7875         raise Exception("Timeout on EAPOL-TX from hostapd")
7876
7877     res = dev[0].request("EAPOL_RX " + bssid + " 0200000404020004")
7878     if "OK" not in res:
7879         raise Exception("EAPOL_RX to wpa_supplicant failed")
7880
7881     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
7882     if ev is None:
7883         raise Exception("Timeout on EAP failure")
7884     dev[0].request("REMOVE_NETWORK all")
7885     dev[0].wait_disconnected()
7886
7887 def test_eap_nak_oom(dev, apdev):
7888     """EAP-Nak OOM"""
7889     check_eap_capa(dev[0], "MD5")
7890     params = hostapd.wpa2_eap_params(ssid="eap-test")
7891     hapd = hostapd.add_ap(apdev[0], params)
7892     with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sm_buildNak"):
7893         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7894                        eap="MD5", identity="sake user", password="password",
7895                        wait_connect=False)
7896         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
7897         dev[0].request("REMOVE_NETWORK all")
7898         dev[0].wait_disconnected()
7899
7900 def test_eap_nak_expanded(dev, apdev):
7901     """EAP-Nak with expanded method"""
7902     check_eap_capa(dev[0], "MD5")
7903     check_eap_capa(dev[0], "VENDOR-TEST")
7904     params = hostapd.wpa2_eap_params(ssid="eap-test")
7905     hapd = hostapd.add_ap(apdev[0], params)
7906     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7907                    eap="VENDOR-TEST WSC",
7908                    identity="sake user", password="password",
7909                    wait_connect=False)
7910     ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=10)
7911     if ev is None or "NAK" not in ev:
7912         raise Exception("No NAK event seen")
7913
7914     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
7915     if ev is None:
7916         raise Exception("No EAP-Failure seen")
7917
7918     dev[0].request("REMOVE_NETWORK all")
7919     dev[0].wait_disconnected()
7920
7921 EAP_TLV_RESULT_TLV = 3
7922 EAP_TLV_NAK_TLV = 4
7923 EAP_TLV_ERROR_CODE_TLV = 5
7924 EAP_TLV_CONNECTION_BINDING_TLV = 6
7925 EAP_TLV_VENDOR_SPECIFIC_TLV = 7
7926 EAP_TLV_URI_TLV = 8
7927 EAP_TLV_EAP_PAYLOAD_TLV = 9
7928 EAP_TLV_INTERMEDIATE_RESULT_TLV = 10
7929 EAP_TLV_PAC_TLV = 11
7930 EAP_TLV_CRYPTO_BINDING_TLV = 12
7931 EAP_TLV_CALLING_STATION_ID_TLV = 13
7932 EAP_TLV_CALLED_STATION_ID_TLV = 14
7933 EAP_TLV_NAS_PORT_TYPE_TLV = 15
7934 EAP_TLV_SERVER_IDENTIFIER_TLV = 16
7935 EAP_TLV_IDENTITY_TYPE_TLV = 17
7936 EAP_TLV_SERVER_TRUSTED_ROOT_TLV = 18
7937 EAP_TLV_REQUEST_ACTION_TLV = 19
7938 EAP_TLV_PKCS7_TLV = 20
7939
7940 EAP_TLV_RESULT_SUCCESS = 1
7941 EAP_TLV_RESULT_FAILURE = 2
7942
7943 EAP_TLV_TYPE_MANDATORY = 0x8000
7944 EAP_TLV_TYPE_MASK = 0x3fff
7945
7946 PAC_TYPE_PAC_KEY = 1
7947 PAC_TYPE_PAC_OPAQUE = 2
7948 PAC_TYPE_CRED_LIFETIME = 3
7949 PAC_TYPE_A_ID = 4
7950 PAC_TYPE_I_ID = 5
7951 PAC_TYPE_A_ID_INFO = 7
7952 PAC_TYPE_PAC_ACKNOWLEDGEMENT = 8
7953 PAC_TYPE_PAC_INFO = 9
7954 PAC_TYPE_PAC_TYPE = 10
7955
7956 def eap_fast_start(ctx):
7957     logger.info("Send EAP-FAST/Start")
7958     return struct.pack(">BBHBBHH", EAP_CODE_REQUEST, ctx['id'],
7959                        4 + 1 + 1 + 4 + 16,
7960                        EAP_TYPE_FAST, 0x21, 4, 16) + 16*'A'
7961
7962 def test_eap_fast_proto(dev, apdev):
7963     """EAP-FAST Phase protocol testing"""
7964     check_eap_capa(dev[0], "FAST")
7965     global eap_fast_proto_ctx
7966     eap_fast_proto_ctx = None
7967
7968     def eap_handler(ctx, req):
7969         logger.info("eap_handler - RX " + req.encode("hex"))
7970         if 'num' not in ctx:
7971             ctx['num'] = 0
7972         ctx['num'] = ctx['num'] + 1
7973         if 'id' not in ctx:
7974             ctx['id'] = 1
7975         ctx['id'] = (ctx['id'] + 1) % 256
7976         idx = 0
7977
7978         global eap_fast_proto_ctx
7979         eap_fast_proto_ctx = ctx
7980         ctx['test_done'] = False
7981
7982         idx += 1
7983         if ctx['num'] == idx:
7984             return eap_fast_start(ctx)
7985         idx += 1
7986         if ctx['num'] == idx:
7987             logger.info("EAP-FAST: TLS processing failed")
7988             data = 'ABCDEFGHIK'
7989             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
7990                                4 + 1 + 1 + len(data),
7991                                EAP_TYPE_FAST, 0x01) + data
7992         idx += 1
7993         if ctx['num'] == idx:
7994             ctx['test_done'] = True
7995             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7996
7997         logger.info("Past last test case")
7998         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7999
8000     srv = start_radius_server(eap_handler)
8001     try:
8002         hapd = start_ap(apdev[0])
8003         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8004                        eap="FAST", anonymous_identity="FAST",
8005                        identity="user", password="password",
8006                        ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8007                        phase1="fast_provisioning=1",
8008                        pac_file="blob://fast_pac_proto",
8009                        wait_connect=False)
8010         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
8011         if ev is None:
8012             raise Exception("Could not start EAP-FAST")
8013         ok = False
8014         for i in range(100):
8015             if eap_fast_proto_ctx:
8016                 if eap_fast_proto_ctx['test_done']:
8017                     ok = True
8018                     break
8019             time.sleep(0.05)
8020         dev[0].request("REMOVE_NETWORK all")
8021         dev[0].wait_disconnected()
8022     finally:
8023         stop_radius_server(srv)
8024
8025 def run_eap_fast_phase2(dev, test_payload, test_failure=True):
8026     global eap_fast_proto_ctx
8027     eap_fast_proto_ctx = None
8028
8029     def ssl_info_callback(conn, where, ret):
8030         logger.debug("SSL: info where=%d ret=%d" % (where, ret))
8031
8032     def process_clienthello(ctx, payload):
8033         logger.info("Process ClientHello")
8034         ctx['sslctx'] = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
8035         ctx['sslctx'].set_info_callback(ssl_info_callback)
8036         ctx['sslctx'].load_tmp_dh("auth_serv/dh.conf")
8037         ctx['sslctx'].set_cipher_list("ADH-AES128-SHA")
8038         ctx['conn'] = OpenSSL.SSL.Connection(ctx['sslctx'], None)
8039         ctx['conn'].set_accept_state()
8040         logger.info("State: " + ctx['conn'].state_string())
8041         ctx['conn'].bio_write(payload)
8042         try:
8043             ctx['conn'].do_handshake()
8044         except OpenSSL.SSL.WantReadError:
8045             pass
8046         logger.info("State: " + ctx['conn'].state_string())
8047         data = ctx['conn'].bio_read(4096)
8048         logger.info("State: " + ctx['conn'].state_string())
8049         return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
8050                            4 + 1 + 1 + len(data),
8051                            EAP_TYPE_FAST, 0x01) + data
8052
8053     def process_clientkeyexchange(ctx, payload, appl_data):
8054         logger.info("Process ClientKeyExchange")
8055         logger.info("State: " + ctx['conn'].state_string())
8056         ctx['conn'].bio_write(payload)
8057         try:
8058             ctx['conn'].do_handshake()
8059         except OpenSSL.SSL.WantReadError:
8060             pass
8061         ctx['conn'].send(appl_data)
8062         logger.info("State: " + ctx['conn'].state_string())
8063         data = ctx['conn'].bio_read(4096)
8064         logger.info("State: " + ctx['conn'].state_string())
8065         return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
8066                            4 + 1 + 1 + len(data),
8067                            EAP_TYPE_FAST, 0x01) + data
8068
8069     def eap_handler(ctx, req):
8070         logger.info("eap_handler - RX " + req.encode("hex"))
8071         if 'num' not in ctx:
8072             ctx['num'] = 0
8073         ctx['num'] = ctx['num'] + 1
8074         if 'id' not in ctx:
8075             ctx['id'] = 1
8076         ctx['id'] = (ctx['id'] + 1) % 256
8077         idx = 0
8078
8079         global eap_fast_proto_ctx
8080         eap_fast_proto_ctx = ctx
8081         ctx['test_done'] = False
8082         logger.debug("ctx['num']=%d" % ctx['num'])
8083
8084         idx += 1
8085         if ctx['num'] == idx:
8086             return eap_fast_start(ctx)
8087         idx += 1
8088         if ctx['num'] == idx:
8089             return process_clienthello(ctx, req[6:])
8090         idx += 1
8091         if ctx['num'] == idx:
8092             if not test_failure:
8093                 ctx['test_done'] = True
8094             return process_clientkeyexchange(ctx, req[6:], test_payload)
8095         idx += 1
8096         if ctx['num'] == idx:
8097             ctx['test_done'] = True
8098             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
8099
8100         logger.info("Past last test case")
8101         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
8102
8103     srv = start_radius_server(eap_handler)
8104     try:
8105         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8106                        eap="FAST", anonymous_identity="FAST",
8107                        identity="user", password="password",
8108                        ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8109                        phase1="fast_provisioning=1",
8110                        pac_file="blob://fast_pac_proto",
8111                        wait_connect=False)
8112         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
8113         if ev is None:
8114             raise Exception("Could not start EAP-FAST")
8115         dev[0].dump_monitor()
8116         ok = False
8117         for i in range(100):
8118             if eap_fast_proto_ctx:
8119                 if eap_fast_proto_ctx['test_done']:
8120                     ok = True
8121                     break
8122             time.sleep(0.05)
8123         time.sleep(0.1)
8124         dev[0].request("REMOVE_NETWORK all")
8125         dev[0].wait_disconnected()
8126         if not ok:
8127             raise Exception("EAP-FAST TLS exchange did not complete")
8128         for i in range(3):
8129             dev[i].dump_monitor()
8130     finally:
8131         stop_radius_server(srv)
8132
8133 def test_eap_fast_proto_phase2(dev, apdev):
8134     """EAP-FAST Phase 2 protocol testing"""
8135     if not openssl_imported:
8136         raise HwsimSkip("OpenSSL python method not available")
8137     check_eap_capa(dev[0], "FAST")
8138     hapd = start_ap(apdev[0])
8139
8140     tests = [ ("Too short Phase 2 TLV frame (len=3)",
8141                "ABC",
8142                False),
8143               ("EAP-FAST: TLV overflow",
8144                struct.pack(">HHB", 0, 2, 0xff),
8145                False),
8146               ("EAP-FAST: Unknown TLV (optional and mandatory)",
8147                struct.pack(">HHB", 0, 1, 0xff) +
8148                struct.pack(">HHB", EAP_TLV_TYPE_MANDATORY, 1, 0xff),
8149                True),
8150               ("EAP-FAST: More than one EAP-Payload TLV in the message",
8151                struct.pack(">HHBHHB",
8152                            EAP_TLV_EAP_PAYLOAD_TLV, 1, 0xff,
8153                            EAP_TLV_EAP_PAYLOAD_TLV, 1, 0xff),
8154                True),
8155               ("EAP-FAST: Unknown Result 255 and More than one Result TLV in the message",
8156                struct.pack(">HHHHHH",
8157                            EAP_TLV_RESULT_TLV, 2, 0xff,
8158                            EAP_TLV_RESULT_TLV, 2, 0xff),
8159                True),
8160               ("EAP-FAST: Too short Result TLV",
8161                struct.pack(">HHB", EAP_TLV_RESULT_TLV, 1, 0xff),
8162                True),
8163               ("EAP-FAST: Unknown Intermediate Result 255 and More than one Intermediate-Result TLV in the message",
8164                struct.pack(">HHHHHH",
8165                            EAP_TLV_INTERMEDIATE_RESULT_TLV, 2, 0xff,
8166                            EAP_TLV_INTERMEDIATE_RESULT_TLV, 2, 0xff),
8167                True),
8168               ("EAP-FAST: Too short Intermediate-Result TLV",
8169                struct.pack(">HHB", EAP_TLV_INTERMEDIATE_RESULT_TLV, 1, 0xff),
8170                True),
8171               ("EAP-FAST: More than one Crypto-Binding TLV in the message",
8172                struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*'A' +
8173                struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*'A',
8174                True),
8175               ("EAP-FAST: Too short Crypto-Binding TLV",
8176                struct.pack(">HHB", EAP_TLV_CRYPTO_BINDING_TLV, 1, 0xff),
8177                True),
8178               ("EAP-FAST: More than one Request-Action TLV in the message",
8179                struct.pack(">HHBBHHBB",
8180                            EAP_TLV_REQUEST_ACTION_TLV, 2, 0xff, 0xff,
8181                            EAP_TLV_REQUEST_ACTION_TLV, 2, 0xff, 0xff),
8182                True),
8183               ("EAP-FAST: Too short Request-Action TLV",
8184                struct.pack(">HHB", EAP_TLV_REQUEST_ACTION_TLV, 1, 0xff),
8185                True),
8186               ("EAP-FAST: More than one PAC TLV in the message",
8187                struct.pack(">HHBHHB",
8188                            EAP_TLV_PAC_TLV, 1, 0xff,
8189                            EAP_TLV_PAC_TLV, 1, 0xff),
8190                True),
8191               ("EAP-FAST: Too short EAP Payload TLV (Len=3)",
8192                struct.pack(">HH3B",
8193                            EAP_TLV_EAP_PAYLOAD_TLV, 3, 0, 0, 0),
8194                False),
8195               ("EAP-FAST: Too short Phase 2 request (Len=0)",
8196                struct.pack(">HHBBH",
8197                            EAP_TLV_EAP_PAYLOAD_TLV, 4,
8198                            EAP_CODE_REQUEST, 0, 0),
8199                False),
8200               ("EAP-FAST: EAP packet overflow in EAP Payload TLV",
8201                struct.pack(">HHBBH",
8202                            EAP_TLV_EAP_PAYLOAD_TLV, 4,
8203                            EAP_CODE_REQUEST, 0, 4 + 1),
8204                False),
8205               ("EAP-FAST: Unexpected code=0 in Phase 2 EAP header",
8206                struct.pack(">HHBBH",
8207                            EAP_TLV_EAP_PAYLOAD_TLV, 4,
8208                            0, 0, 0),
8209                False),
8210               ("EAP-FAST: PAC TLV without Result TLV acknowledging success",
8211                struct.pack(">HHB", EAP_TLV_PAC_TLV, 1, 0xff),
8212                True),
8213               ("EAP-FAST: PAC TLV does not include all the required fields",
8214                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8215                            EAP_TLV_RESULT_SUCCESS) +
8216                struct.pack(">HHB", EAP_TLV_PAC_TLV, 1, 0xff),
8217                True),
8218               ("EAP-FAST: Invalid PAC-Key length 0, Ignored unknown PAC type 0, and PAC TLV overrun (type=0 len=2 left=1)",
8219                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8220                            EAP_TLV_RESULT_SUCCESS) +
8221                struct.pack(">HHHHHHHHB", EAP_TLV_PAC_TLV, 4 + 4 + 5,
8222                            PAC_TYPE_PAC_KEY, 0, 0, 0, 0, 2, 0),
8223                True),
8224               ("EAP-FAST: PAC-Info does not include all the required fields",
8225                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8226                            EAP_TLV_RESULT_SUCCESS) +
8227                struct.pack(">HHHHHHHH", EAP_TLV_PAC_TLV, 4 + 4 + 4 + 32,
8228                            PAC_TYPE_PAC_OPAQUE, 0,
8229                            PAC_TYPE_PAC_INFO, 0,
8230                            PAC_TYPE_PAC_KEY, 32) + 32*'A',
8231                True),
8232               ("EAP-FAST: Invalid CRED_LIFETIME length, Ignored unknown PAC-Info type 0, and Invalid PAC-Type length 1",
8233                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8234                            EAP_TLV_RESULT_SUCCESS) +
8235                struct.pack(">HHHHHHHHHHHHBHH", EAP_TLV_PAC_TLV, 4 + 4 + 13 + 4 + 32,
8236                            PAC_TYPE_PAC_OPAQUE, 0,
8237                            PAC_TYPE_PAC_INFO, 13, PAC_TYPE_CRED_LIFETIME, 0,
8238                            0, 0, PAC_TYPE_PAC_TYPE, 1, 0,
8239                            PAC_TYPE_PAC_KEY, 32) + 32*'A',
8240                True),
8241               ("EAP-FAST: Unsupported PAC-Type 0",
8242                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8243                            EAP_TLV_RESULT_SUCCESS) +
8244                struct.pack(">HHHHHHHHHHH", EAP_TLV_PAC_TLV, 4 + 4 + 6 + 4 + 32,
8245                            PAC_TYPE_PAC_OPAQUE, 0,
8246                            PAC_TYPE_PAC_INFO, 6, PAC_TYPE_PAC_TYPE, 2, 0,
8247                            PAC_TYPE_PAC_KEY, 32) + 32*'A',
8248                True),
8249               ("EAP-FAST: PAC-Info overrun (type=0 len=2 left=1)",
8250                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8251                            EAP_TLV_RESULT_SUCCESS) +
8252                struct.pack(">HHHHHHHHBHH", EAP_TLV_PAC_TLV, 4 + 4 + 5 + 4 + 32,
8253                            PAC_TYPE_PAC_OPAQUE, 0,
8254                            PAC_TYPE_PAC_INFO, 5, 0, 2, 1,
8255                            PAC_TYPE_PAC_KEY, 32) + 32*'A',
8256                True),
8257               ("EAP-FAST: Valid PAC",
8258                struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
8259                            EAP_TLV_RESULT_SUCCESS) +
8260                struct.pack(">HHHHHHHHBHHBHH", EAP_TLV_PAC_TLV,
8261                            4 + 4 + 10 + 4 + 32,
8262                            PAC_TYPE_PAC_OPAQUE, 0,
8263                            PAC_TYPE_PAC_INFO, 10, PAC_TYPE_A_ID, 1, 0x41,
8264                            PAC_TYPE_A_ID_INFO, 1, 0x42,
8265                            PAC_TYPE_PAC_KEY, 32) + 32*'A',
8266                True),
8267               ("EAP-FAST: Invalid version/subtype in Crypto-Binding TLV",
8268                struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*'A',
8269                True) ]
8270     for title, payload, failure in tests:
8271         logger.info("Phase 2 test: " + title)
8272         run_eap_fast_phase2(dev, payload, failure)
8273
8274 def test_eap_fast_tlv_nak_oom(dev, apdev):
8275     """EAP-FAST Phase 2 TLV NAK OOM"""
8276     if not openssl_imported:
8277         raise HwsimSkip("OpenSSL python method not available")
8278     check_eap_capa(dev[0], "FAST")
8279     hapd = start_ap(apdev[0])
8280
8281     with alloc_fail(dev[0], 1, "eap_fast_tlv_nak"):
8282         run_eap_fast_phase2(dev, struct.pack(">HHB", EAP_TLV_TYPE_MANDATORY,
8283                                              1, 0xff), False)