Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[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 hmac
8 import logging
9 logger = logging.getLogger()
10 import select
11 import struct
12 import threading
13 import time
14
15 import hostapd
16 from utils import HwsimSkip
17 from test_ap_eap import check_eap_capa
18
19 EAP_CODE_REQUEST = 1
20 EAP_CODE_RESPONSE = 2
21 EAP_CODE_SUCCESS = 3
22 EAP_CODE_FAILURE = 4
23
24 EAP_TYPE_IDENTITY = 1
25 EAP_TYPE_NOTIFICATION = 2
26 EAP_TYPE_NAK = 3
27 EAP_TYPE_MD5 = 4
28 EAP_TYPE_OTP = 5
29 EAP_TYPE_GTC = 6
30 EAP_TYPE_TLS = 13
31 EAP_TYPE_LEAP = 17
32 EAP_TYPE_SIM = 18
33 EAP_TYPE_TTLS = 21
34 EAP_TYPE_AKA = 23
35 EAP_TYPE_PEAP = 25
36 EAP_TYPE_MSCHAPV2 = 26
37 EAP_TYPE_TLV = 33
38 EAP_TYPE_TNC = 38
39 EAP_TYPE_FAST = 43
40 EAP_TYPE_PAX = 46
41 EAP_TYPE_PSK = 47
42 EAP_TYPE_SAKE = 48
43 EAP_TYPE_IKEV2 = 49
44 EAP_TYPE_AKA_PRIME = 50
45 EAP_TYPE_GPSK = 51
46 EAP_TYPE_PWD = 52
47 EAP_TYPE_EKE = 53
48
49 def run_pyrad_server(srv, t_stop, eap_handler):
50     srv.RunWithStop(t_stop, eap_handler)
51
52 def start_radius_server(eap_handler):
53     try:
54         import pyrad.server
55         import pyrad.packet
56         import pyrad.dictionary
57     except ImportError:
58         raise HwsimSkip("No pyrad modules available")
59
60     class TestServer(pyrad.server.Server):
61         def _HandleAuthPacket(self, pkt):
62             pyrad.server.Server._HandleAuthPacket(self, pkt)
63             if len(pkt[79]) > 1:
64                 logger.info("Multiple EAP-Message attributes")
65                 # TODO: reassemble
66             eap = pkt[79][0]
67             eap_req = self.eap_handler(self.ctx, eap)
68             reply = self.CreateReplyPacket(pkt)
69             if eap_req:
70                 while True:
71                     if len(eap_req) > 253:
72                         reply.AddAttribute("EAP-Message", eap_req[0:253])
73                         eap_req = eap_req[253:]
74                     else:
75                         reply.AddAttribute("EAP-Message", eap_req)
76                         break
77             else:
78                 logger.info("No EAP request available")
79             reply.code = pyrad.packet.AccessChallenge
80
81             hmac_obj = hmac.new(reply.secret)
82             hmac_obj.update(struct.pack("B", reply.code))
83             hmac_obj.update(struct.pack("B", reply.id))
84
85             # reply attributes
86             reply.AddAttribute("Message-Authenticator",
87                                "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
88             attrs = reply._PktEncodeAttributes()
89
90             # Length
91             flen = 4 + 16 + len(attrs)
92             hmac_obj.update(struct.pack(">H", flen))
93             hmac_obj.update(pkt.authenticator)
94             hmac_obj.update(attrs)
95             del reply[80]
96             reply.AddAttribute("Message-Authenticator", hmac_obj.digest())
97
98             self.SendReplyPacket(pkt.fd, reply)
99
100         def RunWithStop(self, t_stop, eap_handler):
101             self._poll = select.poll()
102             self._fdmap = {}
103             self._PrepareSockets()
104             self.t_stop = t_stop
105             self.eap_handler = eap_handler
106             self.ctx = {}
107
108             while not t_stop.is_set():
109                 for (fd, event) in self._poll.poll(1000):
110                     if event == select.POLLIN:
111                         try:
112                             fdo = self._fdmap[fd]
113                             self._ProcessInput(fdo)
114                         except pyrad.server.ServerPacketError as err:
115                             logger.info("pyrad server dropping packet: " + str(err))
116                         except pyrad.packet.PacketError as err:
117                             logger.info("pyrad server received invalid packet: " + str(err))
118                     else:
119                         logger.error("Unexpected event in pyrad server main loop")
120
121     srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
122                      authport=18138, acctport=18139)
123     srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
124                                                      "radius",
125                                                      "localhost")
126     srv.BindToAddress("")
127     t_stop = threading.Event()
128     t = threading.Thread(target=run_pyrad_server, args=(srv, t_stop, eap_handler))
129     t.start()
130
131     return { 'srv': srv, 'stop': t_stop, 'thread': t }
132
133 def stop_radius_server(srv):
134     srv['stop'].set()
135     srv['thread'].join()
136
137 def start_ap(ifname):
138     params = hostapd.wpa2_eap_params(ssid="eap-test")
139     params['auth_server_port'] = "18138"
140     hapd = hostapd.add_ap(ifname, params)
141     return hapd
142
143 def test_eap_proto(dev, apdev):
144     """EAP protocol tests"""
145     check_eap_capa(dev[0], "MD5")
146     def eap_handler(ctx, req):
147         logger.info("eap_handler - RX " + req.encode("hex"))
148         if 'num' not in ctx:
149             ctx['num'] = 0
150         ctx['num'] = ctx['num'] + 1
151         if 'id' not in ctx:
152             ctx['id'] = 1
153         ctx['id'] = (ctx['id'] + 1) % 256
154         idx = 0
155
156         idx += 1
157         if ctx['num'] == idx:
158             logger.info("Test: MD5 challenge")
159             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
160                                4 + 1 + 3,
161                                EAP_TYPE_MD5,
162                                1, 0xaa, ord('n'))
163         idx += 1
164         if ctx['num'] == idx:
165             logger.info("Test: EAP-Success - id off by 2")
166             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] + 1, 4)
167
168         idx += 1
169         if ctx['num'] == idx:
170             logger.info("Test: MD5 challenge")
171             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
172                                4 + 1 + 3,
173                                EAP_TYPE_MD5,
174                                1, 0xaa, ord('n'))
175         idx += 1
176         if ctx['num'] == idx:
177             logger.info("Test: EAP-Success - id off by 3")
178             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] + 2, 4)
179
180         idx += 1
181         if ctx['num'] == idx:
182             logger.info("Test: MD5 challenge")
183             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
184                                4 + 1 + 3,
185                                EAP_TYPE_MD5,
186                                1, 0xaa, ord('n'))
187         idx += 1
188         if ctx['num'] == idx:
189             logger.info("Test: EAP-Notification/Request")
190             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
191                                4 + 1 + 1,
192                                EAP_TYPE_NOTIFICATION,
193                                ord('A'))
194         idx += 1
195         if ctx['num'] == idx:
196             logger.info("Test: EAP-Success")
197             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
198
199         idx += 1
200         if ctx['num'] == idx:
201             logger.info("Test: EAP-Notification/Request")
202             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
203                                4 + 1 + 1,
204                                EAP_TYPE_NOTIFICATION,
205                                ord('B'))
206         idx += 1
207         if ctx['num'] == idx:
208             logger.info("Test: MD5 challenge")
209             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
210                                4 + 1 + 3,
211                                EAP_TYPE_MD5,
212                                1, 0xaa, ord('n'))
213         idx += 1
214         if ctx['num'] == idx:
215             logger.info("Test: EAP-Success")
216             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
217
218         idx += 1
219         if ctx['num'] == idx:
220             logger.info("Test: EAP-Notification/Request")
221             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
222                                4 + 1 + 1,
223                                EAP_TYPE_NOTIFICATION,
224                                ord('C'))
225         idx += 1
226         if ctx['num'] == idx:
227             logger.info("Test: MD5 challenge")
228             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
229                                4 + 1 + 3,
230                                EAP_TYPE_MD5,
231                                1, 0xaa, ord('n'))
232         idx += 1
233         if ctx['num'] == idx:
234             logger.info("Test: EAP-Notification/Request")
235             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
236                                4 + 1 + 1,
237                                EAP_TYPE_NOTIFICATION,
238                                ord('D'))
239         idx += 1
240         if ctx['num'] == idx:
241             logger.info("Test: EAP-Success")
242             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
243
244         idx += 1
245         if ctx['num'] == idx:
246             logger.info("Test: EAP-Notification/Request")
247             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
248                                4 + 1 + 1,
249                                EAP_TYPE_NOTIFICATION,
250                                ord('E'))
251         idx += 1
252         if ctx['num'] == idx:
253             logger.info("Test: EAP-Notification/Request (same id)")
254             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'] - 1,
255                                4 + 1 + 1,
256                                EAP_TYPE_NOTIFICATION,
257                                ord('F'))
258         idx += 1
259         if ctx['num'] == idx:
260             logger.info("Test: Unexpected EAP-Success")
261             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 2, 4)
262
263         return None
264
265     srv = start_radius_server(eap_handler)
266
267     try:
268         hapd = start_ap(apdev[0]['ifname'])
269
270         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
271                        eap="MD5", identity="user", password="password",
272                        wait_connect=False)
273         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
274         if ev is None:
275             raise Exception("Timeout on EAP start")
276         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
277         if ev is None:
278             raise Exception("Timeout on EAP success")
279         dev[0].request("REMOVE_NETWORK all")
280
281         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
282                        eap="MD5", identity="user", password="password",
283                        wait_connect=False)
284         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
285         if ev is None:
286             raise Exception("Timeout on EAP start")
287         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=1)
288         if ev is not None:
289             raise Exception("Unexpected EAP success")
290         dev[0].request("REMOVE_NETWORK all")
291
292         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
293                        eap="MD5", identity="user", password="password",
294                        wait_connect=False)
295         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
296         if ev is None:
297             raise Exception("Timeout on EAP start")
298         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
299         if ev is None:
300             raise Exception("Timeout on EAP notification")
301         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION A":
302             raise Exception("Unexpected notification contents: " + ev)
303         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
304         if ev is None:
305             raise Exception("Timeout on EAP success")
306         dev[0].request("REMOVE_NETWORK all")
307
308         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
309                        eap="MD5", identity="user", password="password",
310                        wait_connect=False)
311         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
312         if ev is None:
313             raise Exception("Timeout on EAP notification")
314         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION B":
315             raise Exception("Unexpected notification contents: " + ev)
316         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
317         if ev is None:
318             raise Exception("Timeout on EAP start")
319         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
320         if ev is None:
321             raise Exception("Timeout on EAP success")
322         dev[0].request("REMOVE_NETWORK all")
323
324         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
325                        eap="MD5", identity="user", password="password",
326                        wait_connect=False)
327         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
328         if ev is None:
329             raise Exception("Timeout on EAP notification")
330         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION C":
331             raise Exception("Unexpected notification contents: " + ev)
332         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
333         if ev is None:
334             raise Exception("Timeout on EAP start")
335         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
336         if ev is None:
337             raise Exception("Timeout on EAP notification")
338         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION D":
339             raise Exception("Unexpected notification contents: " + ev)
340         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
341         if ev is None:
342             raise Exception("Timeout on EAP success")
343         dev[0].request("REMOVE_NETWORK all")
344
345         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
346                        eap="MD5", identity="user", password="password",
347                        wait_connect=False)
348         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
349         if ev is None:
350             raise Exception("Timeout on EAP notification")
351         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION E":
352             raise Exception("Unexpected notification contents: " + ev)
353         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
354         if ev is None:
355             raise Exception("Timeout on EAP notification")
356         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION F":
357             raise Exception("Unexpected notification contents: " + ev)
358         ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=15)
359         if ev is None:
360             raise Exception("Timeout on EAP failure")
361         dev[0].request("REMOVE_NETWORK all")
362     finally:
363         stop_radius_server(srv)
364
365 EAP_SAKE_VERSION = 2
366
367 EAP_SAKE_SUBTYPE_CHALLENGE = 1
368 EAP_SAKE_SUBTYPE_CONFIRM = 2
369 EAP_SAKE_SUBTYPE_AUTH_REJECT = 3
370 EAP_SAKE_SUBTYPE_IDENTITY = 4
371
372 EAP_SAKE_AT_RAND_S = 1
373 EAP_SAKE_AT_RAND_P = 2
374 EAP_SAKE_AT_MIC_S = 3
375 EAP_SAKE_AT_MIC_P = 4
376 EAP_SAKE_AT_SERVERID = 5
377 EAP_SAKE_AT_PEERID = 6
378 EAP_SAKE_AT_SPI_S = 7
379 EAP_SAKE_AT_SPI_P = 8
380 EAP_SAKE_AT_ANY_ID_REQ = 9
381 EAP_SAKE_AT_PERM_ID_REQ = 10
382 EAP_SAKE_AT_ENCR_DATA = 128
383 EAP_SAKE_AT_IV = 129
384 EAP_SAKE_AT_PADDING = 130
385 EAP_SAKE_AT_NEXT_TMPID = 131
386 EAP_SAKE_AT_MSK_LIFE = 132
387
388 def test_eap_proto_sake(dev, apdev):
389     """EAP-SAKE protocol tests"""
390     def sake_challenge(ctx):
391         logger.info("Test: Challenge subtype")
392         return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
393                            4 + 1 + 3 + 18,
394                            EAP_TYPE_SAKE,
395                            EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
396                            EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
397
398     def sake_handler(ctx, req):
399         logger.info("sake_handler - RX " + req.encode("hex"))
400         if 'num' not in ctx:
401             ctx['num'] = 0
402         ctx['num'] = ctx['num'] + 1
403         if 'id' not in ctx:
404             ctx['id'] = 1
405         ctx['id'] = (ctx['id'] + 1) % 256
406
407         if ctx['num'] == 1:
408             logger.info("Test: Missing payload")
409             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
410                                EAP_TYPE_SAKE)
411
412         if ctx['num'] == 2:
413             logger.info("Test: Identity subtype without any attributes")
414             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
415                                4 + 1 + 3,
416                                EAP_TYPE_SAKE,
417                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY)
418
419         if ctx['num'] == 3:
420             logger.info("Test: Identity subtype")
421             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
422                                4 + 1 + 3 + 4,
423                                EAP_TYPE_SAKE,
424                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
425                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
426         if ctx['num'] == 4:
427             logger.info("Test: Identity subtype (different session id)")
428             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
429                                4 + 1 + 3 + 4,
430                                EAP_TYPE_SAKE,
431                                EAP_SAKE_VERSION, 1, EAP_SAKE_SUBTYPE_IDENTITY,
432                                EAP_SAKE_AT_PERM_ID_REQ, 4, 0)
433
434         if ctx['num'] == 5:
435             logger.info("Test: Identity subtype with too short attribute")
436             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
437                                4 + 1 + 3 + 2,
438                                EAP_TYPE_SAKE,
439                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
440                                EAP_SAKE_AT_ANY_ID_REQ, 2)
441
442         if ctx['num'] == 6:
443             logger.info("Test: Identity subtype with truncated attribute")
444             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
445                                4 + 1 + 3 + 2,
446                                EAP_TYPE_SAKE,
447                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
448                                EAP_SAKE_AT_ANY_ID_REQ, 4)
449
450         if ctx['num'] == 7:
451             logger.info("Test: Unknown subtype")
452             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
453                                4 + 1 + 3,
454                                EAP_TYPE_SAKE,
455                                EAP_SAKE_VERSION, 0, 123)
456
457         if ctx['num'] == 8:
458             logger.info("Test: Challenge subtype without any attributes")
459             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
460                                4 + 1 + 3,
461                                EAP_TYPE_SAKE,
462                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE)
463
464         if ctx['num'] == 9:
465             logger.info("Test: Challenge subtype with too short AT_RAND_S")
466             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
467                                4 + 1 + 3 + 2,
468                                EAP_TYPE_SAKE,
469                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
470                                EAP_SAKE_AT_RAND_S, 2)
471
472         if ctx['num'] == 10:
473             return sake_challenge(ctx)
474         if ctx['num'] == 11:
475             logger.info("Test: Unexpected Identity subtype")
476             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
477                                4 + 1 + 3 + 4,
478                                EAP_TYPE_SAKE,
479                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
480                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
481
482         if ctx['num'] == 12:
483             return sake_challenge(ctx)
484         if ctx['num'] == 13:
485             logger.info("Test: Unexpected Challenge subtype")
486             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
487                                4 + 1 + 3 + 18,
488                                EAP_TYPE_SAKE,
489                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
490                                EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
491
492         if ctx['num'] == 14:
493             return sake_challenge(ctx)
494         if ctx['num'] == 15:
495             logger.info("Test: Confirm subtype without any attributes")
496             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
497                                4 + 1 + 3,
498                                EAP_TYPE_SAKE,
499                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM)
500
501         if ctx['num'] == 16:
502             return sake_challenge(ctx)
503         if ctx['num'] == 17:
504             logger.info("Test: Confirm subtype with too short AT_MIC_S")
505             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
506                                4 + 1 + 3 + 2,
507                                EAP_TYPE_SAKE,
508                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
509                                EAP_SAKE_AT_MIC_S, 2)
510
511         if ctx['num'] == 18:
512             logger.info("Test: Unexpected Confirm subtype")
513             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
514                                4 + 1 + 3 + 18,
515                                EAP_TYPE_SAKE,
516                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
517                                EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
518
519         if ctx['num'] == 19:
520             return sake_challenge(ctx)
521         if ctx['num'] == 20:
522             logger.info("Test: Confirm subtype with incorrect AT_MIC_S")
523             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
524                                4 + 1 + 3 + 18,
525                                EAP_TYPE_SAKE,
526                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
527                                EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
528
529         return sake_challenge(ctx)
530
531     srv = start_radius_server(sake_handler)
532
533     try:
534         hapd = start_ap(apdev[0]['ifname'])
535
536         for i in range(0, 14):
537             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
538                            eap="SAKE", identity="sake user",
539                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
540                            wait_connect=False)
541             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
542             if ev is None:
543                 raise Exception("Timeout on EAP start")
544             time.sleep(0.1)
545             dev[0].request("REMOVE_NETWORK all")
546
547         logger.info("Too short password")
548         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
549                        eap="SAKE", identity="sake user",
550                        password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd",
551                        wait_connect=False)
552         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
553         if ev is None:
554             raise Exception("Timeout on EAP start")
555         time.sleep(0.1)
556     finally:
557         stop_radius_server(srv)
558
559 def test_eap_proto_leap(dev, apdev):
560     """EAP-LEAP protocol tests"""
561     check_eap_capa(dev[0], "LEAP")
562     def leap_handler(ctx, req):
563         logger.info("leap_handler - RX " + req.encode("hex"))
564         if 'num' not in ctx:
565             ctx['num'] = 0
566         ctx['num'] = ctx['num'] + 1
567         if 'id' not in ctx:
568             ctx['id'] = 1
569         ctx['id'] = (ctx['id'] + 1) % 256
570
571         if ctx['num'] == 1:
572             logger.info("Test: Missing payload")
573             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
574                                4 + 1,
575                                EAP_TYPE_LEAP)
576
577         if ctx['num'] == 2:
578             logger.info("Test: Unexpected version")
579             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
580                                4 + 1 + 3,
581                                EAP_TYPE_LEAP,
582                                0, 0, 0)
583
584         if ctx['num'] == 3:
585             logger.info("Test: Invalid challenge length")
586             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
587                                4 + 1 + 3,
588                                EAP_TYPE_LEAP,
589                                1, 0, 0)
590
591         if ctx['num'] == 4:
592             logger.info("Test: Truncated challenge")
593             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
594                                4 + 1 + 3,
595                                EAP_TYPE_LEAP,
596                                1, 0, 8)
597
598         if ctx['num'] == 5:
599             logger.info("Test: Valid challenge")
600             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
601                                4 + 1 + 3 + 8,
602                                EAP_TYPE_LEAP,
603                                1, 0, 8, 0, 0)
604         if ctx['num'] == 6:
605             logger.info("Test: Missing payload in Response")
606             return struct.pack(">BBHB", EAP_CODE_RESPONSE, ctx['id'],
607                                4 + 1,
608                                EAP_TYPE_LEAP)
609
610         if ctx['num'] == 7:
611             logger.info("Test: Valid challenge")
612             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
613                                4 + 1 + 3 + 8,
614                                EAP_TYPE_LEAP,
615                                1, 0, 8, 0, 0)
616         if ctx['num'] == 8:
617             logger.info("Test: Unexpected version in Response")
618             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
619                                4 + 1 + 3,
620                                EAP_TYPE_LEAP,
621                                0, 0, 8)
622
623         if ctx['num'] == 9:
624             logger.info("Test: Valid challenge")
625             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
626                                4 + 1 + 3 + 8,
627                                EAP_TYPE_LEAP,
628                                1, 0, 8, 0, 0)
629         if ctx['num'] == 10:
630             logger.info("Test: Invalid challenge length in Response")
631             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
632                                4 + 1 + 3,
633                                EAP_TYPE_LEAP,
634                                1, 0, 0)
635
636         if ctx['num'] == 11:
637             logger.info("Test: Valid challenge")
638             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
639                                4 + 1 + 3 + 8,
640                                EAP_TYPE_LEAP,
641                                1, 0, 8, 0, 0)
642         if ctx['num'] == 12:
643             logger.info("Test: Truncated challenge in Response")
644             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
645                                4 + 1 + 3,
646                                EAP_TYPE_LEAP,
647                                1, 0, 24)
648
649         if ctx['num'] == 13:
650             logger.info("Test: Valid challenge")
651             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
652                                4 + 1 + 3 + 8,
653                                EAP_TYPE_LEAP,
654                                1, 0, 8, 0, 0)
655         if ctx['num'] == 14:
656             logger.info("Test: Invalid challange value in Response")
657             return struct.pack(">BBHBBBB6L", EAP_CODE_RESPONSE, ctx['id'],
658                                4 + 1 + 3 + 24,
659                                EAP_TYPE_LEAP,
660                                1, 0, 24,
661                                0, 0, 0, 0, 0, 0)
662
663         if ctx['num'] == 15:
664             logger.info("Test: Valid challenge")
665             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
666                                4 + 1 + 3 + 8,
667                                EAP_TYPE_LEAP,
668                                1, 0, 8, 0, 0)
669         if ctx['num'] == 16:
670             logger.info("Test: Valid challange value in Response")
671             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
672                                4 + 1 + 3 + 24,
673                                EAP_TYPE_LEAP,
674                                1, 0, 24,
675                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
676                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
677                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
678
679         if ctx['num'] == 17:
680             logger.info("Test: Valid challenge")
681             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
682                                4 + 1 + 3 + 8,
683                                EAP_TYPE_LEAP,
684                                1, 0, 8, 0, 0)
685         if ctx['num'] == 18:
686             logger.info("Test: Success")
687             return struct.pack(">BBHB", EAP_CODE_SUCCESS, ctx['id'],
688                                4 + 1,
689                                EAP_TYPE_LEAP)
690         # hostapd will drop the next frame in the sequence
691
692         if ctx['num'] == 19:
693             logger.info("Test: Valid challenge")
694             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
695                                4 + 1 + 3 + 8,
696                                EAP_TYPE_LEAP,
697                                1, 0, 8, 0, 0)
698         if ctx['num'] == 20:
699             logger.info("Test: Failure")
700             return struct.pack(">BBHB", EAP_CODE_FAILURE, ctx['id'],
701                                4 + 1,
702                                EAP_TYPE_LEAP)
703
704         return None
705
706     srv = start_radius_server(leap_handler)
707
708     try:
709         hapd = start_ap(apdev[0]['ifname'])
710
711         for i in range(0, 12):
712             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
713                            eap="LEAP", identity="user", password="password",
714                            wait_connect=False)
715             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
716             if ev is None:
717                 raise Exception("Timeout on EAP start")
718             time.sleep(0.1)
719             if i == 10:
720                 logger.info("Wait for additional roundtrip")
721                 time.sleep(1)
722             dev[0].request("REMOVE_NETWORK all")
723     finally:
724         stop_radius_server(srv)
725
726 def test_eap_proto_md5(dev, apdev):
727     """EAP-MD5 protocol tests"""
728     check_eap_capa(dev[0], "MD5")
729
730     def md5_handler(ctx, req):
731         logger.info("md5_handler - RX " + req.encode("hex"))
732         if 'num' not in ctx:
733             ctx['num'] = 0
734         ctx['num'] = ctx['num'] + 1
735         if 'id' not in ctx:
736             ctx['id'] = 1
737         ctx['id'] = (ctx['id'] + 1) % 256
738
739         if ctx['num'] == 1:
740             logger.info("Test: Missing payload")
741             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
742                                4 + 1,
743                                EAP_TYPE_MD5)
744
745         if ctx['num'] == 2:
746             logger.info("Test: Zero-length challenge")
747             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
748                                4 + 1 + 1,
749                                EAP_TYPE_MD5,
750                                0)
751
752         if ctx['num'] == 3:
753             logger.info("Test: Truncated challenge")
754             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
755                                4 + 1 + 1,
756                                EAP_TYPE_MD5,
757                                1)
758
759         if ctx['num'] == 4:
760             logger.info("Test: Shortest possible challenge and name")
761             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
762                                4 + 1 + 3,
763                                EAP_TYPE_MD5,
764                                1, 0xaa, ord('n'))
765
766         return None
767
768     srv = start_radius_server(md5_handler)
769
770     try:
771         hapd = start_ap(apdev[0]['ifname'])
772
773         for i in range(0, 4):
774             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
775                            eap="MD5", identity="user", password="password",
776                            wait_connect=False)
777             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
778             if ev is None:
779                 raise Exception("Timeout on EAP start")
780             time.sleep(0.1)
781             dev[0].request("REMOVE_NETWORK all")
782     finally:
783         stop_radius_server(srv)
784
785 def test_eap_proto_otp(dev, apdev):
786     """EAP-OTP protocol tests"""
787     def otp_handler(ctx, req):
788         logger.info("otp_handler - RX " + req.encode("hex"))
789         if 'num' not in ctx:
790             ctx['num'] = 0
791         ctx['num'] = ctx['num'] + 1
792         if 'id' not in ctx:
793             ctx['id'] = 1
794         ctx['id'] = (ctx['id'] + 1) % 256
795
796         if ctx['num'] == 1:
797             logger.info("Test: Empty payload")
798             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
799                                4 + 1,
800                                EAP_TYPE_OTP)
801         if ctx['num'] == 2:
802             logger.info("Test: Success")
803             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
804                                4)
805
806         if ctx['num'] == 3:
807             logger.info("Test: Challenge included")
808             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
809                                4 + 1 + 1,
810                                EAP_TYPE_OTP,
811                                ord('A'))
812         if ctx['num'] == 4:
813             logger.info("Test: Success")
814             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
815                                4)
816
817         return None
818
819     srv = start_radius_server(otp_handler)
820
821     try:
822         hapd = start_ap(apdev[0]['ifname'])
823
824         for i in range(0, 1):
825             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
826                            eap="OTP", identity="user", password="password",
827                            wait_connect=False)
828             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
829                                    timeout=15)
830             if ev is None:
831                 raise Exception("Timeout on EAP start")
832             time.sleep(0.1)
833             dev[0].request("REMOVE_NETWORK all")
834
835         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
836                        eap="OTP", identity="user", wait_connect=False)
837         ev = dev[0].wait_event(["CTRL-REQ-OTP"])
838         if ev is None:
839             raise Exception("Request for password timed out")
840         id = ev.split(':')[0].split('-')[-1]
841         dev[0].request("CTRL-RSP-OTP-" + id + ":password")
842         ev = dev[0].wait_event("CTRL-EVENT-EAP-SUCCESS")
843         if ev is None:
844             raise Exception("Success not reported")
845     finally:
846         stop_radius_server(srv)
847
848 EAP_GPSK_OPCODE_GPSK_1 = 1
849 EAP_GPSK_OPCODE_GPSK_2 = 2
850 EAP_GPSK_OPCODE_GPSK_3 = 3
851 EAP_GPSK_OPCODE_GPSK_4 = 4
852 EAP_GPSK_OPCODE_FAIL = 5
853 EAP_GPSK_OPCODE_PROTECTED_FAIL = 6
854
855 def test_eap_proto_gpsk(dev, apdev):
856     """EAP-GPSK protocol tests"""
857     def gpsk_handler(ctx, req):
858         logger.info("gpsk_handler - RX " + req.encode("hex"))
859         if 'num' not in ctx:
860             ctx['num'] = 0
861         ctx['num'] = ctx['num'] + 1
862         if 'id' not in ctx:
863             ctx['id'] = 1
864         ctx['id'] = (ctx['id'] + 1) % 256
865
866         idx = 0
867
868         idx += 1
869         if ctx['num'] == idx:
870             logger.info("Test: Missing payload")
871             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
872                                4 + 1,
873                                EAP_TYPE_GPSK)
874
875         idx += 1
876         if ctx['num'] == idx:
877             logger.info("Test: Unknown opcode")
878             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
879                                4 + 1 + 1,
880                                EAP_TYPE_GPSK,
881                                255)
882
883         idx += 1
884         if ctx['num'] == idx:
885             logger.info("Test: Unexpected GPSK-3")
886             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
887                                4 + 1 + 1,
888                                EAP_TYPE_GPSK,
889                                EAP_GPSK_OPCODE_GPSK_3)
890
891         idx += 1
892         if ctx['num'] == idx:
893             logger.info("Test: GPSK-1 Too short GPSK-1")
894             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
895                                4 + 1 + 1,
896                                EAP_TYPE_GPSK,
897                                EAP_GPSK_OPCODE_GPSK_1)
898
899         idx += 1
900         if ctx['num'] == idx:
901             logger.info("Test: GPSK-1 Truncated ID_Server")
902             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
903                                4 + 1 + 1 + 2,
904                                EAP_TYPE_GPSK,
905                                EAP_GPSK_OPCODE_GPSK_1, 1)
906
907         idx += 1
908         if ctx['num'] == idx:
909             logger.info("Test: GPSK-1 Missing RAND_Server")
910             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
911                                4 + 1 + 1 + 2,
912                                EAP_TYPE_GPSK,
913                                EAP_GPSK_OPCODE_GPSK_1, 0)
914
915         idx += 1
916         if ctx['num'] == idx:
917             logger.info("Test: GPSK-1 Missing CSuite_List")
918             return struct.pack(">BBHBBH8L", EAP_CODE_REQUEST, ctx['id'],
919                                4 + 1 + 1 + 2 + 32,
920                                EAP_TYPE_GPSK,
921                                EAP_GPSK_OPCODE_GPSK_1, 0,
922                                0, 0, 0, 0, 0, 0, 0, 0)
923
924         idx += 1
925         if ctx['num'] == idx:
926             logger.info("Test: GPSK-1 Truncated CSuite_List")
927             return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
928                                4 + 1 + 1 + 2 + 32 + 2,
929                                EAP_TYPE_GPSK,
930                                EAP_GPSK_OPCODE_GPSK_1, 0,
931                                0, 0, 0, 0, 0, 0, 0, 0,
932                                1)
933
934         idx += 1
935         if ctx['num'] == idx:
936             logger.info("Test: GPSK-1 Empty CSuite_List")
937             return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
938                                4 + 1 + 1 + 2 + 32 + 2,
939                                EAP_TYPE_GPSK,
940                                EAP_GPSK_OPCODE_GPSK_1, 0,
941                                0, 0, 0, 0, 0, 0, 0, 0,
942                                0)
943
944         idx += 1
945         if ctx['num'] == idx:
946             logger.info("Test: GPSK-1 Invalid CSuite_List")
947             return struct.pack(">BBHBBH8LHB", EAP_CODE_REQUEST, ctx['id'],
948                                4 + 1 + 1 + 2 + 32 + 2 + 1,
949                                EAP_TYPE_GPSK,
950                                EAP_GPSK_OPCODE_GPSK_1, 0,
951                                0, 0, 0, 0, 0, 0, 0, 0,
952                                1, 0)
953
954         idx += 1
955         if ctx['num'] == idx:
956             logger.info("Test: GPSK-1 No supported CSuite")
957             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
958                                4 + 1 + 1 + 2 + 32 + 2 + 6,
959                                EAP_TYPE_GPSK,
960                                EAP_GPSK_OPCODE_GPSK_1, 0,
961                                0, 0, 0, 0, 0, 0, 0, 0,
962                                6, 0, 0)
963
964         idx += 1
965         if ctx['num'] == idx:
966             logger.info("Test: GPSK-1 Supported CSuite")
967             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
968                                4 + 1 + 1 + 2 + 32 + 2 + 6,
969                                EAP_TYPE_GPSK,
970                                EAP_GPSK_OPCODE_GPSK_1, 0,
971                                0, 0, 0, 0, 0, 0, 0, 0,
972                                6, 0, 1)
973         idx += 1
974         if ctx['num'] == idx:
975             logger.info("Test: Unexpected GPSK-1")
976             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
977                                4 + 1 + 1 + 2 + 32 + 2 + 6,
978                                EAP_TYPE_GPSK,
979                                EAP_GPSK_OPCODE_GPSK_1, 0,
980                                0, 0, 0, 0, 0, 0, 0, 0,
981                                6, 0, 1)
982
983         idx += 1
984         if ctx['num'] == idx:
985             logger.info("Test: GPSK-1 Supported CSuite but too short key")
986             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
987                                4 + 1 + 1 + 2 + 32 + 2 + 6,
988                                EAP_TYPE_GPSK,
989                                EAP_GPSK_OPCODE_GPSK_1, 0,
990                                0, 0, 0, 0, 0, 0, 0, 0,
991                                6, 0, 1)
992
993         idx += 1
994         if ctx['num'] == idx:
995             logger.info("Test: GPSK-1 Supported CSuite")
996             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
997                                4 + 1 + 1 + 2 + 32 + 2 + 6,
998                                EAP_TYPE_GPSK,
999                                EAP_GPSK_OPCODE_GPSK_1, 0,
1000                                0, 0, 0, 0, 0, 0, 0, 0,
1001                                6, 0, 1)
1002         idx += 1
1003         if ctx['num'] == idx:
1004             logger.info("Test: Too short GPSK-3")
1005             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1006                                4 + 1 + 1,
1007                                EAP_TYPE_GPSK,
1008                                EAP_GPSK_OPCODE_GPSK_3)
1009
1010         idx += 1
1011         if ctx['num'] == idx:
1012             logger.info("Test: GPSK-1 Supported CSuite")
1013             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1014                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1015                                EAP_TYPE_GPSK,
1016                                EAP_GPSK_OPCODE_GPSK_1, 0,
1017                                0, 0, 0, 0, 0, 0, 0, 0,
1018                                6, 0, 1)
1019         idx += 1
1020         if ctx['num'] == idx:
1021             logger.info("Test: GPSK-3 Mismatch in RAND_Peer")
1022             return struct.pack(">BBHBB8L", EAP_CODE_REQUEST, ctx['id'],
1023                                4 + 1 + 1 + 32,
1024                                EAP_TYPE_GPSK,
1025                                EAP_GPSK_OPCODE_GPSK_3,
1026                                0, 0, 0, 0, 0, 0, 0, 0)
1027
1028         idx += 1
1029         if ctx['num'] == idx:
1030             logger.info("Test: GPSK-1 Supported CSuite")
1031             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1032                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1033                                EAP_TYPE_GPSK,
1034                                EAP_GPSK_OPCODE_GPSK_1, 0,
1035                                0, 0, 0, 0, 0, 0, 0, 0,
1036                                6, 0, 1)
1037         idx += 1
1038         if ctx['num'] == idx:
1039             logger.info("Test: GPSK-3 Missing RAND_Server")
1040             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1041                               4 + 1 + 1 + 32,
1042                               EAP_TYPE_GPSK,
1043                               EAP_GPSK_OPCODE_GPSK_3)
1044             msg += req[14:46]
1045             return msg
1046
1047         idx += 1
1048         if ctx['num'] == idx:
1049             logger.info("Test: GPSK-1 Supported CSuite")
1050             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1051                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1052                                EAP_TYPE_GPSK,
1053                                EAP_GPSK_OPCODE_GPSK_1, 0,
1054                                0, 0, 0, 0, 0, 0, 0, 0,
1055                                6, 0, 1)
1056         idx += 1
1057         if ctx['num'] == idx:
1058             logger.info("Test: GPSK-3 Mismatch in RAND_Server")
1059             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1060                               4 + 1 + 1 + 32 + 32,
1061                               EAP_TYPE_GPSK,
1062                               EAP_GPSK_OPCODE_GPSK_3)
1063             msg += req[14:46]
1064             msg += struct.pack(">8L", 1, 1, 1, 1, 1, 1, 1, 1)
1065             return msg
1066
1067         idx += 1
1068         if ctx['num'] == idx:
1069             logger.info("Test: GPSK-1 Supported CSuite")
1070             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1071                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1072                                EAP_TYPE_GPSK,
1073                                EAP_GPSK_OPCODE_GPSK_1, 0,
1074                                0, 0, 0, 0, 0, 0, 0, 0,
1075                                6, 0, 1)
1076         idx += 1
1077         if ctx['num'] == idx:
1078             logger.info("Test: GPSK-3 Missing ID_Server")
1079             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1080                               4 + 1 + 1 + 32 + 32,
1081                               EAP_TYPE_GPSK,
1082                               EAP_GPSK_OPCODE_GPSK_3)
1083             msg += req[14:46]
1084             msg += struct.pack(">8L", 0, 0, 0, 0, 0, 0, 0, 0)
1085             return msg
1086
1087         idx += 1
1088         if ctx['num'] == idx:
1089             logger.info("Test: GPSK-1 Supported CSuite")
1090             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1091                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1092                                EAP_TYPE_GPSK,
1093                                EAP_GPSK_OPCODE_GPSK_1, 0,
1094                                0, 0, 0, 0, 0, 0, 0, 0,
1095                                6, 0, 1)
1096         idx += 1
1097         if ctx['num'] == idx:
1098             logger.info("Test: GPSK-3 Truncated ID_Server")
1099             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1100                               4 + 1 + 1 + 32 + 32 + 2,
1101                               EAP_TYPE_GPSK,
1102                               EAP_GPSK_OPCODE_GPSK_3)
1103             msg += req[14:46]
1104             msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 1)
1105             return msg
1106
1107         idx += 1
1108         if ctx['num'] == idx:
1109             logger.info("Test: GPSK-1 Supported CSuite")
1110             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1111                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1112                                EAP_TYPE_GPSK,
1113                                EAP_GPSK_OPCODE_GPSK_1, 0,
1114                                0, 0, 0, 0, 0, 0, 0, 0,
1115                                6, 0, 1)
1116         idx += 1
1117         if ctx['num'] == idx:
1118             logger.info("Test: GPSK-3 Mismatch in ID_Server")
1119             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1120                               4 + 1 + 1 + 32 + 32 + 3,
1121                               EAP_TYPE_GPSK,
1122                               EAP_GPSK_OPCODE_GPSK_3)
1123             msg += req[14:46]
1124             msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
1125             return msg
1126
1127         idx += 1
1128         if ctx['num'] == idx:
1129             logger.info("Test: GPSK-1 Supported CSuite")
1130             return struct.pack(">BBHBBHB8LHLH", EAP_CODE_REQUEST, ctx['id'],
1131                                4 + 1 + 1 + 3 + 32 + 2 + 6,
1132                                EAP_TYPE_GPSK,
1133                                EAP_GPSK_OPCODE_GPSK_1, 1, ord('A'),
1134                                0, 0, 0, 0, 0, 0, 0, 0,
1135                                6, 0, 1)
1136         idx += 1
1137         if ctx['num'] == idx:
1138             logger.info("Test: GPSK-3 Mismatch in ID_Server (same length)")
1139             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1140                               4 + 1 + 1 + 32 + 32 + 3,
1141                               EAP_TYPE_GPSK,
1142                               EAP_GPSK_OPCODE_GPSK_3)
1143             msg += req[15:47]
1144             msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
1145             return msg
1146
1147         idx += 1
1148         if ctx['num'] == idx:
1149             logger.info("Test: GPSK-1 Supported CSuite")
1150             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1151                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1152                                EAP_TYPE_GPSK,
1153                                EAP_GPSK_OPCODE_GPSK_1, 0,
1154                                0, 0, 0, 0, 0, 0, 0, 0,
1155                                6, 0, 1)
1156         idx += 1
1157         if ctx['num'] == idx:
1158             logger.info("Test: GPSK-3 Missing CSuite_Sel")
1159             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1160                               4 + 1 + 1 + 32 + 32 + 2,
1161                               EAP_TYPE_GPSK,
1162                               EAP_GPSK_OPCODE_GPSK_3)
1163             msg += req[14:46]
1164             msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 0)
1165             return msg
1166
1167         idx += 1
1168         if ctx['num'] == idx:
1169             logger.info("Test: GPSK-1 Supported CSuite")
1170             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1171                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1172                                EAP_TYPE_GPSK,
1173                                EAP_GPSK_OPCODE_GPSK_1, 0,
1174                                0, 0, 0, 0, 0, 0, 0, 0,
1175                                6, 0, 1)
1176         idx += 1
1177         if ctx['num'] == idx:
1178             logger.info("Test: GPSK-3 Mismatch in CSuite_Sel")
1179             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1180                               4 + 1 + 1 + 32 + 32 + 2 + 6,
1181                               EAP_TYPE_GPSK,
1182                               EAP_GPSK_OPCODE_GPSK_3)
1183             msg += req[14:46]
1184             msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2)
1185             return msg
1186
1187         idx += 1
1188         if ctx['num'] == idx:
1189             logger.info("Test: GPSK-1 Supported CSuite")
1190             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1191                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1192                                EAP_TYPE_GPSK,
1193                                EAP_GPSK_OPCODE_GPSK_1, 0,
1194                                0, 0, 0, 0, 0, 0, 0, 0,
1195                                6, 0, 1)
1196         idx += 1
1197         if ctx['num'] == idx:
1198             logger.info("Test: GPSK-3 Missing len(PD_Payload_Block)")
1199             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1200                               4 + 1 + 1 + 32 + 32 + 2 + 6,
1201                               EAP_TYPE_GPSK,
1202                               EAP_GPSK_OPCODE_GPSK_3)
1203             msg += req[14:46]
1204             msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
1205             return msg
1206
1207         idx += 1
1208         if ctx['num'] == idx:
1209             logger.info("Test: GPSK-1 Supported CSuite")
1210             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1211                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1212                                EAP_TYPE_GPSK,
1213                                EAP_GPSK_OPCODE_GPSK_1, 0,
1214                                0, 0, 0, 0, 0, 0, 0, 0,
1215                                6, 0, 1)
1216         idx += 1
1217         if ctx['num'] == idx:
1218             logger.info("Test: GPSK-3 Truncated PD_Payload_Block")
1219             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1220                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 2,
1221                               EAP_TYPE_GPSK,
1222                               EAP_GPSK_OPCODE_GPSK_3)
1223             msg += req[14:46]
1224             msg += struct.pack(">8LHLHH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
1225             return msg
1226
1227         idx += 1
1228         if ctx['num'] == idx:
1229             logger.info("Test: GPSK-1 Supported CSuite")
1230             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1231                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1232                                EAP_TYPE_GPSK,
1233                                EAP_GPSK_OPCODE_GPSK_1, 0,
1234                                0, 0, 0, 0, 0, 0, 0, 0,
1235                                6, 0, 1)
1236         idx += 1
1237         if ctx['num'] == idx:
1238             logger.info("Test: GPSK-3 Missing MAC")
1239             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1240                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 3,
1241                               EAP_TYPE_GPSK,
1242                               EAP_GPSK_OPCODE_GPSK_3)
1243             msg += req[14:46]
1244             msg += struct.pack(">8LHLHHB",
1245                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123)
1246             return msg
1247
1248         idx += 1
1249         if ctx['num'] == idx:
1250             logger.info("Test: GPSK-1 Supported CSuite")
1251             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1252                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1253                                EAP_TYPE_GPSK,
1254                                EAP_GPSK_OPCODE_GPSK_1, 0,
1255                                0, 0, 0, 0, 0, 0, 0, 0,
1256                                6, 0, 1)
1257         idx += 1
1258         if ctx['num'] == idx:
1259             logger.info("Test: GPSK-3 Incorrect MAC")
1260             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1261                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 3 + 16,
1262                               EAP_TYPE_GPSK,
1263                               EAP_GPSK_OPCODE_GPSK_3)
1264             msg += req[14:46]
1265             msg += struct.pack(">8LHLHHB4L",
1266                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123,
1267                                0, 0, 0, 0)
1268             return msg
1269
1270         return None
1271
1272     srv = start_radius_server(gpsk_handler)
1273
1274     try:
1275         hapd = start_ap(apdev[0]['ifname'])
1276
1277         for i in range(0, 27):
1278             if i == 12:
1279                 pw = "short"
1280             else:
1281                 pw = "abcdefghijklmnop0123456789abcdef"
1282             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1283                            eap="GPSK", identity="user", password=pw,
1284                            wait_connect=False)
1285             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
1286                                    timeout=15)
1287             if ev is None:
1288                 raise Exception("Timeout on EAP start")
1289             time.sleep(0.05)
1290             dev[0].request("REMOVE_NETWORK all")
1291     finally:
1292         stop_radius_server(srv)
1293
1294 EAP_EKE_ID = 1
1295 EAP_EKE_COMMIT = 2
1296 EAP_EKE_CONFIRM = 3
1297 EAP_EKE_FAILURE = 4
1298
1299 def test_eap_proto_eke(dev, apdev):
1300     """EAP-EKE protocol tests"""
1301     def eke_handler(ctx, req):
1302         logger.info("eke_handler - RX " + req.encode("hex"))
1303         if 'num' not in ctx:
1304             ctx['num'] = 0
1305         ctx['num'] = ctx['num'] + 1
1306         if 'id' not in ctx:
1307             ctx['id'] = 1
1308         ctx['id'] = (ctx['id'] + 1) % 256
1309
1310         idx = 0
1311
1312         idx += 1
1313         if ctx['num'] == idx:
1314             logger.info("Test: Missing payload")
1315             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1316                                4 + 1,
1317                                EAP_TYPE_EKE)
1318
1319         idx += 1
1320         if ctx['num'] == idx:
1321             logger.info("Test: Unknown exchange")
1322             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1323                                4 + 1 + 1,
1324                                EAP_TYPE_EKE,
1325                                255)
1326
1327         idx += 1
1328         if ctx['num'] == idx:
1329             logger.info("Test: No NumProposals in EAP-EKE-ID/Request")
1330             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1331                                4 + 1 + 1,
1332                                EAP_TYPE_EKE,
1333                                EAP_EKE_ID)
1334         idx += 1
1335         if ctx['num'] == idx:
1336             logger.info("Test: EAP-Failure")
1337             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1338
1339         idx += 1
1340         if ctx['num'] == idx:
1341             logger.info("Test: NumProposals=0 in EAP-EKE-ID/Request")
1342             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
1343                                4 + 1 + 1 + 1,
1344                                EAP_TYPE_EKE,
1345                                EAP_EKE_ID,
1346                                0)
1347         idx += 1
1348         if ctx['num'] == idx:
1349             logger.info("Test: EAP-Failure")
1350             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1351
1352         idx += 1
1353         if ctx['num'] == idx:
1354             logger.info("Test: Truncated Proposals list in EAP-EKE-ID/Request")
1355             return struct.pack(">BBHBBBB4B", EAP_CODE_REQUEST, ctx['id'],
1356                                4 + 1 + 1 + 2 + 4,
1357                                EAP_TYPE_EKE,
1358                                EAP_EKE_ID,
1359                                2, 0, 0, 0, 0, 0)
1360         idx += 1
1361         if ctx['num'] == idx:
1362             logger.info("Test: EAP-Failure")
1363             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1364
1365         idx += 1
1366         if ctx['num'] == idx:
1367             logger.info("Test: Unsupported proposals in EAP-EKE-ID/Request")
1368             return struct.pack(">BBHBBBB4B4B4B4B", EAP_CODE_REQUEST, ctx['id'],
1369                                4 + 1 + 1 + 2 + 4 * 4,
1370                                EAP_TYPE_EKE,
1371                                EAP_EKE_ID,
1372                                4, 0,
1373                                0, 0, 0, 0,
1374                                3, 0, 0, 0,
1375                                3, 1, 0, 0,
1376                                3, 1, 1, 0)
1377         idx += 1
1378         if ctx['num'] == idx:
1379             logger.info("Test: EAP-Failure")
1380             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1381
1382         idx += 1
1383         if ctx['num'] == idx:
1384             logger.info("Test: Missing IDType/Identity in EAP-EKE-ID/Request")
1385             return struct.pack(">BBHBBBB4B4B4B4B4B",
1386                                EAP_CODE_REQUEST, ctx['id'],
1387                                4 + 1 + 1 + 2 + 5 * 4,
1388                                EAP_TYPE_EKE,
1389                                EAP_EKE_ID,
1390                                5, 0,
1391                                0, 0, 0, 0,
1392                                3, 0, 0, 0,
1393                                3, 1, 0, 0,
1394                                3, 1, 1, 0,
1395                                3, 1, 1, 1)
1396         idx += 1
1397         if ctx['num'] == idx:
1398             logger.info("Test: EAP-Failure")
1399             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1400
1401         idx += 1
1402         if ctx['num'] == idx:
1403             logger.info("Test: Valid EAP-EKE-ID/Request")
1404             return struct.pack(">BBHBBBB4BB",
1405                                EAP_CODE_REQUEST, ctx['id'],
1406                                4 + 1 + 1 + 2 + 4 + 1,
1407                                EAP_TYPE_EKE,
1408                                EAP_EKE_ID,
1409                                1, 0,
1410                                3, 1, 1, 1,
1411                                255)
1412         idx += 1
1413         if ctx['num'] == idx:
1414             logger.info("Test: Unexpected EAP-EKE-ID/Request")
1415             return struct.pack(">BBHBBBB4BB",
1416                                EAP_CODE_REQUEST, ctx['id'],
1417                                4 + 1 + 1 + 2 + 4 + 1,
1418                                EAP_TYPE_EKE,
1419                                EAP_EKE_ID,
1420                                1, 0,
1421                                3, 1, 1, 1,
1422                                255)
1423         idx += 1
1424         if ctx['num'] == idx:
1425             logger.info("Test: EAP-Failure")
1426             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1427
1428         idx += 1
1429         if ctx['num'] == idx:
1430             logger.info("Test: Valid EAP-EKE-ID/Request")
1431             return struct.pack(">BBHBBBB4BB",
1432                                EAP_CODE_REQUEST, ctx['id'],
1433                                4 + 1 + 1 + 2 + 4 + 1,
1434                                EAP_TYPE_EKE,
1435                                EAP_EKE_ID,
1436                                1, 0,
1437                                3, 1, 1, 1,
1438                                255)
1439         idx += 1
1440         if ctx['num'] == idx:
1441             logger.info("Test: Unexpected EAP-EKE-Confirm/Request")
1442             return struct.pack(">BBHBB",
1443                                EAP_CODE_REQUEST, ctx['id'],
1444                                4 + 1 + 1,
1445                                EAP_TYPE_EKE,
1446                                EAP_EKE_CONFIRM)
1447         idx += 1
1448         if ctx['num'] == idx:
1449             logger.info("Test: EAP-Failure")
1450             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1451
1452         idx += 1
1453         if ctx['num'] == idx:
1454             logger.info("Test: Too short EAP-EKE-Failure/Request")
1455             return struct.pack(">BBHBB",
1456                                EAP_CODE_REQUEST, ctx['id'],
1457                                4 + 1 + 1,
1458                                EAP_TYPE_EKE,
1459                                EAP_EKE_FAILURE)
1460         idx += 1
1461         if ctx['num'] == idx:
1462             logger.info("Test: EAP-Failure")
1463             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1464
1465         idx += 1
1466         if ctx['num'] == idx:
1467             logger.info("Test: Unexpected EAP-EKE-Commit/Request")
1468             return struct.pack(">BBHBB",
1469                                EAP_CODE_REQUEST, ctx['id'],
1470                                4 + 1 + 1,
1471                                EAP_TYPE_EKE,
1472                                EAP_EKE_COMMIT)
1473         idx += 1
1474         if ctx['num'] == idx:
1475             logger.info("Test: EAP-Failure")
1476             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1477
1478         idx += 1
1479         if ctx['num'] == idx:
1480             logger.info("Test: Valid EAP-EKE-ID/Request")
1481             return struct.pack(">BBHBBBB4BB",
1482                                EAP_CODE_REQUEST, ctx['id'],
1483                                4 + 1 + 1 + 2 + 4 + 1,
1484                                EAP_TYPE_EKE,
1485                                EAP_EKE_ID,
1486                                1, 0,
1487                                3, 1, 1, 1,
1488                                255)
1489         idx += 1
1490         if ctx['num'] == idx:
1491             logger.info("Test: Too short EAP-EKE-Commit/Request")
1492             return struct.pack(">BBHBB",
1493                                EAP_CODE_REQUEST, ctx['id'],
1494                                4 + 1 + 1,
1495                                EAP_TYPE_EKE,
1496                                EAP_EKE_COMMIT)
1497         idx += 1
1498         if ctx['num'] == idx:
1499             logger.info("Test: EAP-Failure")
1500             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1501
1502         idx += 1
1503         if ctx['num'] == idx:
1504             logger.info("Test: Valid EAP-EKE-ID/Request")
1505             return struct.pack(">BBHBBBB4BB",
1506                                EAP_CODE_REQUEST, ctx['id'],
1507                                4 + 1 + 1 + 2 + 4 + 1,
1508                                EAP_TYPE_EKE,
1509                                EAP_EKE_ID,
1510                                1, 0,
1511                                1, 1, 1, 1,
1512                                255)
1513         idx += 1
1514         if ctx['num'] == idx:
1515             logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
1516             return struct.pack(">BBHBB4L32L",
1517                                EAP_CODE_REQUEST, ctx['id'],
1518                                4 + 1 + 1 + 16 + 128,
1519                                EAP_TYPE_EKE,
1520                                EAP_EKE_COMMIT,
1521                                0, 0, 0, 0,
1522                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1523                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1524         idx += 1
1525         if ctx['num'] == idx:
1526             logger.info("Test: Too short EAP-EKE-Confirm/Request")
1527             return struct.pack(">BBHBB",
1528                                EAP_CODE_REQUEST, ctx['id'],
1529                                4 + 1 + 1,
1530                                EAP_TYPE_EKE,
1531                                EAP_EKE_CONFIRM)
1532         idx += 1
1533         if ctx['num'] == idx:
1534             logger.info("Test: EAP-Failure")
1535             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1536
1537         idx += 1
1538         if ctx['num'] == idx:
1539             logger.info("Test: Valid EAP-EKE-ID/Request")
1540             return struct.pack(">BBHBBBB4BB",
1541                                EAP_CODE_REQUEST, ctx['id'],
1542                                4 + 1 + 1 + 2 + 4 + 1,
1543                                EAP_TYPE_EKE,
1544                                EAP_EKE_ID,
1545                                1, 0,
1546                                1, 1, 1, 1,
1547                                255)
1548         idx += 1
1549         if ctx['num'] == idx:
1550             logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
1551             return struct.pack(">BBHBB4L32L",
1552                                EAP_CODE_REQUEST, ctx['id'],
1553                                4 + 1 + 1 + 16 + 128,
1554                                EAP_TYPE_EKE,
1555                                EAP_EKE_COMMIT,
1556                                0, 0, 0, 0,
1557                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1558                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1559         idx += 1
1560         if ctx['num'] == idx:
1561             logger.info("Test: Invalid PNonce_PS and Auth_S values in EAP-EKE-Confirm/Request")
1562             return struct.pack(">BBHBB4L8L5L5L",
1563                                EAP_CODE_REQUEST, ctx['id'],
1564                                4 + 1 + 1 + 16 + 2 * 16 + 20 + 20,
1565                                EAP_TYPE_EKE,
1566                                EAP_EKE_CONFIRM,
1567                                0, 0, 0, 0,
1568                                0, 0, 0, 0, 0, 0, 0, 0,
1569                                0, 0, 0, 0, 0,
1570                                0, 0, 0, 0, 0)
1571         idx += 1
1572         if ctx['num'] == idx:
1573             logger.info("Test: EAP-Failure")
1574             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1575
1576         return None
1577
1578     srv = start_radius_server(eke_handler)
1579
1580     try:
1581         hapd = start_ap(apdev[0]['ifname'])
1582
1583         for i in range(0, 14):
1584             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1585                            eap="EKE", identity="user", password="password",
1586                            wait_connect=False)
1587             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
1588                                    timeout=15)
1589             if ev is None:
1590                 raise Exception("Timeout on EAP start")
1591             if i in [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]:
1592                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
1593                                        timeout=10)
1594                 if ev is None:
1595                     raise Exception("Timeout on EAP failure")
1596             else:
1597                 time.sleep(0.05)
1598             dev[0].request("REMOVE_NETWORK all")
1599             dev[0].dump_monitor()
1600     finally:
1601         stop_radius_server(srv)
1602
1603 EAP_PAX_OP_STD_1 = 0x01
1604 EAP_PAX_OP_STD_2 = 0x02
1605 EAP_PAX_OP_STD_3 = 0x03
1606 EAP_PAX_OP_SEC_1 = 0x11
1607 EAP_PAX_OP_SEC_2 = 0x12
1608 EAP_PAX_OP_SEC_3 = 0x13
1609 EAP_PAX_OP_SEC_4 = 0x14
1610 EAP_PAX_OP_SEC_5 = 0x15
1611 EAP_PAX_OP_ACK = 0x21
1612
1613 EAP_PAX_FLAGS_MF = 0x01
1614 EAP_PAX_FLAGS_CE = 0x02
1615 EAP_PAX_FLAGS_AI = 0x04
1616
1617 EAP_PAX_MAC_HMAC_SHA1_128 = 0x01
1618 EAP_PAX_HMAC_SHA256_128 = 0x02
1619
1620 EAP_PAX_DH_GROUP_NONE = 0x00
1621 EAP_PAX_DH_GROUP_2048_MODP = 0x01
1622 EAP_PAX_DH_GROUP_3072_MODP = 0x02
1623 EAP_PAX_DH_GROUP_NIST_ECC_P_256 = 0x03
1624
1625 EAP_PAX_PUBLIC_KEY_NONE = 0x00
1626 EAP_PAX_PUBLIC_KEY_RSAES_OAEP = 0x01
1627 EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 = 0x02
1628 EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC = 0x03
1629
1630 EAP_PAX_ADE_VENDOR_SPECIFIC = 0x01
1631 EAP_PAX_ADE_CLIENT_CHANNEL_BINDING = 0x02
1632 EAP_PAX_ADE_SERVER_CHANNEL_BINDING = 0x03
1633
1634 def test_eap_proto_pax(dev, apdev):
1635     """EAP-PAX protocol tests"""
1636     def pax_std_1(ctx):
1637             logger.info("Test: STD-1")
1638             ctx['id'] = 10
1639             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1640                                4 + 1 + 5 + 2 + 32 + 16,
1641                                EAP_TYPE_PAX,
1642                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1643                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1644                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1645                                0x16, 0xc9, 0x08, 0x9d, 0x98, 0xa5, 0x6e, 0x1f,
1646                                0xf0, 0xac, 0xcf, 0xc4, 0x66, 0xcd, 0x2d, 0xbf)
1647
1648     def pax_handler(ctx, req):
1649         logger.info("pax_handler - RX " + req.encode("hex"))
1650         if 'num' not in ctx:
1651             ctx['num'] = 0
1652         ctx['num'] = ctx['num'] + 1
1653         if 'id' not in ctx:
1654             ctx['id'] = 1
1655         ctx['id'] = (ctx['id'] + 1) % 256
1656
1657         idx = 0
1658
1659         idx += 1
1660         if ctx['num'] == idx:
1661             logger.info("Test: Missing payload")
1662             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1663                                4 + 1,
1664                                EAP_TYPE_PAX)
1665
1666         idx += 1
1667         if ctx['num'] == idx:
1668             logger.info("Test: Minimum length payload")
1669             return struct.pack(">BBHB4L", EAP_CODE_REQUEST, ctx['id'],
1670                                4 + 1 + 16,
1671                                EAP_TYPE_PAX,
1672                                0, 0, 0, 0)
1673
1674         idx += 1
1675         if ctx['num'] == idx:
1676             logger.info("Test: Unsupported MAC ID")
1677             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
1678                                4 + 1 + 5 + 16,
1679                                EAP_TYPE_PAX,
1680                                EAP_PAX_OP_STD_1, 0, 255, EAP_PAX_DH_GROUP_NONE,
1681                                EAP_PAX_PUBLIC_KEY_NONE,
1682                                0, 0, 0, 0)
1683
1684         idx += 1
1685         if ctx['num'] == idx:
1686             logger.info("Test: Unsupported DH Group ID")
1687             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
1688                                4 + 1 + 5 + 16,
1689                                EAP_TYPE_PAX,
1690                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1691                                255, EAP_PAX_PUBLIC_KEY_NONE,
1692                                0, 0, 0, 0)
1693
1694         idx += 1
1695         if ctx['num'] == idx:
1696             logger.info("Test: Unsupported Public Key ID")
1697             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
1698                                4 + 1 + 5 + 16,
1699                                EAP_TYPE_PAX,
1700                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1701                                EAP_PAX_DH_GROUP_NONE, 255,
1702                                0, 0, 0, 0)
1703
1704         idx += 1
1705         if ctx['num'] == idx:
1706             logger.info("Test: More fragments")
1707             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
1708                                4 + 1 + 5 + 16,
1709                                EAP_TYPE_PAX,
1710                                EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_MF,
1711                                EAP_PAX_MAC_HMAC_SHA1_128,
1712                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1713                                0, 0, 0, 0)
1714
1715         idx += 1
1716         if ctx['num'] == idx:
1717             logger.info("Test: Invalid ICV")
1718             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
1719                                4 + 1 + 5 + 16,
1720                                EAP_TYPE_PAX,
1721                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1722                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1723                                0, 0, 0, 0)
1724
1725         idx += 1
1726         if ctx['num'] == idx:
1727             logger.info("Test: Invalid ICV in short frame")
1728             return struct.pack(">BBHBBBBBB3L", EAP_CODE_REQUEST, ctx['id'],
1729                                4 + 1 + 5 + 12,
1730                                EAP_TYPE_PAX,
1731                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1732                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1733                                0, 0, 0)
1734
1735         idx += 1
1736         if ctx['num'] == idx:
1737             logger.info("Test: Correct ICV - unsupported op_code")
1738             ctx['id'] = 10
1739             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
1740                                4 + 1 + 5 + 16,
1741                                EAP_TYPE_PAX,
1742                                255, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1743                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1744                                0x90, 0x78, 0x97, 0x38, 0x29, 0x94, 0x32, 0xd4,
1745                                0x81, 0x27, 0xe0, 0xf6, 0x3b, 0x0d, 0xb2, 0xb2)
1746
1747         idx += 1
1748         if ctx['num'] == idx:
1749             logger.info("Test: Correct ICV - CE flag in STD-1")
1750             ctx['id'] = 10
1751             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
1752                                4 + 1 + 5 + 16,
1753                                EAP_TYPE_PAX,
1754                                EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_CE,
1755                                EAP_PAX_MAC_HMAC_SHA1_128,
1756                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1757                                0x9c, 0x98, 0xb4, 0x0b, 0x94, 0x90, 0xde, 0x88,
1758                                0xb7, 0x72, 0x63, 0x44, 0x1d, 0xe3, 0x7c, 0x5c)
1759
1760         idx += 1
1761         if ctx['num'] == idx:
1762             logger.info("Test: Correct ICV - too short STD-1 payload")
1763             ctx['id'] = 10
1764             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
1765                                4 + 1 + 5 + 16,
1766                                EAP_TYPE_PAX,
1767                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1768                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1769                                0xda, 0xab, 0x2c, 0xe7, 0x84, 0x41, 0xb5, 0x5c,
1770                                0xee, 0xcf, 0x62, 0x03, 0xc5, 0x69, 0xcb, 0xf4)
1771
1772         idx += 1
1773         if ctx['num'] == idx:
1774             logger.info("Test: Correct ICV - incorrect A length in STD-1")
1775             ctx['id'] = 10
1776             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1777                                4 + 1 + 5 + 2 + 32 + 16,
1778                                EAP_TYPE_PAX,
1779                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1780                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1781                                0, 0, 0, 0, 0, 0, 0, 0, 0,
1782                                0xc4, 0xb0, 0x81, 0xe4, 0x6c, 0x8c, 0x20, 0x23,
1783                                0x60, 0x46, 0x89, 0xea, 0x94, 0x60, 0xf3, 0x2a)
1784
1785         idx += 1
1786         if ctx['num'] == idx:
1787             logger.info("Test: Correct ICV - extra data in STD-1")
1788             ctx['id'] = 10
1789             return struct.pack(">BBHBBBBBBH8LB16B", EAP_CODE_REQUEST, ctx['id'],
1790                                4 + 1 + 5 + 2 + 32 + 1 + 16,
1791                                EAP_TYPE_PAX,
1792                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1793                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1794                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1795                                1,
1796                                0x61, 0x49, 0x65, 0x37, 0x21, 0xe8, 0xd8, 0xbf,
1797                                0xf3, 0x02, 0x01, 0xe5, 0x42, 0x51, 0xd3, 0x34)
1798         idx += 1
1799         if ctx['num'] == idx:
1800             logger.info("Test: Unexpected STD-1")
1801             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1802                                4 + 1 + 5 + 2 + 32 + 16,
1803                                EAP_TYPE_PAX,
1804                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1805                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1806                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1807                                0xe5, 0x1d, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
1808                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
1809
1810         idx += 1
1811         if ctx['num'] == idx:
1812             return pax_std_1(ctx)
1813         idx += 1
1814         if ctx['num'] == idx:
1815             logger.info("Test: MAC ID changed during session")
1816             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1817                                4 + 1 + 5 + 2 + 32 + 16,
1818                                EAP_TYPE_PAX,
1819                                EAP_PAX_OP_STD_1, 0, EAP_PAX_HMAC_SHA256_128,
1820                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1821                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1822                                0xee, 0x00, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
1823                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
1824
1825         idx += 1
1826         if ctx['num'] == idx:
1827             return pax_std_1(ctx)
1828         idx += 1
1829         if ctx['num'] == idx:
1830             logger.info("Test: DH Group ID changed during session")
1831             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1832                                4 + 1 + 5 + 2 + 32 + 16,
1833                                EAP_TYPE_PAX,
1834                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1835                                EAP_PAX_DH_GROUP_2048_MODP,
1836                                EAP_PAX_PUBLIC_KEY_NONE,
1837                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1838                                0xee, 0x01, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
1839                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
1840
1841         idx += 1
1842         if ctx['num'] == idx:
1843             return pax_std_1(ctx)
1844         idx += 1
1845         if ctx['num'] == idx:
1846             logger.info("Test: Public Key ID changed during session")
1847             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1848                                4 + 1 + 5 + 2 + 32 + 16,
1849                                EAP_TYPE_PAX,
1850                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1851                                EAP_PAX_DH_GROUP_NONE,
1852                                EAP_PAX_PUBLIC_KEY_RSAES_OAEP,
1853                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1854                                0xee, 0x02, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
1855                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
1856
1857         idx += 1
1858         if ctx['num'] == idx:
1859             logger.info("Test: Unexpected STD-3")
1860             ctx['id'] = 10
1861             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1862                                4 + 1 + 5 + 2 + 32 + 16,
1863                                EAP_TYPE_PAX,
1864                                EAP_PAX_OP_STD_3, 0, EAP_PAX_MAC_HMAC_SHA1_128,
1865                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1866                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1867                                0x47, 0xbb, 0xc0, 0xf9, 0xb9, 0x69, 0xf5, 0xcb,
1868                                0x3a, 0xe8, 0xe7, 0xd6, 0x80, 0x28, 0xf2, 0x59)
1869
1870         idx += 1
1871         if ctx['num'] == idx:
1872             return pax_std_1(ctx)
1873         idx += 1
1874         if ctx['num'] == idx:
1875             # TODO: MAC calculation; for now, this gets dropped due to incorrect
1876             # ICV
1877             logger.info("Test: STD-3 with CE flag")
1878             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
1879                                4 + 1 + 5 + 2 + 32 + 16,
1880                                EAP_TYPE_PAX,
1881                                EAP_PAX_OP_STD_3, EAP_PAX_FLAGS_CE,
1882                                EAP_PAX_MAC_HMAC_SHA1_128,
1883                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
1884                                32, 0, 0, 0, 0, 0, 0, 0, 0,
1885                                0x8a, 0xc2, 0xf9, 0xf4, 0x8b, 0x75, 0x72, 0xa2,
1886                                0x4d, 0xd3, 0x1e, 0x54, 0x77, 0x04, 0x05, 0xe2)
1887
1888         idx += 1
1889         if ctx['num'] & 0x1 == idx & 0x1:
1890             logger.info("Test: Default request")
1891             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1892                                4 + 1,
1893                                EAP_TYPE_PAX)
1894         else:
1895             logger.info("Test: Default EAP-Failure")
1896             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1897
1898     srv = start_radius_server(pax_handler)
1899
1900     try:
1901         hapd = start_ap(apdev[0]['ifname'])
1902
1903         for i in range(0, 18):
1904             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1905                            eap="PAX", identity="user",
1906                            password_hex="0123456789abcdef0123456789abcdef",
1907                            wait_connect=False)
1908             logger.info("Waiting for EAP method to start")
1909             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
1910                                    timeout=15)
1911             if ev is None:
1912                 raise Exception("Timeout on EAP start")
1913             time.sleep(0.05)
1914             dev[0].request("REMOVE_NETWORK all")
1915             dev[0].dump_monitor()
1916
1917         logger.info("Too short password")
1918         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1919                        eap="PAX", identity="user",
1920                        password_hex="0123456789abcdef0123456789abcd",
1921                        wait_connect=False)
1922         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
1923         if ev is None:
1924             raise Exception("Timeout on EAP start")
1925         time.sleep(0.1)
1926         dev[0].request("REMOVE_NETWORK all")
1927         dev[0].dump_monitor()
1928
1929         logger.info("No password")
1930         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1931                        eap="PAX", identity="user",
1932                        wait_connect=False)
1933         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
1934         if ev is None:
1935             raise Exception("Timeout on EAP start")
1936         time.sleep(0.1)
1937         dev[0].request("REMOVE_NETWORK all")
1938         dev[0].dump_monitor()
1939     finally:
1940         stop_radius_server(srv)
1941
1942 def test_eap_proto_psk(dev, apdev):
1943     """EAP-PSK protocol tests"""
1944     def psk_handler(ctx, req):
1945         logger.info("psk_handler - RX " + req.encode("hex"))
1946         if 'num' not in ctx:
1947             ctx['num'] = 0
1948         ctx['num'] = ctx['num'] + 1
1949         if 'id' not in ctx:
1950             ctx['id'] = 1
1951         ctx['id'] = (ctx['id'] + 1) % 256
1952
1953         idx = 0
1954
1955         idx += 1
1956         if ctx['num'] == idx:
1957             logger.info("Test: Missing payload")
1958             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1959                                4 + 1,
1960                                EAP_TYPE_PSK)
1961
1962         idx += 1
1963         if ctx['num'] == idx:
1964             logger.info("Test: Non-zero T in first message")
1965             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
1966                                4 + 1 + 1 + 16,
1967                                EAP_TYPE_PSK, 0xc0, 0, 0, 0, 0)
1968
1969         idx += 1
1970         if ctx['num'] == idx:
1971             logger.info("Test: Valid first message")
1972             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
1973                                4 + 1 + 1 + 16,
1974                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
1975         idx += 1
1976         if ctx['num'] == idx:
1977             logger.info("Test: Too short third message")
1978             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1979                                4 + 1,
1980                                EAP_TYPE_PSK)
1981
1982         idx += 1
1983         if ctx['num'] == idx:
1984             logger.info("Test: Valid first message")
1985             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
1986                                4 + 1 + 1 + 16,
1987                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
1988         idx += 1
1989         if ctx['num'] == idx:
1990             logger.info("Test: Incorrect T in third message")
1991             return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
1992                                4 + 1 + 1 + 16 + 16,
1993                                EAP_TYPE_PSK, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1994
1995         idx += 1
1996         if ctx['num'] == idx:
1997             logger.info("Test: Valid first message")
1998             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
1999                                4 + 1 + 1 + 16,
2000                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2001         idx += 1
2002         if ctx['num'] == idx:
2003             logger.info("Test: Missing PCHANNEL in third message")
2004             return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
2005                                4 + 1 + 1 + 16 + 16,
2006                                EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0)
2007
2008         idx += 1
2009         if ctx['num'] == idx:
2010             logger.info("Test: Valid first message")
2011             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2012                                4 + 1 + 1 + 16,
2013                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2014         idx += 1
2015         if ctx['num'] == idx:
2016             logger.info("Test: Invalic MAC_S in third message")
2017             return struct.pack(">BBHBB4L4L5LB", EAP_CODE_REQUEST, ctx['id'],
2018                                4 + 1 + 1 + 16 + 16 + 21,
2019                                EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
2020                                0, 0, 0, 0, 0, 0)
2021
2022         idx += 1
2023         if ctx['num'] == idx:
2024             logger.info("Test: Valid first message")
2025             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
2026                                4 + 1 + 1 + 16,
2027                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
2028         idx += 1
2029         if ctx['num'] == idx:
2030             logger.info("Test: EAP-Failure")
2031             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2032
2033         return None
2034
2035     srv = start_radius_server(psk_handler)
2036
2037     try:
2038         hapd = start_ap(apdev[0]['ifname'])
2039
2040         for i in range(0, 6):
2041             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2042                            eap="PSK", identity="user",
2043                            password_hex="0123456789abcdef0123456789abcdef",
2044                            wait_connect=False)
2045             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2046                                    timeout=15)
2047             if ev is None:
2048                 raise Exception("Timeout on EAP start")
2049             time.sleep(0.1)
2050             dev[0].request("REMOVE_NETWORK all")
2051
2052         logger.info("Test: Invalid PSK length")
2053         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2054                        eap="PSK", identity="user",
2055                        password_hex="0123456789abcdef0123456789abcd",
2056                        wait_connect=False)
2057         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2058                                timeout=15)
2059         if ev is None:
2060             raise Exception("Timeout on EAP start")
2061         time.sleep(0.1)
2062         dev[0].request("REMOVE_NETWORK all")
2063     finally:
2064         stop_radius_server(srv)
2065
2066 EAP_SIM_SUBTYPE_START = 10
2067 EAP_SIM_SUBTYPE_CHALLENGE = 11
2068 EAP_SIM_SUBTYPE_NOTIFICATION = 12
2069 EAP_SIM_SUBTYPE_REAUTHENTICATION = 13
2070 EAP_SIM_SUBTYPE_CLIENT_ERROR = 14
2071
2072 EAP_AKA_SUBTYPE_CHALLENGE = 1
2073 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT = 2
2074 EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE = 4
2075 EAP_AKA_SUBTYPE_IDENTITY = 5
2076 EAP_AKA_SUBTYPE_NOTIFICATION = 12
2077 EAP_AKA_SUBTYPE_REAUTHENTICATION = 13
2078 EAP_AKA_SUBTYPE_CLIENT_ERROR = 14
2079
2080 EAP_SIM_AT_RAND = 1
2081 EAP_SIM_AT_AUTN = 2
2082 EAP_SIM_AT_RES = 3
2083 EAP_SIM_AT_AUTS = 4
2084 EAP_SIM_AT_PADDING = 6
2085 EAP_SIM_AT_NONCE_MT = 7
2086 EAP_SIM_AT_PERMANENT_ID_REQ = 10
2087 EAP_SIM_AT_MAC = 11
2088 EAP_SIM_AT_NOTIFICATION = 12
2089 EAP_SIM_AT_ANY_ID_REQ = 13
2090 EAP_SIM_AT_IDENTITY = 14
2091 EAP_SIM_AT_VERSION_LIST = 15
2092 EAP_SIM_AT_SELECTED_VERSION = 16
2093 EAP_SIM_AT_FULLAUTH_ID_REQ = 17
2094 EAP_SIM_AT_COUNTER = 19
2095 EAP_SIM_AT_COUNTER_TOO_SMALL = 20
2096 EAP_SIM_AT_NONCE_S = 21
2097 EAP_SIM_AT_CLIENT_ERROR_CODE = 22
2098 EAP_SIM_AT_KDF_INPUT = 23
2099 EAP_SIM_AT_KDF = 24
2100 EAP_SIM_AT_IV = 129
2101 EAP_SIM_AT_ENCR_DATA = 130
2102 EAP_SIM_AT_NEXT_PSEUDONYM = 132
2103 EAP_SIM_AT_NEXT_REAUTH_ID = 133
2104 EAP_SIM_AT_CHECKCODE = 134
2105 EAP_SIM_AT_RESULT_IND = 135
2106 EAP_SIM_AT_BIDDING = 136
2107
2108 def test_eap_proto_aka(dev, apdev):
2109     """EAP-AKA protocol tests"""
2110     def aka_handler(ctx, req):
2111         logger.info("aka_handler - RX " + req.encode("hex"))
2112         if 'num' not in ctx:
2113             ctx['num'] = 0
2114         ctx['num'] = ctx['num'] + 1
2115         if 'id' not in ctx:
2116             ctx['id'] = 1
2117         ctx['id'] = (ctx['id'] + 1) % 256
2118
2119         idx = 0
2120
2121         idx += 1
2122         if ctx['num'] == idx:
2123             logger.info("Test: Missing payload")
2124             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2125                                4 + 1,
2126                                EAP_TYPE_AKA)
2127
2128         idx += 1
2129         if ctx['num'] == idx:
2130             logger.info("Test: Unknown subtype")
2131             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2132                                4 + 1 + 3,
2133                                EAP_TYPE_AKA, 255, 0)
2134         idx += 1
2135         if ctx['num'] == idx:
2136             logger.info("Test: EAP-Failure")
2137             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2138
2139         idx += 1
2140         if ctx['num'] == idx:
2141             logger.info("Test: Client Error")
2142             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2143                                4 + 1 + 3,
2144                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR, 0)
2145         idx += 1
2146         if ctx['num'] == idx:
2147             logger.info("Test: EAP-Failure")
2148             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2149
2150         idx += 1
2151         if ctx['num'] == idx:
2152             logger.info("Test: Too short attribute header")
2153             return struct.pack(">BBHBBHB", EAP_CODE_REQUEST, ctx['id'],
2154                                4 + 1 + 1 + 3,
2155                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255)
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: Truncated attribute")
2164             return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
2165                                4 + 1 + 1 + 4,
2166                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
2167                                255)
2168         idx += 1
2169         if ctx['num'] == idx:
2170             logger.info("Test: EAP-Failure")
2171             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2172
2173         idx += 1
2174         if ctx['num'] == idx:
2175             logger.info("Test: Too short attribute data")
2176             return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
2177                                4 + 1 + 1 + 4,
2178                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
2179                                0)
2180         idx += 1
2181         if ctx['num'] == idx:
2182             logger.info("Test: EAP-Failure")
2183             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2184
2185         idx += 1
2186         if ctx['num'] == idx:
2187             logger.info("Test: Skippable/non-skippable unrecognzized attribute")
2188             return struct.pack(">BBHBBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2189                                4 + 1 + 1 + 10,
2190                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2191                                255, 1, 0, 127, 1, 0)
2192         idx += 1
2193         if ctx['num'] == idx:
2194             logger.info("Test: EAP-Failure")
2195             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2196
2197         idx += 1
2198         if ctx['num'] == idx:
2199             logger.info("Test: Identity request without ID type")
2200             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2201                                4 + 1 + 3,
2202                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0)
2203         idx += 1
2204         if ctx['num'] == idx:
2205             logger.info("Test: Identity request ANY_ID")
2206             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2207                                4 + 1 + 3 + 4,
2208                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2209                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
2210         idx += 1
2211         if ctx['num'] == idx:
2212             logger.info("Test: Identity request ANY_ID (duplicate)")
2213             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2214                                4 + 1 + 3 + 4,
2215                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2216                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
2217         idx += 1
2218         if ctx['num'] == idx:
2219             logger.info("Test: EAP-Failure")
2220             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2221
2222         idx += 1
2223         if ctx['num'] == idx:
2224             logger.info("Test: Identity request ANY_ID")
2225             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2226                                4 + 1 + 3 + 4,
2227                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2228                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
2229         idx += 1
2230         if ctx['num'] == idx:
2231             logger.info("Test: Identity request FULLAUTH_ID")
2232             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2233                                4 + 1 + 3 + 4,
2234                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2235                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
2236         idx += 1
2237         if ctx['num'] == idx:
2238             logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
2239             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2240                                4 + 1 + 3 + 4,
2241                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2242                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
2243         idx += 1
2244         if ctx['num'] == idx:
2245             logger.info("Test: EAP-Failure")
2246             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2247
2248         idx += 1
2249         if ctx['num'] == idx:
2250             logger.info("Test: Identity request ANY_ID")
2251             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2252                                4 + 1 + 3 + 4,
2253                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2254                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
2255         idx += 1
2256         if ctx['num'] == idx:
2257             logger.info("Test: Identity request FULLAUTH_ID")
2258             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2259                                4 + 1 + 3 + 4,
2260                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2261                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
2262         idx += 1
2263         if ctx['num'] == idx:
2264             logger.info("Test: Identity request PERMANENT_ID")
2265             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2266                                4 + 1 + 3 + 4,
2267                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2268                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
2269         idx += 1
2270         if ctx['num'] == idx:
2271             logger.info("Test: Identity request PERMANENT_ID (duplicate)")
2272             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2273                                4 + 1 + 3 + 4,
2274                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2275                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
2276         idx += 1
2277         if ctx['num'] == idx:
2278             logger.info("Test: EAP-Failure")
2279             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2280
2281         idx += 1
2282         if ctx['num'] == idx:
2283             logger.info("Test: Challenge with no attributes")
2284             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2285                                4 + 1 + 3,
2286                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0)
2287         idx += 1
2288         if ctx['num'] == idx:
2289             logger.info("Test: EAP-Failure")
2290             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2291
2292         idx += 1
2293         if ctx['num'] == idx:
2294             logger.info("Test: AKA Challenge with BIDDING")
2295             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2296                                4 + 1 + 3 + 4,
2297                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2298                                EAP_SIM_AT_BIDDING, 1, 0x8000)
2299         idx += 1
2300         if ctx['num'] == idx:
2301             logger.info("Test: EAP-Failure")
2302             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2303
2304         idx += 1
2305         if ctx['num'] == idx:
2306             logger.info("Test: Notification with no attributes")
2307             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2308                                4 + 1 + 3,
2309                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0)
2310         idx += 1
2311         if ctx['num'] == idx:
2312             logger.info("Test: EAP-Failure")
2313             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2314
2315         idx += 1
2316         if ctx['num'] == idx:
2317             logger.info("Test: Notification indicating success, but no MAC")
2318             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2319                                4 + 1 + 3 + 4,
2320                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2321                                EAP_SIM_AT_NOTIFICATION, 1, 32768)
2322         idx += 1
2323         if ctx['num'] == idx:
2324             logger.info("Test: EAP-Failure")
2325             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2326
2327         idx += 1
2328         if ctx['num'] == idx:
2329             logger.info("Test: Notification indicating success, but invalid MAC value")
2330             return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
2331                                4 + 1 + 3 + 4 + 20,
2332                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2333                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
2334                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
2335         idx += 1
2336         if ctx['num'] == idx:
2337             logger.info("Test: EAP-Failure")
2338             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2339
2340         idx += 1
2341         if ctx['num'] == idx:
2342             logger.info("Test: Notification indicating success with zero-key MAC")
2343             return struct.pack(">BBHBBHBBHBBH16B", EAP_CODE_REQUEST,
2344                                ctx['id'] - 2,
2345                                4 + 1 + 3 + 4 + 20,
2346                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2347                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
2348                                EAP_SIM_AT_MAC, 5, 0,
2349                                0xbe, 0x2e, 0xbb, 0xa9, 0xfa, 0x2e, 0x82, 0x36,
2350                                0x37, 0x8c, 0x32, 0x41, 0xb7, 0xc7, 0x58, 0xa3)
2351         idx += 1
2352         if ctx['num'] == idx:
2353             logger.info("Test: EAP-Success")
2354             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
2355
2356         idx += 1
2357         if ctx['num'] == idx:
2358             logger.info("Test: Notification before auth")
2359             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2360                                4 + 1 + 3 + 4,
2361                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2362                                EAP_SIM_AT_NOTIFICATION, 1, 16384)
2363         idx += 1
2364         if ctx['num'] == idx:
2365             logger.info("Test: EAP-Failure")
2366             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2367
2368         idx += 1
2369         if ctx['num'] == idx:
2370             logger.info("Test: Notification before auth")
2371             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2372                                4 + 1 + 3 + 4,
2373                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2374                                EAP_SIM_AT_NOTIFICATION, 1, 16385)
2375         idx += 1
2376         if ctx['num'] == idx:
2377             logger.info("Test: EAP-Failure")
2378             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2379
2380         idx += 1
2381         if ctx['num'] == idx:
2382             logger.info("Test: Notification with unrecognized non-failure")
2383             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2384                                4 + 1 + 3 + 4,
2385                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2386                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
2387         idx += 1
2388         if ctx['num'] == idx:
2389             logger.info("Test: Notification before auth (duplicate)")
2390             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2391                                4 + 1 + 3 + 4,
2392                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
2393                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
2394         idx += 1
2395         if ctx['num'] == idx:
2396             logger.info("Test: EAP-Failure")
2397             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2398
2399         idx += 1
2400         if ctx['num'] == idx:
2401             logger.info("Test: Re-authentication (unexpected) with no attributes")
2402             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2403                                4 + 1 + 3,
2404                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
2405                                0)
2406         idx += 1
2407         if ctx['num'] == idx:
2408             logger.info("Test: EAP-Failure")
2409             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2410
2411         idx += 1
2412         if ctx['num'] == idx:
2413             logger.info("Test: AKA Challenge with Checkcode claiming identity round was used")
2414             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
2415                                4 + 1 + 3 + 24,
2416                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2417                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
2418         idx += 1
2419         if ctx['num'] == idx:
2420             logger.info("Test: EAP-Failure")
2421             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2422
2423         idx += 1
2424         if ctx['num'] == idx:
2425             logger.info("Test: Identity request ANY_ID")
2426             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2427                                4 + 1 + 3 + 4,
2428                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2429                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
2430         idx += 1
2431         if ctx['num'] == idx:
2432             logger.info("Test: AKA Challenge with Checkcode claiming no identity round was used")
2433             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2434                                4 + 1 + 3 + 4,
2435                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2436                                EAP_SIM_AT_CHECKCODE, 1, 0)
2437         idx += 1
2438         if ctx['num'] == idx:
2439             logger.info("Test: EAP-Failure")
2440             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2441
2442         idx += 1
2443         if ctx['num'] == idx:
2444             logger.info("Test: Identity request ANY_ID")
2445             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2446                                4 + 1 + 3 + 4,
2447                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2448                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
2449         idx += 1
2450         if ctx['num'] == idx:
2451             logger.info("Test: AKA Challenge with mismatching Checkcode value")
2452             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
2453                                4 + 1 + 3 + 24,
2454                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2455                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
2456         idx += 1
2457         if ctx['num'] == idx:
2458             logger.info("Test: EAP-Failure")
2459             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2460
2461         idx += 1
2462         if ctx['num'] == idx:
2463             logger.info("Test: Re-authentication (unexpected) with Checkcode claimin identity round was used")
2464             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
2465                                4 + 1 + 3 + 24,
2466                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
2467                                0,
2468                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
2469         idx += 1
2470         if ctx['num'] == idx:
2471             logger.info("Test: EAP-Failure")
2472             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2473
2474         idx += 1
2475         if ctx['num'] == idx:
2476             logger.info("Test: Invalid AT_RAND length")
2477             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2478                                4 + 1 + 3 + 4,
2479                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2480                                EAP_SIM_AT_RAND, 1, 0)
2481         idx += 1
2482         if ctx['num'] == idx:
2483             logger.info("Test: EAP-Failure")
2484             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2485
2486         idx += 1
2487         if ctx['num'] == idx:
2488             logger.info("Test: Invalid AT_AUTN length")
2489             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2490                                4 + 1 + 3 + 4,
2491                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2492                                EAP_SIM_AT_AUTN, 1, 0)
2493         idx += 1
2494         if ctx['num'] == idx:
2495             logger.info("Test: EAP-Failure")
2496             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2497
2498         idx += 1
2499         if ctx['num'] == idx:
2500             logger.info("Test: Unencrypted AT_PADDING")
2501             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2502                                4 + 1 + 3 + 4,
2503                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2504                                EAP_SIM_AT_PADDING, 1, 0)
2505         idx += 1
2506         if ctx['num'] == idx:
2507             logger.info("Test: EAP-Failure")
2508             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2509
2510         idx += 1
2511         if ctx['num'] == idx:
2512             logger.info("Test: Invalid AT_NONCE_MT length")
2513             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2514                                4 + 1 + 3 + 4,
2515                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2516                                EAP_SIM_AT_NONCE_MT, 1, 0)
2517         idx += 1
2518         if ctx['num'] == idx:
2519             logger.info("Test: EAP-Failure")
2520             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2521
2522         idx += 1
2523         if ctx['num'] == idx:
2524             logger.info("Test: Invalid AT_MAC length")
2525             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2526                                4 + 1 + 3 + 4,
2527                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2528                                EAP_SIM_AT_MAC, 1, 0)
2529         idx += 1
2530         if ctx['num'] == idx:
2531             logger.info("Test: EAP-Failure")
2532             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2533
2534         idx += 1
2535         if ctx['num'] == idx:
2536             logger.info("Test: Invalid AT_NOTIFICATION length")
2537             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2538                                4 + 1 + 3 + 8,
2539                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2540                                EAP_SIM_AT_NOTIFICATION, 2, 0, 0)
2541         idx += 1
2542         if ctx['num'] == idx:
2543             logger.info("Test: EAP-Failure")
2544             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2545
2546         idx += 1
2547         if ctx['num'] == idx:
2548             logger.info("Test: AT_IDENTITY overflow")
2549             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2550                                4 + 1 + 3 + 4,
2551                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2552                                EAP_SIM_AT_IDENTITY, 1, 0xffff)
2553         idx += 1
2554         if ctx['num'] == idx:
2555             logger.info("Test: EAP-Failure")
2556             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2557
2558         idx += 1
2559         if ctx['num'] == idx:
2560             logger.info("Test: Unexpected AT_VERSION_LIST")
2561             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2562                                4 + 1 + 3 + 4,
2563                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2564                                EAP_SIM_AT_VERSION_LIST, 1, 0)
2565         idx += 1
2566         if ctx['num'] == idx:
2567             logger.info("Test: EAP-Failure")
2568             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2569
2570         idx += 1
2571         if ctx['num'] == idx:
2572             logger.info("Test: Invalid AT_SELECTED_VERSION length")
2573             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2574                                4 + 1 + 3 + 8,
2575                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2576                                EAP_SIM_AT_SELECTED_VERSION, 2, 0, 0)
2577         idx += 1
2578         if ctx['num'] == idx:
2579             logger.info("Test: EAP-Failure")
2580             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2581
2582         idx += 1
2583         if ctx['num'] == idx:
2584             logger.info("Test: Unencrypted AT_COUNTER")
2585             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2586                                4 + 1 + 3 + 4,
2587                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2588                                EAP_SIM_AT_COUNTER, 1, 0)
2589         idx += 1
2590         if ctx['num'] == idx:
2591             logger.info("Test: EAP-Failure")
2592             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2593
2594         idx += 1
2595         if ctx['num'] == idx:
2596             logger.info("Test: Unencrypted AT_COUNTER_TOO_SMALL")
2597             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2598                                4 + 1 + 3 + 4,
2599                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2600                                EAP_SIM_AT_COUNTER_TOO_SMALL, 1, 0)
2601         idx += 1
2602         if ctx['num'] == idx:
2603             logger.info("Test: EAP-Failure")
2604             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2605
2606         idx += 1
2607         if ctx['num'] == idx:
2608             logger.info("Test: Unencrypted AT_NONCE_S")
2609             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2610                                4 + 1 + 3 + 4,
2611                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2612                                EAP_SIM_AT_NONCE_S, 1, 0)
2613         idx += 1
2614         if ctx['num'] == idx:
2615             logger.info("Test: EAP-Failure")
2616             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2617
2618         idx += 1
2619         if ctx['num'] == idx:
2620             logger.info("Test: Invalid AT_CLIENT_ERROR_CODE length")
2621             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2622                                4 + 1 + 3 + 8,
2623                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2624                                EAP_SIM_AT_CLIENT_ERROR_CODE, 2, 0, 0)
2625         idx += 1
2626         if ctx['num'] == idx:
2627             logger.info("Test: EAP-Failure")
2628             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2629
2630         idx += 1
2631         if ctx['num'] == idx:
2632             logger.info("Test: Invalid AT_IV length")
2633             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2634                                4 + 1 + 3 + 4,
2635                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2636                                EAP_SIM_AT_IV, 1, 0)
2637         idx += 1
2638         if ctx['num'] == idx:
2639             logger.info("Test: EAP-Failure")
2640             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2641
2642         idx += 1
2643         if ctx['num'] == idx:
2644             logger.info("Test: Invalid AT_ENCR_DATA length")
2645             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2646                                4 + 1 + 3 + 8,
2647                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2648                                EAP_SIM_AT_ENCR_DATA, 2, 0, 0)
2649         idx += 1
2650         if ctx['num'] == idx:
2651             logger.info("Test: EAP-Failure")
2652             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2653
2654         idx += 1
2655         if ctx['num'] == idx:
2656             logger.info("Test: Unencrypted AT_NEXT_PSEUDONYM")
2657             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2658                                4 + 1 + 3 + 4,
2659                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2660                                EAP_SIM_AT_NEXT_PSEUDONYM, 1, 0)
2661         idx += 1
2662         if ctx['num'] == idx:
2663             logger.info("Test: EAP-Failure")
2664             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2665
2666         idx += 1
2667         if ctx['num'] == idx:
2668             logger.info("Test: Unencrypted AT_NEXT_REAUTH_ID")
2669             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2670                                4 + 1 + 3 + 4,
2671                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2672                                EAP_SIM_AT_NEXT_REAUTH_ID, 1, 0)
2673         idx += 1
2674         if ctx['num'] == idx:
2675             logger.info("Test: EAP-Failure")
2676             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2677
2678         idx += 1
2679         if ctx['num'] == idx:
2680             logger.info("Test: Invalid AT_RES length")
2681             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2682                                4 + 1 + 3 + 4,
2683                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2684                                EAP_SIM_AT_RES, 1, 0)
2685         idx += 1
2686         if ctx['num'] == idx:
2687             logger.info("Test: EAP-Failure")
2688             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2689
2690         idx += 1
2691         if ctx['num'] == idx:
2692             logger.info("Test: Invalid AT_RES length")
2693             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
2694                                4 + 1 + 3 + 24,
2695                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2696                                EAP_SIM_AT_RES, 6, 0xffff, 0, 0, 0, 0, 0)
2697         idx += 1
2698         if ctx['num'] == idx:
2699             logger.info("Test: EAP-Failure")
2700             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2701
2702         idx += 1
2703         if ctx['num'] == idx:
2704             logger.info("Test: Invalid AT_AUTS length")
2705             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2706                                4 + 1 + 3 + 8,
2707                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2708                                EAP_SIM_AT_AUTS, 2, 0, 0)
2709         idx += 1
2710         if ctx['num'] == idx:
2711             logger.info("Test: EAP-Failure")
2712             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2713
2714         idx += 1
2715         if ctx['num'] == idx:
2716             logger.info("Test: Invalid AT_CHECKCODE length")
2717             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2718                                4 + 1 + 3 + 8,
2719                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2720                                EAP_SIM_AT_CHECKCODE, 2, 0, 0)
2721         idx += 1
2722         if ctx['num'] == idx:
2723             logger.info("Test: EAP-Failure")
2724             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2725
2726         idx += 1
2727         if ctx['num'] == idx:
2728             logger.info("Test: Invalid AT_RESULT_IND length")
2729             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2730                                4 + 1 + 3 + 8,
2731                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2732                                EAP_SIM_AT_RESULT_IND, 2, 0, 0)
2733         idx += 1
2734         if ctx['num'] == idx:
2735             logger.info("Test: EAP-Failure")
2736             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2737
2738         idx += 1
2739         if ctx['num'] == idx:
2740             logger.info("Test: Unexpected AT_KDF_INPUT")
2741             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2742                                4 + 1 + 3 + 8,
2743                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2744                                EAP_SIM_AT_KDF_INPUT, 2, 0, 0)
2745         idx += 1
2746         if ctx['num'] == idx:
2747             logger.info("Test: EAP-Failure")
2748             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2749
2750         idx += 1
2751         if ctx['num'] == idx:
2752             logger.info("Test: Unexpected AT_KDF")
2753             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2754                                4 + 1 + 3 + 8,
2755                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2756                                EAP_SIM_AT_KDF, 2, 0, 0)
2757         idx += 1
2758         if ctx['num'] == idx:
2759             logger.info("Test: EAP-Failure")
2760             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2761
2762         idx += 1
2763         if ctx['num'] == idx:
2764             logger.info("Test: Invalid AT_BIDDING length")
2765             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
2766                                4 + 1 + 3 + 8,
2767                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
2768                                EAP_SIM_AT_BIDDING, 2, 0, 0)
2769         idx += 1
2770         if ctx['num'] == idx:
2771             logger.info("Test: EAP-Failure")
2772             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2773
2774         return None
2775
2776     srv = start_radius_server(aka_handler)
2777
2778     try:
2779         hapd = start_ap(apdev[0]['ifname'])
2780
2781         for i in range(0, 49):
2782             eap = "AKA AKA'" if i == 11 else "AKA"
2783             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2784                            eap=eap, identity="0232010000000000",
2785                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
2786                            wait_connect=False)
2787             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2788                                    timeout=15)
2789             if ev is None:
2790                 raise Exception("Timeout on EAP start")
2791             if i in [ 0, 15 ]:
2792                 time.sleep(0.1)
2793             else:
2794                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
2795                                        timeout=10)
2796                 if ev is None:
2797                     raise Exception("Timeout on EAP failure")
2798             dev[0].request("REMOVE_NETWORK all")
2799             dev[0].dump_monitor()
2800     finally:
2801         stop_radius_server(srv)
2802
2803 def test_eap_proto_aka_prime(dev, apdev):
2804     """EAP-AKA' protocol tests"""
2805     def aka_prime_handler(ctx, req):
2806         logger.info("aka_prime_handler - RX " + req.encode("hex"))
2807         if 'num' not in ctx:
2808             ctx['num'] = 0
2809         ctx['num'] = ctx['num'] + 1
2810         if 'id' not in ctx:
2811             ctx['id'] = 1
2812         ctx['id'] = (ctx['id'] + 1) % 256
2813
2814         idx = 0
2815
2816         idx += 1
2817         if ctx['num'] == idx:
2818             logger.info("Test: Missing payload")
2819             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2820                                4 + 1,
2821                                EAP_TYPE_AKA_PRIME)
2822
2823         idx += 1
2824         if ctx['num'] == idx:
2825             logger.info("Test: Challenge with no attributes")
2826             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
2827                                4 + 1 + 3,
2828                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0)
2829         idx += 1
2830         if ctx['num'] == idx:
2831             logger.info("Test: EAP-Failure")
2832             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2833
2834         idx += 1
2835         if ctx['num'] == idx:
2836             logger.info("Test: Challenge with empty AT_KDF_INPUT")
2837             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
2838                                4 + 1 + 3 + 4,
2839                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2840                                EAP_SIM_AT_KDF_INPUT, 1, 0)
2841         idx += 1
2842         if ctx['num'] == idx:
2843             logger.info("Test: EAP-Failure")
2844             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2845
2846         idx += 1
2847         if ctx['num'] == idx:
2848             logger.info("Test: Challenge with AT_KDF_INPUT")
2849             return struct.pack(">BBHBBHBBHBBBB", EAP_CODE_REQUEST, ctx['id'],
2850                                4 + 1 + 3 + 8,
2851                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2852                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2853                                ord('c'), ord('d'))
2854         idx += 1
2855         if ctx['num'] == idx:
2856             logger.info("Test: EAP-Failure")
2857             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2858
2859         idx += 1
2860         if ctx['num'] == idx:
2861             logger.info("Test: Challenge with duplicated KDF")
2862             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
2863                                EAP_CODE_REQUEST, ctx['id'],
2864                                4 + 1 + 3 + 8 + 3 * 4,
2865                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2866                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2867                                ord('c'), ord('d'),
2868                                EAP_SIM_AT_KDF, 1, 1,
2869                                EAP_SIM_AT_KDF, 1, 2,
2870                                EAP_SIM_AT_KDF, 1, 1)
2871         idx += 1
2872         if ctx['num'] == idx:
2873             logger.info("Test: EAP-Failure")
2874             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2875
2876         idx += 1
2877         if ctx['num'] == idx:
2878             logger.info("Test: Challenge with multiple KDF proposals")
2879             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
2880                                EAP_CODE_REQUEST, ctx['id'],
2881                                4 + 1 + 3 + 8 + 3 * 4,
2882                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2883                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2884                                ord('c'), ord('d'),
2885                                EAP_SIM_AT_KDF, 1, 255,
2886                                EAP_SIM_AT_KDF, 1, 254,
2887                                EAP_SIM_AT_KDF, 1, 1)
2888         idx += 1
2889         if ctx['num'] == idx:
2890             logger.info("Test: Challenge with incorrect KDF selected")
2891             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
2892                                EAP_CODE_REQUEST, ctx['id'],
2893                                4 + 1 + 3 + 8 + 4 * 4,
2894                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2895                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2896                                ord('c'), ord('d'),
2897                                EAP_SIM_AT_KDF, 1, 255,
2898                                EAP_SIM_AT_KDF, 1, 255,
2899                                EAP_SIM_AT_KDF, 1, 254,
2900                                EAP_SIM_AT_KDF, 1, 1)
2901         idx += 1
2902         if ctx['num'] == idx:
2903             logger.info("Test: EAP-Failure")
2904             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2905
2906         idx += 1
2907         if ctx['num'] == idx:
2908             logger.info("Test: Challenge with multiple KDF proposals")
2909             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
2910                                EAP_CODE_REQUEST, ctx['id'],
2911                                4 + 1 + 3 + 8 + 3 * 4,
2912                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2913                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2914                                ord('c'), ord('d'),
2915                                EAP_SIM_AT_KDF, 1, 255,
2916                                EAP_SIM_AT_KDF, 1, 254,
2917                                EAP_SIM_AT_KDF, 1, 1)
2918         idx += 1
2919         if ctx['num'] == idx:
2920             logger.info("Test: Challenge with selected KDF not duplicated")
2921             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
2922                                EAP_CODE_REQUEST, ctx['id'],
2923                                4 + 1 + 3 + 8 + 3 * 4,
2924                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2925                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2926                                ord('c'), ord('d'),
2927                                EAP_SIM_AT_KDF, 1, 1,
2928                                EAP_SIM_AT_KDF, 1, 255,
2929                                EAP_SIM_AT_KDF, 1, 254)
2930         idx += 1
2931         if ctx['num'] == idx:
2932             logger.info("Test: EAP-Failure")
2933             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2934
2935         idx += 1
2936         if ctx['num'] == idx:
2937             logger.info("Test: Challenge with multiple KDF proposals")
2938             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
2939                                EAP_CODE_REQUEST, ctx['id'],
2940                                4 + 1 + 3 + 8 + 3 * 4,
2941                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2942                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2943                                ord('c'), ord('d'),
2944                                EAP_SIM_AT_KDF, 1, 255,
2945                                EAP_SIM_AT_KDF, 1, 254,
2946                                EAP_SIM_AT_KDF, 1, 1)
2947         idx += 1
2948         if ctx['num'] == idx:
2949             logger.info("Test: Challenge with selected KDF duplicated (missing MAC, RAND, AUTN)")
2950             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
2951                                EAP_CODE_REQUEST, ctx['id'],
2952                                4 + 1 + 3 + 8 + 4 * 4,
2953                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2954                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2955                                ord('c'), ord('d'),
2956                                EAP_SIM_AT_KDF, 1, 1,
2957                                EAP_SIM_AT_KDF, 1, 255,
2958                                EAP_SIM_AT_KDF, 1, 254,
2959                                EAP_SIM_AT_KDF, 1, 1)
2960         idx += 1
2961         if ctx['num'] == idx:
2962             logger.info("Test: EAP-Failure")
2963             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2964
2965         idx += 1
2966         if ctx['num'] == idx:
2967             logger.info("Test: Challenge with multiple unsupported KDF proposals")
2968             return struct.pack(">BBHBBHBBHBBBBBBHBBH",
2969                                EAP_CODE_REQUEST, ctx['id'],
2970                                4 + 1 + 3 + 8 + 2 * 4,
2971                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2972                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2973                                ord('c'), ord('d'),
2974                                EAP_SIM_AT_KDF, 1, 255,
2975                                EAP_SIM_AT_KDF, 1, 254)
2976         idx += 1
2977         if ctx['num'] == idx:
2978             logger.info("Test: EAP-Failure")
2979             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2980
2981         idx += 1
2982         if ctx['num'] == idx:
2983             logger.info("Test: Challenge with multiple KDF proposals")
2984             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
2985                                EAP_CODE_REQUEST, ctx['id'],
2986                                4 + 1 + 3 + 8 + 3 * 4,
2987                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
2988                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
2989                                ord('c'), ord('d'),
2990                                EAP_SIM_AT_KDF, 1, 255,
2991                                EAP_SIM_AT_KDF, 1, 254,
2992                                EAP_SIM_AT_KDF, 1, 1)
2993         idx += 1
2994         if ctx['num'] == idx:
2995             logger.info("Test: Challenge with invalid MAC, RAND, AUTN values)")
2996             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBHBBH4LBBH4LBBH4L",
2997                                EAP_CODE_REQUEST, ctx['id'],
2998                                4 + 1 + 3 + 8 + 4 * 4 + 20 + 20 + 20,
2999                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3000                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3001                                ord('c'), ord('d'),
3002                                EAP_SIM_AT_KDF, 1, 1,
3003                                EAP_SIM_AT_KDF, 1, 255,
3004                                EAP_SIM_AT_KDF, 1, 254,
3005                                EAP_SIM_AT_KDF, 1, 1,
3006                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0,
3007                                EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
3008                                EAP_SIM_AT_AUTN, 5, 0, 0, 0, 0, 0)
3009         idx += 1
3010         if ctx['num'] == idx:
3011             logger.info("Test: EAP-Failure")
3012             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3013
3014         idx += 1
3015         if ctx['num'] == idx:
3016             logger.info("Test: Challenge - AMF separation bit not set)")
3017             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
3018                                EAP_CODE_REQUEST, ctx['id'],
3019                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
3020                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3021                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3022                                ord('c'), ord('d'),
3023                                EAP_SIM_AT_KDF, 1, 1,
3024                                EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
3025                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
3026                                EAP_SIM_AT_AUTN, 5, 0, 9, 10,
3027                                0x2fda8ef7, 0xbba518cc)
3028         idx += 1
3029         if ctx['num'] == idx:
3030             logger.info("Test: EAP-Failure")
3031             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3032
3033         idx += 1
3034         if ctx['num'] == idx:
3035             logger.info("Test: Challenge - Invalid MAC")
3036             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
3037                                EAP_CODE_REQUEST, ctx['id'],
3038                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
3039                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3040                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3041                                ord('c'), ord('d'),
3042                                EAP_SIM_AT_KDF, 1, 1,
3043                                EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
3044                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
3045                                EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
3046                                0xd1f90322, 0x40514cb4)
3047         idx += 1
3048         if ctx['num'] == idx:
3049             logger.info("Test: EAP-Failure")
3050             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3051
3052         idx += 1
3053         if ctx['num'] == idx:
3054             logger.info("Test: Challenge - Valid MAC")
3055             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
3056                                EAP_CODE_REQUEST, ctx['id'],
3057                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
3058                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3059                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
3060                                ord('c'), ord('d'),
3061                                EAP_SIM_AT_KDF, 1, 1,
3062                                EAP_SIM_AT_MAC, 5, 0,
3063                                0xf4a3c1d3, 0x7c901401, 0x34bd8b01, 0x6f7fa32f,
3064                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
3065                                EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
3066                                0xd1f90322, 0x40514cb4)
3067         idx += 1
3068         if ctx['num'] == idx:
3069             logger.info("Test: EAP-Failure")
3070             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3071
3072         idx += 1
3073         if ctx['num'] == idx:
3074             logger.info("Test: Invalid AT_KDF_INPUT length")
3075             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3076                                4 + 1 + 3 + 8,
3077                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
3078                                EAP_SIM_AT_KDF_INPUT, 2, 0xffff, 0)
3079         idx += 1
3080         if ctx['num'] == idx:
3081             logger.info("Test: EAP-Failure")
3082             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3083
3084         idx += 1
3085         if ctx['num'] == idx:
3086             logger.info("Test: Invalid AT_KDF length")
3087             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3088                                4 + 1 + 3 + 8,
3089                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
3090                                EAP_SIM_AT_KDF, 2, 0, 0)
3091         idx += 1
3092         if ctx['num'] == idx:
3093             logger.info("Test: EAP-Failure")
3094             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3095
3096         idx += 1
3097         if ctx['num'] == idx:
3098             logger.info("Test: Challenge with large number of KDF proposals")
3099             return struct.pack(">BBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
3100                                EAP_CODE_REQUEST, ctx['id'],
3101                                4 + 1 + 3 + 12 * 4,
3102                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
3103                                EAP_SIM_AT_KDF, 1, 255,
3104                                EAP_SIM_AT_KDF, 1, 254,
3105                                EAP_SIM_AT_KDF, 1, 253,
3106                                EAP_SIM_AT_KDF, 1, 252,
3107                                EAP_SIM_AT_KDF, 1, 251,
3108                                EAP_SIM_AT_KDF, 1, 250,
3109                                EAP_SIM_AT_KDF, 1, 249,
3110                                EAP_SIM_AT_KDF, 1, 248,
3111                                EAP_SIM_AT_KDF, 1, 247,
3112                                EAP_SIM_AT_KDF, 1, 246,
3113                                EAP_SIM_AT_KDF, 1, 245,
3114                                EAP_SIM_AT_KDF, 1, 244)
3115         idx += 1
3116         if ctx['num'] == idx:
3117             logger.info("Test: EAP-Failure")
3118             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3119
3120         return None
3121
3122     srv = start_radius_server(aka_prime_handler)
3123
3124     try:
3125         hapd = start_ap(apdev[0]['ifname'])
3126
3127         for i in range(0, 16):
3128             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3129                            eap="AKA'", identity="6555444333222111",
3130                            password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
3131                            wait_connect=False)
3132             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3133                                    timeout=15)
3134             if ev is None:
3135                 raise Exception("Timeout on EAP start")
3136             if i in [ 0 ]:
3137                 time.sleep(0.1)
3138             else:
3139                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
3140                                        timeout=10)
3141                 if ev is None:
3142                     raise Exception("Timeout on EAP failure")
3143             dev[0].request("REMOVE_NETWORK all")
3144             dev[0].dump_monitor()
3145     finally:
3146         stop_radius_server(srv)
3147
3148 def test_eap_proto_sim(dev, apdev):
3149     """EAP-SIM protocol tests"""
3150     def sim_handler(ctx, req):
3151         logger.info("sim_handler - RX " + req.encode("hex"))
3152         if 'num' not in ctx:
3153             ctx['num'] = 0
3154         ctx['num'] = ctx['num'] + 1
3155         if 'id' not in ctx:
3156             ctx['id'] = 1
3157         ctx['id'] = (ctx['id'] + 1) % 256
3158
3159         idx = 0
3160
3161         idx += 1
3162         if ctx['num'] == idx:
3163             logger.info("Test: Missing payload")
3164             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3165                                4 + 1,
3166                                EAP_TYPE_SIM)
3167
3168         idx += 1
3169         if ctx['num'] == idx:
3170             logger.info("Test: Unexpected AT_AUTN")
3171             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3172                                4 + 1 + 3 + 8,
3173                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3174                                EAP_SIM_AT_AUTN, 2, 0, 0)
3175         idx += 1
3176         if ctx['num'] == idx:
3177             logger.info("Test: EAP-Failure")
3178             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3179
3180         idx += 1
3181         if ctx['num'] == idx:
3182             logger.info("Test: Too short AT_VERSION_LIST")
3183             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3184                                4 + 1 + 3 + 4,
3185                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3186                                EAP_SIM_AT_VERSION_LIST, 1, 0)
3187         idx += 1
3188         if ctx['num'] == idx:
3189             logger.info("Test: EAP-Failure")
3190             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3191
3192         idx += 1
3193         if ctx['num'] == idx:
3194             logger.info("Test: AT_VERSION_LIST overflow")
3195             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3196                                4 + 1 + 3 + 4,
3197                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3198                                EAP_SIM_AT_VERSION_LIST, 1, 0xffff)
3199         idx += 1
3200         if ctx['num'] == idx:
3201             logger.info("Test: EAP-Failure")
3202             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3203
3204         idx += 1
3205         if ctx['num'] == idx:
3206             logger.info("Test: Unexpected AT_AUTS")
3207             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3208                                4 + 1 + 3 + 8,
3209                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3210                                EAP_SIM_AT_AUTS, 2, 0, 0)
3211         idx += 1
3212         if ctx['num'] == idx:
3213             logger.info("Test: EAP-Failure")
3214             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3215
3216         idx += 1
3217         if ctx['num'] == idx:
3218             logger.info("Test: Unexpected AT_CHECKCODE")
3219             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
3220                                4 + 1 + 3 + 8,
3221                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3222                                EAP_SIM_AT_CHECKCODE, 2, 0, 0)
3223         idx += 1
3224         if ctx['num'] == idx:
3225             logger.info("Test: EAP-Failure")
3226             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3227
3228         idx += 1
3229         if ctx['num'] == idx:
3230             logger.info("Test: No AT_VERSION_LIST in Start")
3231             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3232                                4 + 1 + 3,
3233                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0)
3234         idx += 1
3235         if ctx['num'] == idx:
3236             logger.info("Test: EAP-Failure")
3237             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3238
3239         idx += 1
3240         if ctx['num'] == idx:
3241             logger.info("Test: No support version in AT_VERSION_LIST")
3242             return struct.pack(">BBHBBHBBH4B", EAP_CODE_REQUEST, ctx['id'],
3243                                4 + 1 + 3 + 8,
3244                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3245                                EAP_SIM_AT_VERSION_LIST, 2, 3, 2, 3, 4, 5)
3246         idx += 1
3247         if ctx['num'] == idx:
3248             logger.info("Test: EAP-Failure")
3249             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3250
3251
3252         idx += 1
3253         if ctx['num'] == idx:
3254             logger.info("Test: Identity request without ID type")
3255             return struct.pack(">BBHBBHBBH2H", EAP_CODE_REQUEST, ctx['id'],
3256                                4 + 1 + 3 + 8,
3257                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3258                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0)
3259         idx += 1
3260         if ctx['num'] == idx:
3261             logger.info("Test: Identity request ANY_ID")
3262             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3263                                4 + 1 + 3 + 8 + 4,
3264                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3265                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3266                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3267         idx += 1
3268         if ctx['num'] == idx:
3269             logger.info("Test: Identity request ANY_ID (duplicate)")
3270             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3271                                4 + 1 + 3 + 8 + 4,
3272                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3273                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3274                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3275         idx += 1
3276         if ctx['num'] == idx:
3277             logger.info("Test: EAP-Failure")
3278             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3279
3280         idx += 1
3281         if ctx['num'] == idx:
3282             logger.info("Test: Identity request ANY_ID")
3283             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3284                                4 + 1 + 3 + 8 + 4,
3285                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3286                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3287                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3288         idx += 1
3289         if ctx['num'] == idx:
3290             logger.info("Test: Identity request FULLAUTH_ID")
3291             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3292                                4 + 1 + 3 + 8 + 4,
3293                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3294                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3295                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
3296         idx += 1
3297         if ctx['num'] == idx:
3298             logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
3299             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3300                                4 + 1 + 3 + 8 + 4,
3301                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3302                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3303                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
3304         idx += 1
3305         if ctx['num'] == idx:
3306             logger.info("Test: EAP-Failure")
3307             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3308
3309         idx += 1
3310         if ctx['num'] == idx:
3311             logger.info("Test: Identity request ANY_ID")
3312             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3313                                4 + 1 + 3 + 8 + 4,
3314                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3315                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3316                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
3317         idx += 1
3318         if ctx['num'] == idx:
3319             logger.info("Test: Identity request FULLAUTH_ID")
3320             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3321                                4 + 1 + 3 + 8 + 4,
3322                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3323                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3324                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
3325         idx += 1
3326         if ctx['num'] == idx:
3327             logger.info("Test: Identity request PERMANENT_ID")
3328             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3329                                4 + 1 + 3 + 8 + 4,
3330                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3331                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3332                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
3333         idx += 1
3334         if ctx['num'] == idx:
3335             logger.info("Test: Identity request PERMANENT_ID (duplicate)")
3336             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
3337                                4 + 1 + 3 + 8 + 4,
3338                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
3339                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
3340                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
3341         idx += 1
3342         if ctx['num'] == idx:
3343             logger.info("Test: EAP-Failure")
3344             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3345
3346         idx += 1
3347         if ctx['num'] == idx:
3348             logger.info("Test: No AT_MAC and AT_RAND in Challenge")
3349             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3350                                4 + 1 + 3,
3351                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0)
3352         idx += 1
3353         if ctx['num'] == idx:
3354             logger.info("Test: EAP-Failure")
3355             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3356
3357         idx += 1
3358         if ctx['num'] == idx:
3359             logger.info("Test: No AT_RAND in Challenge")
3360             return struct.pack(">BBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
3361                                4 + 1 + 3 + 20,
3362                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
3363                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
3364         idx += 1
3365         if ctx['num'] == idx:
3366             logger.info("Test: EAP-Failure")
3367             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3368
3369         idx += 1
3370         if ctx['num'] == idx:
3371             logger.info("Test: Insufficient number of challenges in Challenge")
3372             return struct.pack(">BBHBBHBBH4LBBH4L", EAP_CODE_REQUEST, ctx['id'],
3373                                4 + 1 + 3 + 20 + 20,
3374                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
3375                                EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
3376                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 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: Too many challenges in Challenge")
3385             return struct.pack(">BBHBBHBBH4L4L4L4LBBH4L", EAP_CODE_REQUEST,
3386                                ctx['id'],
3387                                4 + 1 + 3 + 4 + 4 * 16 + 20,
3388                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
3389                                EAP_SIM_AT_RAND, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3390                                0, 0, 0, 0, 0, 0, 0, 0,
3391                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
3392         idx += 1
3393         if ctx['num'] == idx:
3394             logger.info("Test: EAP-Failure")
3395             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3396
3397         idx += 1
3398         if ctx['num'] == idx:
3399             logger.info("Test: Same RAND multiple times in Challenge")
3400             return struct.pack(">BBHBBHBBH4L4L4LBBH4L", EAP_CODE_REQUEST,
3401                                ctx['id'],
3402                                4 + 1 + 3 + 4 + 3 * 16 + 20,
3403                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
3404                                EAP_SIM_AT_RAND, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1,
3405                                0, 0, 0, 0,
3406                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
3407         idx += 1
3408         if ctx['num'] == idx:
3409             logger.info("Test: EAP-Failure")
3410             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3411
3412         idx += 1
3413         if ctx['num'] == idx:
3414             logger.info("Test: Notification with no attributes")
3415             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3416                                4 + 1 + 3,
3417                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0)
3418         idx += 1
3419         if ctx['num'] == idx:
3420             logger.info("Test: EAP-Failure")
3421             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3422
3423         idx += 1
3424         if ctx['num'] == idx:
3425             logger.info("Test: Notification indicating success, but no MAC")
3426             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3427                                4 + 1 + 3 + 4,
3428                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
3429                                EAP_SIM_AT_NOTIFICATION, 1, 32768)
3430         idx += 1
3431         if ctx['num'] == idx:
3432             logger.info("Test: EAP-Failure")
3433             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3434
3435         idx += 1
3436         if ctx['num'] == idx:
3437             logger.info("Test: Notification indicating success, but invalid MAC value")
3438             return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
3439                                4 + 1 + 3 + 4 + 20,
3440                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
3441                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
3442                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
3443         idx += 1
3444         if ctx['num'] == idx:
3445             logger.info("Test: EAP-Failure")
3446             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3447
3448         idx += 1
3449         if ctx['num'] == idx:
3450             logger.info("Test: Notification before auth")
3451             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3452                                4 + 1 + 3 + 4,
3453                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
3454                                EAP_SIM_AT_NOTIFICATION, 1, 16384)
3455         idx += 1
3456         if ctx['num'] == idx:
3457             logger.info("Test: EAP-Failure")
3458             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3459
3460         idx += 1
3461         if ctx['num'] == idx:
3462             logger.info("Test: Notification before auth")
3463             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3464                                4 + 1 + 3 + 4,
3465                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
3466                                EAP_SIM_AT_NOTIFICATION, 1, 16385)
3467         idx += 1
3468         if ctx['num'] == idx:
3469             logger.info("Test: EAP-Failure")
3470             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3471
3472         idx += 1
3473         if ctx['num'] == idx:
3474             logger.info("Test: Notification with unrecognized non-failure")
3475             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3476                                4 + 1 + 3 + 4,
3477                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
3478                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
3479         idx += 1
3480         if ctx['num'] == idx:
3481             logger.info("Test: Notification before auth (duplicate)")
3482             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
3483                                4 + 1 + 3 + 4,
3484                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
3485                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
3486         idx += 1
3487         if ctx['num'] == idx:
3488             logger.info("Test: EAP-Failure")
3489             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3490
3491         idx += 1
3492         if ctx['num'] == idx:
3493             logger.info("Test: Re-authentication (unexpected) with no attributes")
3494             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3495                                4 + 1 + 3,
3496                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION,
3497                                0)
3498         idx += 1
3499         if ctx['num'] == idx:
3500             logger.info("Test: EAP-Failure")
3501             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3502
3503         idx += 1
3504         if ctx['num'] == idx:
3505             logger.info("Test: Client Error")
3506             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3507                                4 + 1 + 3,
3508                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR, 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: Unknown subtype")
3517             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3518                                4 + 1 + 3,
3519                                EAP_TYPE_SIM, 255, 0)
3520         idx += 1
3521         if ctx['num'] == idx:
3522             logger.info("Test: EAP-Failure")
3523             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3524
3525         return None
3526
3527     srv = start_radius_server(sim_handler)
3528
3529     try:
3530         hapd = start_ap(apdev[0]['ifname'])
3531
3532         for i in range(0, 25):
3533             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3534                            eap="SIM", identity="1232010000000000",
3535                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
3536                            wait_connect=False)
3537             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3538                                    timeout=15)
3539             if ev is None:
3540                 raise Exception("Timeout on EAP start")
3541             if i in [ 0 ]:
3542                 time.sleep(0.1)
3543             else:
3544                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
3545                                        timeout=10)
3546                 if ev is None:
3547                     raise Exception("Timeout on EAP failure")
3548             dev[0].request("REMOVE_NETWORK all")
3549             dev[0].dump_monitor()
3550     finally:
3551         stop_radius_server(srv)
3552
3553 def test_eap_proto_ikev2(dev, apdev):
3554     """EAP-IKEv2 protocol tests"""
3555     check_eap_capa(dev[0], "IKEV2")
3556     def ikev2_handler(ctx, req):
3557         logger.info("ikev2_handler - RX " + req.encode("hex"))
3558         if 'num' not in ctx:
3559             ctx['num'] = 0
3560         ctx['num'] = ctx['num'] + 1
3561         if 'id' not in ctx:
3562             ctx['id'] = 1
3563         ctx['id'] = (ctx['id'] + 1) % 256
3564
3565         idx = 0
3566
3567         idx += 1
3568         if ctx['num'] == idx:
3569             logger.info("Test: Missing payload")
3570             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3571                                4 + 1,
3572                                EAP_TYPE_IKEV2)
3573
3574         idx += 1
3575         if ctx['num'] == idx:
3576             logger.info("Test: Truncated Message Length field")
3577             return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
3578                                4 + 1 + 1 + 3,
3579                                EAP_TYPE_IKEV2, 0x80, 0, 0, 0)
3580
3581         idx += 1
3582         if ctx['num'] == idx:
3583             logger.info("Test: Too short Message Length value")
3584             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
3585                                4 + 1 + 1 + 4 + 1,
3586                                EAP_TYPE_IKEV2, 0x80, 0, 1)
3587
3588         idx += 1
3589         if ctx['num'] == idx:
3590             logger.info("Test: Truncated message")
3591             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
3592                                4 + 1 + 1 + 4,
3593                                EAP_TYPE_IKEV2, 0x80, 1)
3594
3595         idx += 1
3596         if ctx['num'] == idx:
3597             logger.info("Test: Truncated message(2)")
3598             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
3599                                4 + 1 + 1 + 4,
3600                                EAP_TYPE_IKEV2, 0x80, 0xffffffff)
3601
3602         idx += 1
3603         if ctx['num'] == idx:
3604             logger.info("Test: Truncated message(3)")
3605             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
3606                                4 + 1 + 1 + 4,
3607                                EAP_TYPE_IKEV2, 0xc0, 0xffffffff)
3608
3609         idx += 1
3610         if ctx['num'] == idx:
3611             logger.info("Test: Truncated message(4)")
3612             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
3613                                4 + 1 + 1 + 4,
3614                                EAP_TYPE_IKEV2, 0xc0, 10000000)
3615
3616         idx += 1
3617         if ctx['num'] == idx:
3618             logger.info("Test: Too long fragments (first fragment)")
3619             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
3620                                4 + 1 + 1 + 4 + 1,
3621                                EAP_TYPE_IKEV2, 0xc0, 2, 1)
3622
3623         idx += 1
3624         if ctx['num'] == idx:
3625             logger.info("Test: Too long fragments (second fragment)")
3626             return struct.pack(">BBHBB2B", EAP_CODE_REQUEST, ctx['id'],
3627                                4 + 1 + 1 + 2,
3628                                EAP_TYPE_IKEV2, 0x00, 2, 3)
3629
3630         idx += 1
3631         if ctx['num'] == idx:
3632             logger.info("Test: No Message Length field in first fragment")
3633             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
3634                                4 + 1 + 1 + 1,
3635                                EAP_TYPE_IKEV2, 0x40, 1)
3636
3637         idx += 1
3638         if ctx['num'] == idx:
3639             logger.info("Test: ICV before keys")
3640             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
3641                                4 + 1 + 1,
3642                                EAP_TYPE_IKEV2, 0x20)
3643
3644         idx += 1
3645         if ctx['num'] == idx:
3646             logger.info("Test: Unsupported IKEv2 header version")
3647             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3648                                4 + 1 + 1 + 28,
3649                                EAP_TYPE_IKEV2, 0x00,
3650                                0, 0, 0, 0,
3651                                0, 0, 0, 0, 0, 0)
3652
3653         idx += 1
3654         if ctx['num'] == idx:
3655             logger.info("Test: Incorrect IKEv2 header Length")
3656             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3657                                4 + 1 + 1 + 28,
3658                                EAP_TYPE_IKEV2, 0x00,
3659                                0, 0, 0, 0,
3660                                0, 0x20, 0, 0, 0, 0)
3661
3662         idx += 1
3663         if ctx['num'] == idx:
3664             logger.info("Test: Unexpected IKEv2 Exchange Type in SA_INIT state")
3665             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3666                                4 + 1 + 1 + 28,
3667                                EAP_TYPE_IKEV2, 0x00,
3668                                0, 0, 0, 0,
3669                                0, 0x20, 0, 0, 0, 28)
3670
3671         idx += 1
3672         if ctx['num'] == idx:
3673             logger.info("Test: Unexpected IKEv2 Message ID in SA_INIT state")
3674             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3675                                4 + 1 + 1 + 28,
3676                                EAP_TYPE_IKEV2, 0x00,
3677                                0, 0, 0, 0,
3678                                0, 0x20, 34, 0, 1, 28)
3679
3680         idx += 1
3681         if ctx['num'] == idx:
3682             logger.info("Test: Unexpected IKEv2 Flags value")
3683             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3684                                4 + 1 + 1 + 28,
3685                                EAP_TYPE_IKEV2, 0x00,
3686                                0, 0, 0, 0,
3687                                0, 0x20, 34, 0, 0, 28)
3688
3689         idx += 1
3690         if ctx['num'] == idx:
3691             logger.info("Test: Unexpected IKEv2 Flags value(2)")
3692             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3693                                4 + 1 + 1 + 28,
3694                                EAP_TYPE_IKEV2, 0x00,
3695                                0, 0, 0, 0,
3696                                0, 0x20, 34, 0x20, 0, 28)
3697
3698         idx += 1
3699         if ctx['num'] == idx:
3700             logger.info("Test: No SAi1 in SA_INIT")
3701             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
3702                                4 + 1 + 1 + 28,
3703                                EAP_TYPE_IKEV2, 0x00,
3704                                0, 0, 0, 0,
3705                                0, 0x20, 34, 0x08, 0, 28)
3706
3707         def build_ike(id, next=0, exch_type=34, flags=0x00, ike=''):
3708             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, id,
3709                                4 + 1 + 1 + 28 + len(ike),
3710                                EAP_TYPE_IKEV2, flags,
3711                                0, 0, 0, 0,
3712                                next, 0x20, exch_type, 0x08, 0,
3713                                28 + len(ike)) + ike
3714
3715         idx += 1
3716         if ctx['num'] == idx:
3717             logger.info("Test: Unexpected extra data after payloads")
3718             return build_ike(ctx['id'], ike=struct.pack(">B", 1))
3719
3720         idx += 1
3721         if ctx['num'] == idx:
3722             logger.info("Test: Truncated payload header")
3723             return build_ike(ctx['id'], next=128, ike=struct.pack(">B", 1))
3724
3725         idx += 1
3726         if ctx['num'] == idx:
3727             logger.info("Test: Too small payload header length")
3728             ike = struct.pack(">BBH", 0, 0, 3)
3729             return build_ike(ctx['id'], next=128, ike=ike)
3730
3731         idx += 1
3732         if ctx['num'] == idx:
3733             logger.info("Test: Too large payload header length")
3734             ike = struct.pack(">BBH", 0, 0, 5)
3735             return build_ike(ctx['id'], next=128, ike=ike)
3736
3737         idx += 1
3738         if ctx['num'] == idx:
3739             logger.info("Test: Unsupported payload (non-critical and critical)")
3740             ike = struct.pack(">BBHBBH", 129, 0, 4, 0, 0x01, 4)
3741             return build_ike(ctx['id'], next=128, ike=ike)
3742
3743         idx += 1
3744         if ctx['num'] == idx:
3745             logger.info("Test: Certificate and empty SAi1")
3746             ike = struct.pack(">BBHBBH", 33, 0, 4, 0, 0, 4)
3747             return build_ike(ctx['id'], next=37, ike=ike)
3748
3749         idx += 1
3750         if ctx['num'] == idx:
3751             logger.info("Test: Too short proposal")
3752             ike = struct.pack(">BBHBBHBBB", 0, 0, 4 + 7,
3753                               0, 0, 7, 0, 0, 0)
3754             return build_ike(ctx['id'], next=33, ike=ike)
3755
3756         idx += 1
3757         if ctx['num'] == idx:
3758             logger.info("Test: Too small proposal length in SAi1")
3759             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3760                               0, 0, 7, 0, 0, 0, 0)
3761             return build_ike(ctx['id'], next=33, ike=ike)
3762
3763         idx += 1
3764         if ctx['num'] == idx:
3765             logger.info("Test: Too large proposal length in SAi1")
3766             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3767                               0, 0, 9, 0, 0, 0, 0)
3768             return build_ike(ctx['id'], next=33, ike=ike)
3769
3770         idx += 1
3771         if ctx['num'] == idx:
3772             logger.info("Test: Unexpected proposal type in SAi1")
3773             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3774                               1, 0, 8, 0, 0, 0, 0)
3775             return build_ike(ctx['id'], next=33, ike=ike)
3776
3777         idx += 1
3778         if ctx['num'] == idx:
3779             logger.info("Test: Unexpected Protocol ID in SAi1")
3780             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3781                               0, 0, 8, 0, 0, 0, 0)
3782             return build_ike(ctx['id'], next=33, ike=ike)
3783
3784         idx += 1
3785         if ctx['num'] == idx:
3786             logger.info("Test: Unexpected proposal number in SAi1")
3787             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3788                               0, 0, 8, 0, 1, 0, 0)
3789             return build_ike(ctx['id'], next=33, ike=ike)
3790
3791         idx += 1
3792         if ctx['num'] == idx:
3793             logger.info("Test: Not enough room for SPI in SAi1")
3794             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3795                               0, 0, 8, 1, 1, 1, 0)
3796             return build_ike(ctx['id'], next=33, ike=ike)
3797
3798         idx += 1
3799         if ctx['num'] == idx:
3800             logger.info("Test: Unexpected SPI in SAi1")
3801             ike = struct.pack(">BBHBBHBBBBB", 0, 0, 4 + 9,
3802                               0, 0, 9, 1, 1, 1, 0, 1)
3803             return build_ike(ctx['id'], next=33, ike=ike)
3804
3805         idx += 1
3806         if ctx['num'] == idx:
3807             logger.info("Test: No transforms in SAi1")
3808             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3809                               0, 0, 8, 1, 1, 0, 0)
3810             return build_ike(ctx['id'], next=33, ike=ike)
3811
3812         idx += 1
3813         if ctx['num'] == idx:
3814             logger.info("Test: Too short transform in SAi1")
3815             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
3816                               0, 0, 8, 1, 1, 0, 1)
3817             return build_ike(ctx['id'], next=33, ike=ike)
3818
3819         idx += 1
3820         if ctx['num'] == idx:
3821             logger.info("Test: Too small transform length in SAi1")
3822             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
3823                               0, 0, 8 + 8, 1, 1, 0, 1,
3824                               0, 0, 7, 0, 0, 0)
3825             return build_ike(ctx['id'], next=33, ike=ike)
3826
3827         idx += 1
3828         if ctx['num'] == idx:
3829             logger.info("Test: Too large transform length in SAi1")
3830             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
3831                               0, 0, 8 + 8, 1, 1, 0, 1,
3832                               0, 0, 9, 0, 0, 0)
3833             return build_ike(ctx['id'], next=33, ike=ike)
3834
3835         idx += 1
3836         if ctx['num'] == idx:
3837             logger.info("Test: Unexpected Transform type in SAi1")
3838             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
3839                               0, 0, 8 + 8, 1, 1, 0, 1,
3840                               1, 0, 8, 0, 0, 0)
3841             return build_ike(ctx['id'], next=33, ike=ike)
3842
3843         idx += 1
3844         if ctx['num'] == idx:
3845             logger.info("Test: No transform attributes in SAi1")
3846             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
3847                               0, 0, 8 + 8, 1, 1, 0, 1,
3848                               0, 0, 8, 0, 0, 0)
3849             return build_ike(ctx['id'], next=33, ike=ike)
3850
3851         idx += 1
3852         if ctx['num'] == idx:
3853             logger.info("Test: No transform attr for AES and unexpected data after transforms in SAi1")
3854             tlen1 = 8 + 3
3855             tlen2 = 8 + 4
3856             tlen3 = 8 + 4
3857             tlen = tlen1 + tlen2 + tlen3
3858             ike = struct.pack(">BBHBBHBBBBBBHBBH3BBBHBBHHHBBHBBHHHB",
3859                               0, 0, 4 + 8 + tlen + 1,
3860                               0, 0, 8 + tlen + 1, 1, 1, 0, 3,
3861                               3, 0, tlen1, 1, 0, 12, 1, 2, 3,
3862                               3, 0, tlen2, 1, 0, 12, 0, 128,
3863                               0, 0, tlen3, 1, 0, 12, 0x8000 | 14, 127,
3864                               1)
3865             return build_ike(ctx['id'], next=33, ike=ike)
3866
3867         def build_sa(next=0):
3868             tlen = 5 * 8
3869             return struct.pack(">BBHBBHBBBBBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
3870                                next, 0, 4 + 8 + tlen,
3871                                0, 0, 8 + tlen, 1, 1, 0, 5,
3872                                3, 0, 8, 1, 0, 3,
3873                                3, 0, 8, 2, 0, 1,
3874                                3, 0, 8, 3, 0, 1,
3875                                3, 0, 8, 4, 0, 5,
3876                                0, 0, 8, 241, 0, 0)
3877
3878         idx += 1
3879         if ctx['num'] == idx:
3880             logger.info("Test: Valid proposal, but no KEi in SAi1")
3881             ike = build_sa()
3882             return build_ike(ctx['id'], next=33, ike=ike)
3883
3884         idx += 1
3885         if ctx['num'] == idx:
3886             logger.info("Test: Empty KEi in SAi1")
3887             ike = build_sa(next=34) + struct.pack(">BBH", 0, 0, 4)
3888             return build_ike(ctx['id'], next=33, ike=ike)
3889
3890         idx += 1
3891         if ctx['num'] == idx:
3892             logger.info("Test: Mismatch in DH Group in SAi1")
3893             ike = build_sa(next=34)
3894             ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 12345, 0)
3895             ike += 96*'\x00'
3896             return build_ike(ctx['id'], next=33, ike=ike)
3897         idx += 1
3898         if ctx['num'] == idx:
3899             logger.info("Test: EAP-Failure")
3900             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3901
3902         idx += 1
3903         if ctx['num'] == idx:
3904             logger.info("Test: Invalid DH public value length in SAi1")
3905             ike = build_sa(next=34)
3906             ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 5, 0)
3907             ike += 96*'\x00'
3908             return build_ike(ctx['id'], next=33, ike=ike)
3909
3910         def build_ke(next=0):
3911             ke = struct.pack(">BBHHH", next, 0, 4 + 4 + 192, 5, 0)
3912             ke += 192*'\x00'
3913             return ke
3914
3915         idx += 1
3916         if ctx['num'] == idx:
3917             logger.info("Test: Valid proposal and KEi, but no Ni in SAi1")
3918             ike = build_sa(next=34)
3919             ike += build_ke()
3920             return build_ike(ctx['id'], next=33, ike=ike)
3921
3922         idx += 1
3923         if ctx['num'] == idx:
3924             logger.info("Test: Too short Ni in SAi1")
3925             ike = build_sa(next=34)
3926             ike += build_ke(next=40)
3927             ike += struct.pack(">BBH", 0, 0, 4)
3928             return build_ike(ctx['id'], next=33, ike=ike)
3929
3930         idx += 1
3931         if ctx['num'] == idx:
3932             logger.info("Test: Too long Ni in SAi1")
3933             ike = build_sa(next=34)
3934             ike += build_ke(next=40)
3935             ike += struct.pack(">BBH", 0, 0, 4 + 257) + 257*'\x00'
3936             return build_ike(ctx['id'], next=33, ike=ike)
3937
3938         def build_ni(next=0):
3939             return struct.pack(">BBH", next, 0, 4 + 256) + 256*'\x00'
3940
3941         def build_sai1(id):
3942             ike = build_sa(next=34)
3943             ike += build_ke(next=40)
3944             ike += build_ni()
3945             return build_ike(ctx['id'], next=33, ike=ike)
3946
3947         idx += 1
3948         if ctx['num'] == idx:
3949             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
3950             return build_sai1(ctx['id'])
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: Valid proposal, KEi, and Ni in SAi1")
3959             return build_sai1(ctx['id'])
3960         idx += 1
3961         if ctx['num'] == idx:
3962             logger.info("Test: No integrity checksum")
3963             ike = ''
3964             return build_ike(ctx['id'], next=37, ike=ike)
3965
3966         idx += 1
3967         if ctx['num'] == idx:
3968             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
3969             return build_sai1(ctx['id'])
3970         idx += 1
3971         if ctx['num'] == idx:
3972             logger.info("Test: Truncated integrity checksum")
3973             return struct.pack(">BBHBB",
3974                                EAP_CODE_REQUEST, ctx['id'],
3975                                4 + 1 + 1,
3976                                EAP_TYPE_IKEV2, 0x20)
3977
3978         idx += 1
3979         if ctx['num'] == idx:
3980             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
3981             return build_sai1(ctx['id'])
3982         idx += 1
3983         if ctx['num'] == idx:
3984             logger.info("Test: Invalid integrity checksum")
3985             ike = ''
3986             return build_ike(ctx['id'], next=37, flags=0x20, ike=ike)
3987
3988         return None
3989
3990     srv = start_radius_server(ikev2_handler)
3991
3992     try:
3993         hapd = start_ap(apdev[0]['ifname'])
3994
3995         for i in range(49):
3996             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3997                            eap="IKEV2", identity="user",
3998                            password="password",
3999                            wait_connect=False)
4000             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
4001                                    timeout=15)
4002             if ev is None:
4003                 raise Exception("Timeout on EAP start")
4004             if i in [ 40, 45 ]:
4005                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
4006                                        timeout=10)
4007                 if ev is None:
4008                     raise Exception("Timeout on EAP failure")
4009             else:
4010                 time.sleep(0.05)
4011             dev[0].request("REMOVE_NETWORK all")
4012     finally:
4013         stop_radius_server(srv)