1 # EAP protocol tests
2 # Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6 
7 import binascii
8 import hashlib
9 import hmac
10 import logging
11 logger = logging.getLogger()
12 import os
13 import select
14 import struct
15 import threading
16 import time
17 
18 import hostapd
19 from utils import *
20 from test_ap_eap import check_eap_capa, check_hlr_auc_gw_support, int_eap_server_params
21 
22 try:
23     import OpenSSL
24     openssl_imported = True
25 except ImportError:
26     openssl_imported = False
27 
28 EAP_CODE_REQUEST = 1
29 EAP_CODE_RESPONSE = 2
30 EAP_CODE_SUCCESS = 3
31 EAP_CODE_FAILURE = 4
32 EAP_CODE_INITIATE = 5
33 EAP_CODE_FINISH = 6
34 
35 EAP_TYPE_IDENTITY = 1
36 EAP_TYPE_NOTIFICATION = 2
37 EAP_TYPE_NAK = 3
38 EAP_TYPE_MD5 = 4
39 EAP_TYPE_OTP = 5
40 EAP_TYPE_GTC = 6
41 EAP_TYPE_TLS = 13
42 EAP_TYPE_LEAP = 17
43 EAP_TYPE_SIM = 18
44 EAP_TYPE_TTLS = 21
45 EAP_TYPE_AKA = 23
46 EAP_TYPE_PEAP = 25
47 EAP_TYPE_MSCHAPV2 = 26
48 EAP_TYPE_TLV = 33
49 EAP_TYPE_TNC = 38
50 EAP_TYPE_FAST = 43
51 EAP_TYPE_PAX = 46
52 EAP_TYPE_PSK = 47
53 EAP_TYPE_SAKE = 48
54 EAP_TYPE_IKEV2 = 49
55 EAP_TYPE_AKA_PRIME = 50
56 EAP_TYPE_GPSK = 51
57 EAP_TYPE_PWD = 52
58 EAP_TYPE_EKE = 53
59 EAP_TYPE_EXPANDED = 254
60 
61 # Type field in EAP-Initiate and EAP-Finish messages
62 EAP_ERP_TYPE_REAUTH_START = 1
63 EAP_ERP_TYPE_REAUTH = 2
64 
65 EAP_ERP_TLV_KEYNAME_NAI = 1
66 EAP_ERP_TV_RRK_LIFETIME = 2
67 EAP_ERP_TV_RMSK_LIFETIME = 3
68 EAP_ERP_TLV_DOMAIN_NAME = 4
69 EAP_ERP_TLV_CRYPTOSUITES = 5
70 EAP_ERP_TLV_AUTHORIZATION_INDICATION = 6
71 EAP_ERP_TLV_CALLED_STATION_ID = 128
72 EAP_ERP_TLV_CALLING_STATION_ID = 129
73 EAP_ERP_TLV_NAS_IDENTIFIER = 130
74 EAP_ERP_TLV_NAS_IP_ADDRESS = 131
75 EAP_ERP_TLV_NAS_IPV6_ADDRESS = 132
76 
77 def add_message_authenticator_attr(reply, digest):
78     if digest.startswith(b'0x'):
79         # Work around pyrad tools.py EncodeOctets() functionality that
80         # assumes a binary value that happens to start with "0x" to be
81         # a hex string.
82         digest = b"0x" + binascii.hexlify(digest)
83     reply.AddAttribute("Message-Authenticator", digest)
84 
85 def build_message_auth(pkt, reply, secret=None):
86     if secret is None:
87         secret = reply.secret
88     hmac_obj = hmac.new(secret, digestmod=hashlib.md5)
89     hmac_obj.update(struct.pack("B", reply.code))
90     hmac_obj.update(struct.pack("B", reply.id))
91 
92     reply.AddAttribute("Message-Authenticator", 16*b'\x00')
93     attrs = reply._PktEncodeAttributes()
94 
95     # Length
96     flen = 4 + 16 + len(attrs)
97     hmac_obj.update(struct.pack(">H", flen))
98     hmac_obj.update(pkt.authenticator)
99     hmac_obj.update(attrs)
100     del reply[80]
101     add_message_authenticator_attr(reply, hmac_obj.digest())
102 
103 def run_pyrad_server(srv, t_stop, eap_handler):
104     srv.RunWithStop(t_stop, eap_handler)
105 
106 def start_radius_server(eap_handler):
107     try:
108         import pyrad.server
109         import pyrad.packet
110         import pyrad.dictionary
111     except ImportError:
112         raise HwsimSkip("No pyrad modules available")
113 
114     class TestServer(pyrad.server.Server):
115         def _HandleAuthPacket(self, pkt):
116             pyrad.server.Server._HandleAuthPacket(self, pkt)
117             eap = b''
118             for p in pkt[79]:
119                 eap += p
120             eap_req = self.eap_handler(self.ctx, eap)
121             reply = self.CreateReplyPacket(pkt)
122             if eap_req:
123                 while True:
124                     if len(eap_req) > 253:
125                         reply.AddAttribute("EAP-Message", eap_req[0:253])
126                         eap_req = eap_req[253:]
127                     else:
128                         reply.AddAttribute("EAP-Message", eap_req)
129                         break
130             else:
131                 logger.info("No EAP request available")
132             reply.code = pyrad.packet.AccessChallenge
133 
134             # reply attributes
135             build_message_auth(pkt, reply)
136 
137             self.SendReplyPacket(pkt.fd, reply)
138 
139         def RunWithStop(self, t_stop, eap_handler):
140             self._poll = select.poll()
141             self._fdmap = {}
142             self._PrepareSockets()
143             self.t_stop = t_stop
144             self.eap_handler = eap_handler
145             self.ctx = {}
146 
147             while not t_stop.is_set():
148                 for (fd, event) in self._poll.poll(200):
149                     if event == select.POLLIN:
150                         try:
151                             fdo = self._fdmap[fd]
152                             self._ProcessInput(fdo)
153                         except pyrad.server.ServerPacketError as err:
154                             logger.info("pyrad server dropping packet: " + str(err))
155                         except pyrad.packet.PacketError as err:
156                             logger.info("pyrad server received invalid packet: " + str(err))
157                     else:
158                         logger.error("Unexpected event in pyrad server main loop")
159 
160             for fd in self.authfds + self.acctfds:
161                 fd.close()
162 
163     srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
164                      authport=18138, acctport=18139)
165     srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
166                                                      b"radius",
167                                                      "localhost")
168     srv.BindToAddress("127.0.0.1")
169     t_stop = threading.Event()
170     t = threading.Thread(target=run_pyrad_server, args=(srv, t_stop, eap_handler))
171     t.start()
172 
173     return {'srv': srv, 'stop': t_stop, 'thread': t}
174 
175 def stop_radius_server(srv):
176     srv['stop'].set()
177     srv['thread'].join()
178 
179 def start_ap(ap):
180     params = hostapd.wpa2_eap_params(ssid="eap-test")
181     params['auth_server_port'] = "18138"
182     hapd = hostapd.add_ap(ap, params)
183     return hapd
184 
185 def test_eap_proto(dev, apdev):
186     """EAP protocol tests"""
187     check_eap_capa(dev[0], "MD5")
188     def eap_handler(ctx, req):
189         logger.info("eap_handler - RX " + binascii.hexlify(req).decode())
190         if 'num' not in ctx:
191             ctx['num'] = 0
192         ctx['num'] = ctx['num'] + 1
193         if 'id' not in ctx:
194             ctx['id'] = 1
195         ctx['id'] = (ctx['id'] + 1) % 256
196         idx = 0
197 
198         idx += 1
199         if ctx['num'] == idx:
200             logger.info("Test: MD5 challenge")
201             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
202                                4 + 1 + 3,
203                                EAP_TYPE_MD5,
204                                1, 0xaa, ord('n'))
205         idx += 1
206         if ctx['num'] == idx:
207             logger.info("Test: EAP-Success - id off by 2")
208             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] + 1, 4)
209 
210         idx += 1
211         if ctx['num'] == idx:
212             logger.info("Test: MD5 challenge")
213             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
214                                4 + 1 + 3,
215                                EAP_TYPE_MD5,
216                                1, 0xaa, ord('n'))
217         idx += 1
218         if ctx['num'] == idx:
219             logger.info("Test: EAP-Success - id off by 3")
220             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] + 2, 4)
221 
222         idx += 1
223         if ctx['num'] == idx:
224             logger.info("Test: MD5 challenge")
225             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
226                                4 + 1 + 3,
227                                EAP_TYPE_MD5,
228                                1, 0xaa, ord('n'))
229         idx += 1
230         if ctx['num'] == idx:
231             logger.info("Test: EAP-Notification/Request")
232             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
233                                4 + 1 + 1,
234                                EAP_TYPE_NOTIFICATION,
235                                ord('A'))
236         idx += 1
237         if ctx['num'] == idx:
238             logger.info("Test: EAP-Success")
239             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
240 
241         idx += 1
242         if ctx['num'] == idx:
243             logger.info("Test: EAP-Notification/Request")
244             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
245                                4 + 1 + 1,
246                                EAP_TYPE_NOTIFICATION,
247                                ord('B'))
248         idx += 1
249         if ctx['num'] == idx:
250             logger.info("Test: MD5 challenge")
251             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
252                                4 + 1 + 3,
253                                EAP_TYPE_MD5,
254                                1, 0xaa, ord('n'))
255         idx += 1
256         if ctx['num'] == idx:
257             logger.info("Test: EAP-Success")
258             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
259 
260         idx += 1
261         if ctx['num'] == idx:
262             logger.info("Test: EAP-Notification/Request")
263             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
264                                4 + 1 + 1,
265                                EAP_TYPE_NOTIFICATION,
266                                ord('C'))
267         idx += 1
268         if ctx['num'] == idx:
269             logger.info("Test: MD5 challenge")
270             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
271                                4 + 1 + 3,
272                                EAP_TYPE_MD5,
273                                1, 0xaa, ord('n'))
274         idx += 1
275         if ctx['num'] == idx:
276             logger.info("Test: EAP-Notification/Request")
277             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
278                                4 + 1 + 1,
279                                EAP_TYPE_NOTIFICATION,
280                                ord('D'))
281         idx += 1
282         if ctx['num'] == idx:
283             logger.info("Test: EAP-Success")
284             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 1, 4)
285 
286         idx += 1
287         if ctx['num'] == idx:
288             logger.info("Test: EAP-Notification/Request")
289             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
290                                4 + 1 + 1,
291                                EAP_TYPE_NOTIFICATION,
292                                ord('E'))
293         idx += 1
294         if ctx['num'] == idx:
295             logger.info("Test: EAP-Notification/Request (same id)")
296             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'] - 1,
297                                4 + 1 + 1,
298                                EAP_TYPE_NOTIFICATION,
299                                ord('F'))
300         idx += 1
301         if ctx['num'] == idx:
302             logger.info("Test: Unexpected EAP-Success")
303             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'] - 2, 4)
304 
305         return None
306 
307     srv = start_radius_server(eap_handler)
308 
309     try:
310         hapd = start_ap(apdev[0])
311         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
312 
313         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
314                        eap="MD5", identity="user", password="password",
315                        wait_connect=False)
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-PROPOSED-METHOD"], timeout=15)
328         if ev is None:
329             raise Exception("Timeout on EAP start")
330         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=1)
331         if ev is not None:
332             raise Exception("Unexpected EAP success")
333         dev[0].request("REMOVE_NETWORK all")
334 
335         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
336                        eap="MD5", identity="user", password="password",
337                        wait_connect=False)
338         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
339         if ev is None:
340             raise Exception("Timeout on EAP start")
341         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
342         if ev is None:
343             raise Exception("Timeout on EAP notification")
344         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION A":
345             raise Exception("Unexpected notification contents: " + ev)
346         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
347         if ev is None:
348             raise Exception("Timeout on EAP success")
349         dev[0].request("REMOVE_NETWORK all")
350 
351         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
352                        eap="MD5", identity="user", password="password",
353                        wait_connect=False)
354         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
355         if ev is None:
356             raise Exception("Timeout on EAP notification")
357         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION B":
358             raise Exception("Unexpected notification contents: " + ev)
359         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
360         if ev is None:
361             raise Exception("Timeout on EAP start")
362         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
363         if ev is None:
364             raise Exception("Timeout on EAP success")
365         dev[0].request("REMOVE_NETWORK all")
366 
367         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
368                        eap="MD5", identity="user", password="password",
369                        wait_connect=False)
370         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
371         if ev is None:
372             raise Exception("Timeout on EAP notification")
373         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION C":
374             raise Exception("Unexpected notification contents: " + ev)
375         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
376         if ev is None:
377             raise Exception("Timeout on EAP start")
378         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
379         if ev is None:
380             raise Exception("Timeout on EAP notification")
381         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION D":
382             raise Exception("Unexpected notification contents: " + ev)
383         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
384         if ev is None:
385             raise Exception("Timeout on EAP success")
386         dev[0].request("REMOVE_NETWORK all")
387 
388         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
389                        eap="MD5", identity="user", password="password",
390                        wait_connect=False)
391         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
392         if ev is None:
393             raise Exception("Timeout on EAP notification")
394         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION E":
395             raise Exception("Unexpected notification contents: " + ev)
396         ev = dev[0].wait_event(["CTRL-EVENT-EAP-NOTIFICATION"], timeout=10)
397         if ev is None:
398             raise Exception("Timeout on EAP notification")
399         if ev != "<3>CTRL-EVENT-EAP-NOTIFICATION F":
400             raise Exception("Unexpected notification contents: " + ev)
401         ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=15)
402         if ev is None:
403             raise Exception("Timeout on EAP failure")
404         dev[0].request("REMOVE_NETWORK all")
405     finally:
406         stop_radius_server(srv)
407 
408 def test_eap_proto_notification_errors(dev, apdev):
409     """EAP Notification errors"""
410     def eap_handler(ctx, req):
411         logger.info("eap_handler - RX " + binascii.hexlify(req).decode())
412         if 'num' not in ctx:
413             ctx['num'] = 0
414         ctx['num'] = ctx['num'] + 1
415         if 'id' not in ctx:
416             ctx['id'] = 1
417         ctx['id'] = (ctx['id'] + 1) % 256
418         idx = 0
419 
420         idx += 1
421         if ctx['num'] == idx:
422             logger.info("Test: MD5 challenge")
423             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
424                                4 + 1 + 3,
425                                EAP_TYPE_MD5,
426                                1, 0xaa, ord('n'))
427         idx += 1
428         if ctx['num'] == idx:
429             logger.info("Test: EAP-Notification/Request")
430             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
431                                4 + 1 + 1,
432                                EAP_TYPE_NOTIFICATION,
433                                ord('A'))
434 
435         idx += 1
436         if ctx['num'] == idx:
437             logger.info("Test: MD5 challenge")
438             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
439                                4 + 1 + 3,
440                                EAP_TYPE_MD5,
441                                1, 0xaa, ord('n'))
442         idx += 1
443         if ctx['num'] == idx:
444             logger.info("Test: EAP-Notification/Request")
445             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
446                                4 + 1 + 1,
447                                EAP_TYPE_NOTIFICATION,
448                                ord('A'))
449 
450         return None
451 
452     srv = start_radius_server(eap_handler)
453 
454     try:
455         hapd = start_ap(apdev[0])
456         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
457 
458         with alloc_fail(dev[0], 1, "eap_sm_processNotify"):
459             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
460                            eap="MD5", identity="user", password="password",
461                            wait_connect=False)
462             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
463             dev[0].request("REMOVE_NETWORK all")
464             dev[0].wait_disconnected()
465 
466         with alloc_fail(dev[0], 1, "eap_msg_alloc;sm_EAP_NOTIFICATION_Enter"):
467             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
468                            eap="MD5", identity="user", password="password",
469                            wait_connect=False)
470             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
471             dev[0].request("REMOVE_NETWORK all")
472             dev[0].wait_disconnected()
473     finally:
474         stop_radius_server(srv)
475 
476 EAP_SAKE_VERSION = 2
477 
478 EAP_SAKE_SUBTYPE_CHALLENGE = 1
479 EAP_SAKE_SUBTYPE_CONFIRM = 2
480 EAP_SAKE_SUBTYPE_AUTH_REJECT = 3
481 EAP_SAKE_SUBTYPE_IDENTITY = 4
482 
483 EAP_SAKE_AT_RAND_S = 1
484 EAP_SAKE_AT_RAND_P = 2
485 EAP_SAKE_AT_MIC_S = 3
486 EAP_SAKE_AT_MIC_P = 4
487 EAP_SAKE_AT_SERVERID = 5
488 EAP_SAKE_AT_PEERID = 6
489 EAP_SAKE_AT_SPI_S = 7
490 EAP_SAKE_AT_SPI_P = 8
491 EAP_SAKE_AT_ANY_ID_REQ = 9
492 EAP_SAKE_AT_PERM_ID_REQ = 10
493 EAP_SAKE_AT_ENCR_DATA = 128
494 EAP_SAKE_AT_IV = 129
495 EAP_SAKE_AT_PADDING = 130
496 EAP_SAKE_AT_NEXT_TMPID = 131
497 EAP_SAKE_AT_MSK_LIFE = 132
498 
499 def test_eap_proto_sake(dev, apdev):
500     """EAP-SAKE protocol tests"""
501     global eap_proto_sake_test_done
502     eap_proto_sake_test_done = False
503 
504     def sake_challenge(ctx):
505         logger.info("Test: Challenge subtype")
506         return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
507                            4 + 1 + 3 + 18,
508                            EAP_TYPE_SAKE,
509                            EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
510                            EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
511 
512     def sake_handler(ctx, req):
513         logger.info("sake_handler - RX " + binascii.hexlify(req).decode())
514         if 'num' not in ctx:
515             ctx['num'] = 0
516         ctx['num'] += 1
517         if 'id' not in ctx:
518             ctx['id'] = 1
519         ctx['id'] = (ctx['id'] + 1) % 256
520         idx = 0
521 
522         idx += 1
523         if ctx['num'] == idx:
524             logger.info("Test: Missing payload")
525             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
526                                EAP_TYPE_SAKE)
527 
528         idx += 1
529         if ctx['num'] == idx:
530             logger.info("Test: Identity subtype without any attributes")
531             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
532                                4 + 1 + 3,
533                                EAP_TYPE_SAKE,
534                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY)
535 
536         idx += 1
537         if ctx['num'] == idx:
538             logger.info("Test: Identity subtype")
539             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
540                                4 + 1 + 3 + 4,
541                                EAP_TYPE_SAKE,
542                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
543                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
544         idx += 1
545         if ctx['num'] == idx:
546             logger.info("Test: Identity subtype (different session id)")
547             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
548                                4 + 1 + 3 + 4,
549                                EAP_TYPE_SAKE,
550                                EAP_SAKE_VERSION, 1, EAP_SAKE_SUBTYPE_IDENTITY,
551                                EAP_SAKE_AT_PERM_ID_REQ, 4, 0)
552 
553         idx += 1
554         if ctx['num'] == idx:
555             logger.info("Test: Identity subtype with too short attribute")
556             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
557                                4 + 1 + 3 + 2,
558                                EAP_TYPE_SAKE,
559                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
560                                EAP_SAKE_AT_ANY_ID_REQ, 2)
561 
562         idx += 1
563         if ctx['num'] == idx:
564             logger.info("Test: Identity subtype with truncated attribute")
565             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
566                                4 + 1 + 3 + 2,
567                                EAP_TYPE_SAKE,
568                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
569                                EAP_SAKE_AT_ANY_ID_REQ, 4)
570 
571         idx += 1
572         if ctx['num'] == idx:
573             logger.info("Test: Identity subtype with too short attribute header")
574             payload = struct.pack("B", EAP_SAKE_AT_ANY_ID_REQ)
575             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
576                                4 + 1 + 3 + len(payload),
577                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
578                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
579 
580         idx += 1
581         if ctx['num'] == idx:
582             logger.info("Test: Identity subtype with AT_IV but not AT_ENCR_DATA")
583             payload = struct.pack("BB", EAP_SAKE_AT_IV, 2)
584             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
585                                4 + 1 + 3 + len(payload),
586                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
587                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
588 
589         idx += 1
590         if ctx['num'] == idx:
591             logger.info("Test: Identity subtype with skippable and non-skippable unknown attribute")
592             payload = struct.pack("BBBB", 255, 2, 127, 2)
593             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
594                                4 + 1 + 3 + len(payload),
595                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
596                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
597 
598         idx += 1
599         if ctx['num'] == idx:
600             logger.info("Test: Identity subtype: AT_RAND_P with invalid payload length")
601             payload = struct.pack("BB", EAP_SAKE_AT_RAND_P, 2)
602             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
603                                4 + 1 + 3 + len(payload),
604                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
605                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
606 
607         idx += 1
608         if ctx['num'] == idx:
609             logger.info("Test: Identity subtype: AT_MIC_P with invalid payload length")
610             payload = struct.pack("BB", EAP_SAKE_AT_MIC_P, 2)
611             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
612                                4 + 1 + 3 + len(payload),
613                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
614                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
615 
616         idx += 1
617         if ctx['num'] == idx:
618             logger.info("Test: Identity subtype: AT_PERM_ID_REQ with invalid payload length")
619             payload = struct.pack("BBBBBBBBBBBBBB",
620                                   EAP_SAKE_AT_SPI_S, 2,
621                                   EAP_SAKE_AT_SPI_P, 2,
622                                   EAP_SAKE_AT_ENCR_DATA, 2,
623                                   EAP_SAKE_AT_NEXT_TMPID, 2,
624                                   EAP_SAKE_AT_PERM_ID_REQ, 4, 0, 0,
625                                   EAP_SAKE_AT_PERM_ID_REQ, 2)
626             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
627                                4 + 1 + 3 + len(payload),
628                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
629                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
630 
631         idx += 1
632         if ctx['num'] == idx:
633             logger.info("Test: Identity subtype: AT_PADDING")
634             payload = struct.pack("BBBBBB",
635                                   EAP_SAKE_AT_PADDING, 3, 0,
636                                   EAP_SAKE_AT_PADDING, 3, 1)
637             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
638                                4 + 1 + 3 + len(payload),
639                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
640                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
641 
642         idx += 1
643         if ctx['num'] == idx:
644             logger.info("Test: Identity subtype: AT_MSK_LIFE")
645             payload = struct.pack(">BBLBBH",
646                                   EAP_SAKE_AT_MSK_LIFE, 6, 0,
647                                   EAP_SAKE_AT_MSK_LIFE, 4, 0)
648             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
649                                4 + 1 + 3 + len(payload),
650                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
651                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
652 
653         idx += 1
654         if ctx['num'] == idx:
655             logger.info("Test: Identity subtype with invalid attribute length")
656             payload = struct.pack("BB", EAP_SAKE_AT_ANY_ID_REQ, 0)
657             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
658                                4 + 1 + 3 + len(payload),
659                                EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
660                                EAP_SAKE_SUBTYPE_IDENTITY) + payload
661 
662         idx += 1
663         if ctx['num'] == idx:
664             logger.info("Test: Unknown subtype")
665             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
666                                4 + 1 + 3,
667                                EAP_TYPE_SAKE,
668                                EAP_SAKE_VERSION, 0, 123)
669 
670         idx += 1
671         if ctx['num'] == idx:
672             logger.info("Test: Challenge subtype without any attributes")
673             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
674                                4 + 1 + 3,
675                                EAP_TYPE_SAKE,
676                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE)
677 
678         idx += 1
679         if ctx['num'] == idx:
680             logger.info("Test: Challenge subtype with too short AT_RAND_S")
681             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
682                                4 + 1 + 3 + 2,
683                                EAP_TYPE_SAKE,
684                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
685                                EAP_SAKE_AT_RAND_S, 2)
686 
687         idx += 1
688         if ctx['num'] == idx:
689             return sake_challenge(ctx)
690         idx += 1
691         if ctx['num'] == idx:
692             logger.info("Test: Unexpected Identity subtype")
693             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
694                                4 + 1 + 3 + 4,
695                                EAP_TYPE_SAKE,
696                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
697                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
698 
699         idx += 1
700         if ctx['num'] == idx:
701             return sake_challenge(ctx)
702         idx += 1
703         if ctx['num'] == idx:
704             logger.info("Test: Unexpected Challenge subtype")
705             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
706                                4 + 1 + 3 + 18,
707                                EAP_TYPE_SAKE,
708                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
709                                EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
710 
711         idx += 1
712         if ctx['num'] == idx:
713             return sake_challenge(ctx)
714         idx += 1
715         if ctx['num'] == idx:
716             logger.info("Test: Confirm subtype without any attributes")
717             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
718                                4 + 1 + 3,
719                                EAP_TYPE_SAKE,
720                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM)
721 
722         idx += 1
723         if ctx['num'] == idx:
724             return sake_challenge(ctx)
725         idx += 1
726         if ctx['num'] == idx:
727             logger.info("Test: Confirm subtype with too short AT_MIC_S")
728             return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
729                                4 + 1 + 3 + 2,
730                                EAP_TYPE_SAKE,
731                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
732                                EAP_SAKE_AT_MIC_S, 2)
733 
734         idx += 1
735         if ctx['num'] == idx:
736             logger.info("Test: Unexpected Confirm subtype")
737             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
738                                4 + 1 + 3 + 18,
739                                EAP_TYPE_SAKE,
740                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
741                                EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
742 
743         idx += 1
744         if ctx['num'] == idx:
745             return sake_challenge(ctx)
746         idx += 1
747         if ctx['num'] == idx:
748             logger.info("Test: Confirm subtype with incorrect AT_MIC_S")
749             return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
750                                4 + 1 + 3 + 18,
751                                EAP_TYPE_SAKE,
752                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
753                                EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
754 
755         global eap_proto_sake_test_done
756         if eap_proto_sake_test_done:
757             return sake_challenge(ctx)
758 
759         logger.info("No more test responses available - test case completed")
760         eap_proto_sake_test_done = True
761         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
762 
763     srv = start_radius_server(sake_handler)
764 
765     try:
766         hapd = start_ap(apdev[0])
767         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
768 
769         while not eap_proto_sake_test_done:
770             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
771                            eap="SAKE", identity="sake user",
772                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
773                            wait_connect=False)
774             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
775             if ev is None:
776                 raise Exception("Timeout on EAP start")
777             time.sleep(0.1)
778             dev[0].request("REMOVE_NETWORK all")
779             dev[0].dump_monitor()
780 
781         logger.info("Too short password")
782         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
783                        eap="SAKE", identity="sake user",
784                        password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd",
785                        wait_connect=False)
786         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
787         if ev is None:
788             raise Exception("Timeout on EAP start")
789         start = os.times()[4]
790         while True:
791             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
792                                    timeout=0.1)
793             if ev is None:
794                 break
795             now = os.times()[4]
796             if now - start > 0.1:
797                 break
798             dev[0].dump_monitor()
799 
800         dev[0].request("REMOVE_NETWORK all")
801         time.sleep(0.1)
802         dev[0].dump_monitor()
803     finally:
804         stop_radius_server(srv)
805 
806 def test_eap_proto_sake_errors(dev, apdev):
807     """EAP-SAKE local error cases"""
808     check_eap_capa(dev[0], "SAKE")
809     params = hostapd.wpa2_eap_params(ssid="eap-test")
810     hapd = hostapd.add_ap(apdev[0], params)
811     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
812 
813     for i in range(1, 3):
814         with alloc_fail(dev[0], i, "eap_sake_init"):
815             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
816                            eap="SAKE", identity="sake user",
817                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
818                            wait_connect=False)
819             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
820                                    timeout=15)
821             if ev is None:
822                 raise Exception("Timeout on EAP start")
823             dev[0].request("REMOVE_NETWORK all")
824             dev[0].wait_disconnected()
825             dev[0].dump_monitor()
826 
827     tests = [(1, "eap_msg_alloc;eap_sake_build_msg;eap_sake_process_challenge"),
828              (1, "=eap_sake_process_challenge"),
829              (1, "eap_sake_compute_mic;eap_sake_process_challenge"),
830              (1, "eap_sake_build_msg;eap_sake_process_confirm"),
831              (1, "eap_sake_compute_mic;eap_sake_process_confirm"),
832              (2, "eap_sake_compute_mic"),
833              (3, "eap_sake_compute_mic"),
834              (1, "eap_sake_getKey"),
835              (1, "eap_sake_get_emsk"),
836              (1, "eap_sake_get_session_id")]
837     for count, func in tests:
838         with alloc_fail(dev[0], count, func):
839             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
840                            eap="SAKE", identity="sake user@domain",
841                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
842                            erp="1",
843                            wait_connect=False)
844             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
845                                    timeout=15)
846             if ev is None:
847                 raise Exception("Timeout on EAP start")
848             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
849             dev[0].request("REMOVE_NETWORK all")
850             dev[0].wait_disconnected()
851             dev[0].dump_monitor()
852 
853     tests = [(1, "os_get_random;eap_sake_process_challenge"),
854              (1, "eap_sake_derive_keys;eap_sake_process_challenge"),
855              (2, "eap_sake_derive_keys;eap_sake_process_challenge"),
856              (3, "eap_sake_derive_keys;eap_sake_process_challenge"),
857              (4, "eap_sake_derive_keys;eap_sake_process_challenge"),
858              (5, "eap_sake_derive_keys;eap_sake_process_challenge"),
859              (6, "eap_sake_derive_keys;eap_sake_process_challenge")]
860     for count, func in tests:
861         with fail_test(dev[0], count, func):
862             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
863                            eap="SAKE", identity="sake user",
864                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
865                            wait_connect=False)
866             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
867             if ev is None:
868                 raise Exception("Timeout on EAP start")
869             wait_fail_trigger(dev[0], "GET_FAIL")
870             dev[0].request("REMOVE_NETWORK all")
871             dev[0].wait_disconnected()
872             dev[0].dump_monitor()
873 
874 def test_eap_proto_sake_errors2(dev, apdev):
875     """EAP-SAKE protocol tests (2)"""
876     def sake_handler(ctx, req):
877         logger.info("sake_handler - RX " + binascii.hexlify(req).decode())
878         if 'num' not in ctx:
879             ctx['num'] = 0
880         ctx['num'] += 1
881         if 'id' not in ctx:
882             ctx['id'] = 1
883         ctx['id'] = (ctx['id'] + 1) % 256
884         idx = 0
885 
886         idx += 1
887         if ctx['num'] == idx:
888             logger.info("Test: Identity subtype")
889             return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
890                                4 + 1 + 3 + 4,
891                                EAP_TYPE_SAKE,
892                                EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
893                                EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
894 
895     srv = start_radius_server(sake_handler)
896 
897     try:
898         hapd = start_ap(apdev[0])
899         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
900 
901         with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sake_build_msg;eap_sake_process_identity"):
902             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
903                            eap="SAKE", identity="sake user",
904                            password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
905                            wait_connect=False)
906             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
907                                    timeout=15)
908             if ev is None:
909                 raise Exception("Timeout on EAP start")
910                 dev[0].request("REMOVE_NETWORK all")
911                 dev[0].wait_disconnected()
912 
913     finally:
914         stop_radius_server(srv)
915 
916 def run_eap_sake_connect(dev):
917     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
918                 eap="SAKE", identity="sake user",
919                 password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
920                 wait_connect=False)
921     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
922                          "CTRL-EVENT-DISCONNECTED"],
923                         timeout=1)
924     dev.request("REMOVE_NETWORK all")
925     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
926         dev.wait_disconnected()
927     dev.dump_monitor()
928 
929 def test_eap_proto_sake_errors_server(dev, apdev):
930     """EAP-SAKE local error cases on server"""
931     check_eap_capa(dev[0], "SAKE")
932     params = int_eap_server_params()
933     params['erp_domain'] = 'example.com'
934     params['eap_server_erp'] = '1'
935     hapd = hostapd.add_ap(apdev[0], params)
936     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
937 
938     tests = [(1, "eap_sake_init"),
939              (1, "eap_sake_build_msg;eap_sake_build_challenge"),
940              (1, "eap_sake_build_msg;eap_sake_build_confirm"),
941              (1, "eap_sake_compute_mic;eap_sake_build_confirm"),
942              (1, "eap_sake_process_challenge"),
943              (1, "eap_sake_getKey"),
944              (1, "eap_sake_get_emsk"),
945              (1, "eap_sake_get_session_id")]
946     for count, func in tests:
947         with alloc_fail(hapd, count, func):
948             run_eap_sake_connect(dev[0])
949 
950     tests = [(1, "eap_sake_init"),
951              (1, "eap_sake_build_challenge"),
952              (1, "eap_sake_build_confirm"),
953              (1, "eap_sake_derive_keys;eap_sake_process_challenge"),
954              (1, "eap_sake_compute_mic;eap_sake_process_challenge"),
955              (1, "eap_sake_compute_mic;eap_sake_process_confirm"),
956              (1, "eap_sake_compute_mic;eap_sake_build_confirm"),
957              (1, "eap_sake_process_confirm")]
958     for count, func in tests:
959         with fail_test(hapd, count, func):
960             run_eap_sake_connect(dev[0])
961 
962 def start_sake_assoc(dev, hapd):
963     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
964                 eap="SAKE", identity="sake user",
965                 password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
966                 wait_connect=False)
967     proxy_msg(hapd, dev) # EAP-Identity/Request
968     proxy_msg(dev, hapd) # EAP-Identity/Response
969     proxy_msg(hapd, dev) # SAKE/Challenge/Request
970 
971 def stop_sake_assoc(dev, hapd):
972     dev.request("REMOVE_NETWORK all")
973     dev.wait_disconnected()
974     dev.dump_monitor()
975     hapd.dump_monitor()
976 
977 def test_eap_proto_sake_server(dev, apdev):
978     """EAP-SAKE protocol testing for the server"""
979     check_eap_capa(dev[0], "SAKE")
980     params = int_eap_server_params()
981     params['erp_domain'] = 'example.com'
982     params['eap_server_erp'] = '1'
983     hapd = hostapd.add_ap(apdev[0], params)
984     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
985     hapd.request("SET ext_eapol_frame_io 1")
986     dev[0].request("SET ext_eapol_frame_io 1")
987 
988     # Successful exchange to verify proxying mechanism
989     start_sake_assoc(dev[0], hapd)
990     proxy_msg(dev[0], hapd) # SAKE/Challenge/Response
991     proxy_msg(hapd, dev[0]) # SAKE/Confirm/Request
992     proxy_msg(dev[0], hapd) # SAKE/Confirm/Response
993     proxy_msg(hapd, dev[0]) # EAP-Success
994     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 1/4
995     proxy_msg(dev[0], hapd) # EAPOL-Key msg 2/4
996     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 3/4
997     proxy_msg(dev[0], hapd) # EAPOL-Key msg 4/4
998     dev[0].wait_connected()
999     stop_sake_assoc(dev[0], hapd)
1000 
1001     start_sake_assoc(dev[0], hapd)
1002     resp = rx_msg(dev[0])
1003     # Too short EAP-SAKE header
1004     # --> EAP-SAKE: Invalid frame
1005     msg = resp[0:4] + "0007" + resp[8:12] + "0007" + "300200"
1006     tx_msg(dev[0], hapd, msg)
1007     # Unknown version
1008     # --> EAP-SAKE: Unknown version 1
1009     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "30010000"
1010     tx_msg(dev[0], hapd, msg)
1011     # Unknown session
1012     # --> EAP-SAKE: Session ID mismatch
1013     sess, = struct.unpack('B', binascii.unhexlify(resp[20:22]))
1014     sess = binascii.hexlify(struct.pack('B', (sess + 1) % 256)).decode()
1015     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "3002" + sess + "00"
1016     tx_msg(dev[0], hapd, msg)
1017     # Unknown subtype
1018     # --> EAP-SAKE: Unexpected subtype=5 in state=1
1019     msg = resp[0:22] + "05" + resp[24:]
1020     tx_msg(dev[0], hapd, msg)
1021     # Empty challenge
1022     # --> EAP-SAKE: Response/Challenge did not include AT_RAND_P or AT_MIC_P
1023     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + resp[16:24]
1024     tx_msg(dev[0], hapd, msg)
1025     rx_msg(hapd)
1026     stop_sake_assoc(dev[0], hapd)
1027 
1028     start_sake_assoc(dev[0], hapd)
1029     resp = rx_msg(dev[0])
1030     # Invalid attribute in challenge
1031     # --> EAP-SAKE: Too short attribute
1032     msg = resp[0:4] + "0009" + resp[8:12] + "0009" + resp[16:26]
1033     tx_msg(dev[0], hapd, msg)
1034     rx_msg(hapd)
1035     stop_sake_assoc(dev[0], hapd)
1036 
1037     start_sake_assoc(dev[0], hapd)
1038     proxy_msg(dev[0], hapd) # SAKE/Challenge/Response
1039     proxy_msg(hapd, dev[0]) # SAKE/Confirm/Request
1040     resp = rx_msg(dev[0])
1041     # Empty confirm
1042     # --> EAP-SAKE: Response/Confirm did not include AT_MIC_P
1043     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + resp[16:26]
1044     tx_msg(dev[0], hapd, msg)
1045     rx_msg(hapd)
1046     stop_sake_assoc(dev[0], hapd)
1047 
1048     start_sake_assoc(dev[0], hapd)
1049     proxy_msg(dev[0], hapd) # SAKE/Challenge/Response
1050     proxy_msg(hapd, dev[0]) # SAKE/Confirm/Request
1051     resp = rx_msg(dev[0])
1052     # Invalid attribute in confirm
1053     # --> EAP-SAKE: Too short attribute
1054     msg = resp[0:4] + "0009" + resp[8:12] + "0009" + resp[16:26]
1055     tx_msg(dev[0], hapd, msg)
1056     rx_msg(hapd)
1057     stop_sake_assoc(dev[0], hapd)
1058 
1059     start_sake_assoc(dev[0], hapd)
1060     proxy_msg(dev[0], hapd) # SAKE/Challenge/Response
1061     proxy_msg(hapd, dev[0]) # SAKE/Confirm/Request
1062     resp = rx_msg(dev[0])
1063     # Corrupted AT_MIC_P value
1064     # --> EAP-SAKE: Incorrect AT_MIC_P
1065     msg = resp[0:30] + "000000000000" + resp[42:]
1066     tx_msg(dev[0], hapd, msg)
1067     rx_msg(hapd)
1068     stop_sake_assoc(dev[0], hapd)
1069 
1070 def test_eap_proto_leap(dev, apdev):
1071     """EAP-LEAP protocol tests"""
1072     check_eap_capa(dev[0], "LEAP")
1073     def leap_handler(ctx, req):
1074         logger.info("leap_handler - RX " + binascii.hexlify(req).decode())
1075         if 'num' not in ctx:
1076             ctx['num'] = 0
1077         ctx['num'] = ctx['num'] + 1
1078         if 'id' not in ctx:
1079             ctx['id'] = 1
1080         ctx['id'] = (ctx['id'] + 1) % 256
1081 
1082         if ctx['num'] == 1:
1083             logger.info("Test: Missing payload")
1084             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1085                                4 + 1,
1086                                EAP_TYPE_LEAP)
1087 
1088         if ctx['num'] == 2:
1089             logger.info("Test: Unexpected version")
1090             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
1091                                4 + 1 + 3,
1092                                EAP_TYPE_LEAP,
1093                                0, 0, 0)
1094 
1095         if ctx['num'] == 3:
1096             logger.info("Test: Invalid challenge length")
1097             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
1098                                4 + 1 + 3,
1099                                EAP_TYPE_LEAP,
1100                                1, 0, 0)
1101 
1102         if ctx['num'] == 4:
1103             logger.info("Test: Truncated challenge")
1104             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
1105                                4 + 1 + 3,
1106                                EAP_TYPE_LEAP,
1107                                1, 0, 8)
1108 
1109         if ctx['num'] == 5:
1110             logger.info("Test: Valid challenge")
1111             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1112                                4 + 1 + 3 + 8,
1113                                EAP_TYPE_LEAP,
1114                                1, 0, 8, 0, 0)
1115         if ctx['num'] == 6:
1116             logger.info("Test: Missing payload in Response")
1117             return struct.pack(">BBHB", EAP_CODE_RESPONSE, ctx['id'],
1118                                4 + 1,
1119                                EAP_TYPE_LEAP)
1120 
1121         if ctx['num'] == 7:
1122             logger.info("Test: Valid challenge")
1123             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1124                                4 + 1 + 3 + 8,
1125                                EAP_TYPE_LEAP,
1126                                1, 0, 8, 0, 0)
1127         if ctx['num'] == 8:
1128             logger.info("Test: Unexpected version in Response")
1129             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
1130                                4 + 1 + 3,
1131                                EAP_TYPE_LEAP,
1132                                0, 0, 8)
1133 
1134         if ctx['num'] == 9:
1135             logger.info("Test: Valid challenge")
1136             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1137                                4 + 1 + 3 + 8,
1138                                EAP_TYPE_LEAP,
1139                                1, 0, 8, 0, 0)
1140         if ctx['num'] == 10:
1141             logger.info("Test: Invalid challenge length in Response")
1142             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
1143                                4 + 1 + 3,
1144                                EAP_TYPE_LEAP,
1145                                1, 0, 0)
1146 
1147         if ctx['num'] == 11:
1148             logger.info("Test: Valid challenge")
1149             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1150                                4 + 1 + 3 + 8,
1151                                EAP_TYPE_LEAP,
1152                                1, 0, 8, 0, 0)
1153         if ctx['num'] == 12:
1154             logger.info("Test: Truncated challenge in Response")
1155             return struct.pack(">BBHBBBB", EAP_CODE_RESPONSE, ctx['id'],
1156                                4 + 1 + 3,
1157                                EAP_TYPE_LEAP,
1158                                1, 0, 24)
1159 
1160         if ctx['num'] == 13:
1161             logger.info("Test: Valid challenge")
1162             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1163                                4 + 1 + 3 + 8,
1164                                EAP_TYPE_LEAP,
1165                                1, 0, 8, 0, 0)
1166         if ctx['num'] == 14:
1167             logger.info("Test: Invalid challange value in Response")
1168             return struct.pack(">BBHBBBB6L", EAP_CODE_RESPONSE, ctx['id'],
1169                                4 + 1 + 3 + 24,
1170                                EAP_TYPE_LEAP,
1171                                1, 0, 24,
1172                                0, 0, 0, 0, 0, 0)
1173 
1174         if ctx['num'] == 15:
1175             logger.info("Test: Valid challenge")
1176             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1177                                4 + 1 + 3 + 8,
1178                                EAP_TYPE_LEAP,
1179                                1, 0, 8, 0, 0)
1180         if ctx['num'] == 16:
1181             logger.info("Test: Valid challange value in Response")
1182             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1183                                4 + 1 + 3 + 24,
1184                                EAP_TYPE_LEAP,
1185                                1, 0, 24,
1186                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1187                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1188                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1189 
1190         if ctx['num'] == 17:
1191             logger.info("Test: Valid challenge")
1192             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1193                                4 + 1 + 3 + 8,
1194                                EAP_TYPE_LEAP,
1195                                1, 0, 8, 0, 0)
1196         if ctx['num'] == 18:
1197             logger.info("Test: Success")
1198             return struct.pack(">BBHB", EAP_CODE_SUCCESS, ctx['id'],
1199                                4 + 1,
1200                                EAP_TYPE_LEAP)
1201         # hostapd will drop the next frame in the sequence
1202 
1203         if ctx['num'] == 19:
1204             logger.info("Test: Valid challenge")
1205             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1206                                4 + 1 + 3 + 8,
1207                                EAP_TYPE_LEAP,
1208                                1, 0, 8, 0, 0)
1209         if ctx['num'] == 20:
1210             logger.info("Test: Failure")
1211             return struct.pack(">BBHB", EAP_CODE_FAILURE, ctx['id'],
1212                                4 + 1,
1213                                EAP_TYPE_LEAP)
1214 
1215         return None
1216 
1217     srv = start_radius_server(leap_handler)
1218 
1219     try:
1220         hapd = start_ap(apdev[0])
1221         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1222 
1223         for i in range(0, 12):
1224             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1225                            eap="LEAP", identity="user", password="password",
1226                            wait_connect=False)
1227             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
1228             if ev is None:
1229                 raise Exception("Timeout on EAP start")
1230             time.sleep(0.1)
1231             if i == 10:
1232                 logger.info("Wait for additional roundtrip")
1233                 time.sleep(1)
1234             dev[0].request("REMOVE_NETWORK all")
1235     finally:
1236         stop_radius_server(srv)
1237 
1238 def test_eap_proto_leap_errors(dev, apdev):
1239     """EAP-LEAP protocol tests (error paths)"""
1240     check_eap_capa(dev[0], "LEAP")
1241 
1242     def leap_handler2(ctx, req):
1243         logger.info("leap_handler2 - RX " + binascii.hexlify(req).decode())
1244         if 'num' not in ctx:
1245             ctx['num'] = 0
1246         ctx['num'] = ctx['num'] + 1
1247         if 'id' not in ctx:
1248             ctx['id'] = 1
1249         ctx['id'] = (ctx['id'] + 1) % 256
1250         idx = 0
1251 
1252         idx += 1
1253         if ctx['num'] == idx:
1254             logger.info("Test: Valid challenge")
1255             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1256                                4 + 1 + 3 + 8,
1257                                EAP_TYPE_LEAP,
1258                                1, 0, 8, 0, 0)
1259         idx += 1
1260         if ctx['num'] == idx:
1261             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1262 
1263         idx += 1
1264         if ctx['num'] == idx:
1265             logger.info("Test: Valid challenge")
1266             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1267                                4 + 1 + 3 + 8,
1268                                EAP_TYPE_LEAP,
1269                                1, 0, 8, 0, 0)
1270 
1271         idx += 1
1272         if ctx['num'] == idx:
1273             logger.info("Test: Valid challenge")
1274             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1275                                4 + 1 + 3 + 8,
1276                                EAP_TYPE_LEAP,
1277                                1, 0, 8, 0, 0)
1278         idx += 1
1279         if ctx['num'] == idx:
1280             logger.info("Test: Success")
1281             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
1282 
1283         idx += 1
1284         if ctx['num'] == idx:
1285             logger.info("Test: Valid challenge")
1286             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1287                                4 + 1 + 3 + 8,
1288                                EAP_TYPE_LEAP,
1289                                1, 0, 8, 0, 0)
1290         idx += 1
1291         if ctx['num'] == idx:
1292             logger.info("Test: Success")
1293             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
1294 
1295         idx += 1
1296         if ctx['num'] == idx:
1297             logger.info("Test: Valid challenge")
1298             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1299                                4 + 1 + 3 + 8,
1300                                EAP_TYPE_LEAP,
1301                                1, 0, 8, 0, 0)
1302         idx += 1
1303         if ctx['num'] == idx:
1304             logger.info("Test: Valid challange value in Response")
1305             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1306                                4 + 1 + 3 + 24,
1307                                EAP_TYPE_LEAP,
1308                                1, 0, 24,
1309                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1310                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1311                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1312 
1313         idx += 1
1314         if ctx['num'] == idx:
1315             logger.info("Test: Valid challenge")
1316             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1317                                4 + 1 + 3 + 8,
1318                                EAP_TYPE_LEAP,
1319                                1, 0, 8, 0, 0)
1320         idx += 1
1321         if ctx['num'] == idx:
1322             logger.info("Test: Valid challange value in Response")
1323             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1324                                4 + 1 + 3 + 24,
1325                                EAP_TYPE_LEAP,
1326                                1, 0, 24,
1327                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1328                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1329                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1330 
1331         idx += 1
1332         if ctx['num'] == idx:
1333             logger.info("Test: Valid challenge")
1334             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1335                                4 + 1 + 3 + 8,
1336                                EAP_TYPE_LEAP,
1337                                1, 0, 8, 0, 0)
1338         idx += 1
1339         if ctx['num'] == idx:
1340             logger.info("Test: Valid challange value in Response")
1341             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1342                                4 + 1 + 3 + 24,
1343                                EAP_TYPE_LEAP,
1344                                1, 0, 24,
1345                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1346                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1347                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1348 
1349         idx += 1
1350         if ctx['num'] == idx:
1351             logger.info("Test: Valid challenge")
1352             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1353                                4 + 1 + 3 + 8,
1354                                EAP_TYPE_LEAP,
1355                                1, 0, 8, 0, 0)
1356         idx += 1
1357         if ctx['num'] == idx:
1358             logger.info("Test: Valid challange value in Response")
1359             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1360                                4 + 1 + 3 + 24,
1361                                EAP_TYPE_LEAP,
1362                                1, 0, 24,
1363                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1364                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1365                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1366 
1367         idx += 1
1368         if ctx['num'] == idx:
1369             logger.info("Test: Valid challenge")
1370             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1371                                4 + 1 + 3 + 8,
1372                                EAP_TYPE_LEAP,
1373                                1, 0, 8, 0, 0)
1374         idx += 1
1375         if ctx['num'] == idx:
1376             logger.info("Test: Valid challange value in Response")
1377             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1378                                4 + 1 + 3 + 24,
1379                                EAP_TYPE_LEAP,
1380                                1, 0, 24,
1381                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1382                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1383                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1384 
1385         idx += 1
1386         if ctx['num'] == idx:
1387             logger.info("Test: Valid challenge")
1388             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1389                                4 + 1 + 3 + 8,
1390                                EAP_TYPE_LEAP,
1391                                1, 0, 8, 0, 0)
1392         idx += 1
1393         if ctx['num'] == idx:
1394             logger.info("Test: Valid challange value in Response")
1395             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1396                                4 + 1 + 3 + 24,
1397                                EAP_TYPE_LEAP,
1398                                1, 0, 24,
1399                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1400                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1401                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1402 
1403         idx += 1
1404         if ctx['num'] == idx:
1405             logger.info("Test: Valid challenge")
1406             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1407                                4 + 1 + 3 + 8,
1408                                EAP_TYPE_LEAP,
1409                                1, 0, 8, 0, 0)
1410         idx += 1
1411         if ctx['num'] == idx:
1412             logger.info("Test: Valid challange value in Response")
1413             return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
1414                                4 + 1 + 3 + 24,
1415                                EAP_TYPE_LEAP,
1416                                1, 0, 24,
1417                                0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
1418                                0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
1419                                0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
1420 
1421         idx += 1
1422         if ctx['num'] == idx:
1423             logger.info("Test: Valid challenge")
1424             return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
1425                                4 + 1 + 3 + 8,
1426                                EAP_TYPE_LEAP,
1427                                1, 0, 8, 0, 0)
1428 
1429         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1430 
1431     srv = start_radius_server(leap_handler2)
1432 
1433     try:
1434         hapd = start_ap(apdev[0])
1435         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1436 
1437         with alloc_fail(dev[0], 1, "eap_leap_init"):
1438             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1439                            eap="LEAP", identity="user", password="password",
1440                            wait_connect=False)
1441             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1442             dev[0].request("REMOVE_NETWORK all")
1443             dev[0].wait_disconnected()
1444 
1445         with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_leap_process_request"):
1446             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1447                            eap="LEAP", identity="user",
1448                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1449                            wait_connect=False)
1450             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1451             dev[0].request("REMOVE_NETWORK all")
1452             dev[0].wait_disconnected()
1453 
1454         with alloc_fail(dev[0], 1, "eap_leap_process_success"):
1455             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1456                            eap="LEAP", identity="user", password="password",
1457                            wait_connect=False)
1458             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1459             dev[0].request("REMOVE_NETWORK all")
1460             dev[0].wait_disconnected()
1461 
1462         with fail_test(dev[0], 1, "os_get_random;eap_leap_process_success"):
1463             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1464                            eap="LEAP", identity="user", password="password",
1465                            wait_connect=False)
1466             wait_fail_trigger(dev[0], "GET_FAIL")
1467             dev[0].request("REMOVE_NETWORK all")
1468             dev[0].wait_disconnected()
1469 
1470         with fail_test(dev[0], 1, "eap_leap_process_response"):
1471             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1472                            eap="LEAP", identity="user",
1473                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1474                            wait_connect=False)
1475             wait_fail_trigger(dev[0], "GET_FAIL")
1476             dev[0].request("REMOVE_NETWORK all")
1477             dev[0].wait_disconnected()
1478 
1479         with fail_test(dev[0], 1, "nt_password_hash;eap_leap_process_response"):
1480             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1481                            eap="LEAP", identity="user", password="password",
1482                            wait_connect=False)
1483             wait_fail_trigger(dev[0], "GET_FAIL")
1484             dev[0].request("REMOVE_NETWORK all")
1485             dev[0].wait_disconnected()
1486 
1487         with fail_test(dev[0], 1, "hash_nt_password_hash;eap_leap_process_response"):
1488             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1489                            eap="LEAP", identity="user", password="password",
1490                            wait_connect=False)
1491             wait_fail_trigger(dev[0], "GET_FAIL")
1492             dev[0].request("REMOVE_NETWORK all")
1493             dev[0].wait_disconnected()
1494 
1495         with alloc_fail(dev[0], 1, "eap_leap_getKey"):
1496             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1497                            eap="LEAP", identity="user",
1498                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1499                            wait_connect=False)
1500             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1501             dev[0].request("REMOVE_NETWORK all")
1502             dev[0].wait_disconnected()
1503 
1504         with fail_test(dev[0], 1, "eap_leap_getKey"):
1505             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1506                            eap="LEAP", identity="user",
1507                            password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
1508                            wait_connect=False)
1509             wait_fail_trigger(dev[0], "GET_FAIL")
1510             dev[0].request("REMOVE_NETWORK all")
1511             dev[0].wait_disconnected()
1512 
1513         with fail_test(dev[0], 1, "nt_password_hash;eap_leap_getKey"):
1514             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1515                            eap="LEAP", identity="user", password="password",
1516                            wait_connect=False)
1517             wait_fail_trigger(dev[0], "GET_FAIL")
1518             dev[0].request("REMOVE_NETWORK all")
1519             dev[0].wait_disconnected()
1520 
1521         with fail_test(dev[0], 1, "hash_nt_password_hash;eap_leap_getKey"):
1522             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1523                            eap="LEAP", identity="user", password="password",
1524                            wait_connect=False)
1525             wait_fail_trigger(dev[0], "GET_FAIL")
1526             dev[0].request("REMOVE_NETWORK all")
1527             dev[0].wait_disconnected()
1528 
1529         with fail_test(dev[0], 1,
1530                        "nt_challenge_response;eap_leap_process_request"):
1531             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1532                            eap="LEAP", identity="user", password="password",
1533                            wait_connect=False)
1534             wait_fail_trigger(dev[0], "GET_FAIL")
1535             dev[0].request("REMOVE_NETWORK all")
1536             dev[0].wait_disconnected()
1537     finally:
1538         stop_radius_server(srv)
1539 
1540 def test_eap_proto_md5(dev, apdev):
1541     """EAP-MD5 protocol tests"""
1542     check_eap_capa(dev[0], "MD5")
1543 
1544     def md5_handler(ctx, req):
1545         logger.info("md5_handler - RX " + binascii.hexlify(req).decode())
1546         if 'num' not in ctx:
1547             ctx['num'] = 0
1548         ctx['num'] = ctx['num'] + 1
1549         if 'id' not in ctx:
1550             ctx['id'] = 1
1551         ctx['id'] = (ctx['id'] + 1) % 256
1552 
1553         if ctx['num'] == 1:
1554             logger.info("Test: Missing payload")
1555             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1556                                4 + 1,
1557                                EAP_TYPE_MD5)
1558 
1559         if ctx['num'] == 2:
1560             logger.info("Test: Zero-length challenge")
1561             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1562                                4 + 1 + 1,
1563                                EAP_TYPE_MD5,
1564                                0)
1565 
1566         if ctx['num'] == 3:
1567             logger.info("Test: Truncated challenge")
1568             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1569                                4 + 1 + 1,
1570                                EAP_TYPE_MD5,
1571                                1)
1572 
1573         if ctx['num'] == 4:
1574             logger.info("Test: Shortest possible challenge and name")
1575             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
1576                                4 + 1 + 3,
1577                                EAP_TYPE_MD5,
1578                                1, 0xaa, ord('n'))
1579 
1580         return None
1581 
1582     srv = start_radius_server(md5_handler)
1583 
1584     try:
1585         hapd = start_ap(apdev[0])
1586         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1587 
1588         for i in range(0, 4):
1589             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1590                            eap="MD5", identity="user", password="password",
1591                            wait_connect=False)
1592             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
1593             if ev is None:
1594                 raise Exception("Timeout on EAP start")
1595             time.sleep(0.1)
1596             dev[0].request("REMOVE_NETWORK all")
1597     finally:
1598         stop_radius_server(srv)
1599 
1600 def test_eap_proto_md5_errors(dev, apdev):
1601     """EAP-MD5 local error cases"""
1602     check_eap_capa(dev[0], "MD5")
1603     params = hostapd.wpa2_eap_params(ssid="eap-test")
1604     hapd = hostapd.add_ap(apdev[0], params)
1605     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1606 
1607     with fail_test(dev[0], 1, "chap_md5"):
1608         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1609                        eap="MD5", identity="phase1-user", password="password",
1610                        wait_connect=False)
1611         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
1612         if ev is None:
1613             raise Exception("Timeout on EAP start")
1614         dev[0].request("REMOVE_NETWORK all")
1615         dev[0].wait_disconnected()
1616 
1617     with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_md5_process"):
1618         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1619                        eap="MD5", identity="phase1-user", password="password",
1620                        wait_connect=False)
1621         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
1622         if ev is None:
1623             raise Exception("Timeout on EAP start")
1624         time.sleep(0.1)
1625         dev[0].request("REMOVE_NETWORK all")
1626 
1627 def run_eap_md5_connect(dev):
1628     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
1629                 eap="MD5", identity="phase1-user", password="password",
1630                 wait_connect=False)
1631     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
1632                          "CTRL-EVENT-DISCONNECTED"],
1633                         timeout=1)
1634     dev.request("REMOVE_NETWORK all")
1635     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
1636         dev.wait_disconnected()
1637     dev.dump_monitor()
1638 
1639 def test_eap_proto_md5_errors_server(dev, apdev):
1640     """EAP-MD5 local error cases on server"""
1641     check_eap_capa(dev[0], "MD5")
1642     params = int_eap_server_params()
1643     params['erp_domain'] = 'example.com'
1644     params['eap_server_erp'] = '1'
1645     hapd = hostapd.add_ap(apdev[0], params)
1646     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1647 
1648     tests = [(1, "eap_md5_init")]
1649     for count, func in tests:
1650         with alloc_fail(hapd, count, func):
1651             run_eap_md5_connect(dev[0])
1652 
1653     tests = [(1, "os_get_random;eap_md5_buildReq"),
1654              (1, "chap_md5;eap_md5_process")]
1655     for count, func in tests:
1656         with fail_test(hapd, count, func):
1657             run_eap_md5_connect(dev[0])
1658 
1659 def start_md5_assoc(dev, hapd):
1660     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
1661                 eap="MD5", identity="phase1-user", password="password",
1662                 wait_connect=False)
1663     proxy_msg(hapd, dev) # EAP-Identity/Request
1664     proxy_msg(dev, hapd) # EAP-Identity/Response
1665     proxy_msg(hapd, dev) # MSCHAPV2/Request
1666     proxy_msg(dev, hapd) # NAK
1667     proxy_msg(hapd, dev) # MD5 Request
1668 
1669 def stop_md5_assoc(dev, hapd, wait=True):
1670     dev.request("REMOVE_NETWORK all")
1671     if wait:
1672         dev.wait_disconnected()
1673     dev.dump_monitor()
1674     hapd.dump_monitor()
1675 
1676 def test_eap_proto_md5_server(dev, apdev):
1677     """EAP-MD5 protocol testing for the server"""
1678     check_eap_capa(dev[0], "MD5")
1679     params = int_eap_server_params()
1680     params['erp_domain'] = 'example.com'
1681     params['eap_server_erp'] = '1'
1682     hapd = hostapd.add_ap(apdev[0], params)
1683     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1684     hapd.request("SET ext_eapol_frame_io 1")
1685     dev[0].request("SET ext_eapol_frame_io 1")
1686 
1687     # Successful exchange to verify proxying mechanism
1688     start_md5_assoc(dev[0], hapd)
1689     proxy_msg(dev[0], hapd) # MD5 Response
1690     proxy_msg(hapd, dev[0]) # EAP-Success
1691     # Accept both EAP-Success and disconnection indication since it is possible
1692     # for disconnection from the AP (due to EAP-MD5 not deriving keys) to be
1693     # processed more quickly.
1694     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS",
1695                             "CTRL-EVENT-DISCONNECTED"], timeout=5)
1696     if ev is None:
1697         raise Exception("No EAP-Success reported")
1698     stop_md5_assoc(dev[0], hapd, wait="CTRL-EVENT-EAP-SUCCESS" in ev)
1699 
1700     start_md5_assoc(dev[0], hapd)
1701     resp = rx_msg(dev[0])
1702     # Too short EAP-MD5 header (no length field)
1703     hapd.note("EAP-MD5: Invalid frame")
1704     msg = resp[0:4] + "0005" + resp[8:12] + "0005" + "04"
1705     tx_msg(dev[0], hapd, msg)
1706     # Too short EAP-MD5 header (no length field)
1707     hapd.note("EAP-MD5: Invalid response (response_len=0 payload_len=1")
1708     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "0400"
1709     tx_msg(dev[0], hapd, msg)
1710     stop_md5_assoc(dev[0], hapd)
1711 
1712 def test_eap_proto_otp(dev, apdev):
1713     """EAP-OTP protocol tests"""
1714     def otp_handler(ctx, req):
1715         logger.info("otp_handler - RX " + binascii.hexlify(req).decode())
1716         if 'num' not in ctx:
1717             ctx['num'] = 0
1718         ctx['num'] = ctx['num'] + 1
1719         if 'id' not in ctx:
1720             ctx['id'] = 1
1721         ctx['id'] = (ctx['id'] + 1) % 256
1722 
1723         if ctx['num'] == 1:
1724             logger.info("Test: Empty payload")
1725             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1726                                4 + 1,
1727                                EAP_TYPE_OTP)
1728         if ctx['num'] == 2:
1729             logger.info("Test: Success")
1730             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
1731                                4)
1732 
1733         if ctx['num'] == 3:
1734             logger.info("Test: Challenge included")
1735             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1736                                4 + 1 + 1,
1737                                EAP_TYPE_OTP,
1738                                ord('A'))
1739         if ctx['num'] == 4:
1740             logger.info("Test: Success")
1741             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
1742                                4)
1743 
1744         return None
1745 
1746     srv = start_radius_server(otp_handler)
1747 
1748     try:
1749         hapd = start_ap(apdev[0])
1750         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1751 
1752         for i in range(0, 1):
1753             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1754                            eap="OTP", identity="user", password="password",
1755                            wait_connect=False)
1756             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
1757                                    timeout=15)
1758             if ev is None:
1759                 raise Exception("Timeout on EAP start")
1760             time.sleep(0.1)
1761             dev[0].request("REMOVE_NETWORK all")
1762 
1763         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1764                        eap="OTP", identity="user", wait_connect=False)
1765         ev = dev[0].wait_event(["CTRL-REQ-OTP"])
1766         if ev is None:
1767             raise Exception("Request for password timed out")
1768         id = ev.split(':')[0].split('-')[-1]
1769         dev[0].request("CTRL-RSP-OTP-" + id + ":password")
1770         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"])
1771         if ev is None:
1772             raise Exception("Success not reported")
1773     finally:
1774         stop_radius_server(srv)
1775 
1776 def test_eap_proto_otp_errors(dev, apdev):
1777     """EAP-OTP local error cases"""
1778     def otp_handler2(ctx, req):
1779         logger.info("otp_handler2 - RX " + binascii.hexlify(req).decode())
1780         if 'num' not in ctx:
1781             ctx['num'] = 0
1782         ctx['num'] = ctx['num'] + 1
1783         if 'id' not in ctx:
1784             ctx['id'] = 1
1785         ctx['id'] = (ctx['id'] + 1) % 256
1786         idx = 0
1787 
1788         idx += 1
1789         if ctx['num'] == idx:
1790             logger.info("Test: Challenge included")
1791             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1792                                4 + 1 + 1,
1793                                EAP_TYPE_OTP,
1794                                ord('A'))
1795 
1796         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
1797 
1798     srv = start_radius_server(otp_handler2)
1799 
1800     try:
1801         hapd = start_ap(apdev[0])
1802         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
1803 
1804         with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_otp_process"):
1805             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
1806                            eap="OTP", identity="user", password="password",
1807                            wait_connect=False)
1808             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
1809             dev[0].request("REMOVE_NETWORK all")
1810             dev[0].wait_disconnected()
1811     finally:
1812         stop_radius_server(srv)
1813 
1814 EAP_GPSK_OPCODE_GPSK_1 = 1
1815 EAP_GPSK_OPCODE_GPSK_2 = 2
1816 EAP_GPSK_OPCODE_GPSK_3 = 3
1817 EAP_GPSK_OPCODE_GPSK_4 = 4
1818 EAP_GPSK_OPCODE_FAIL = 5
1819 EAP_GPSK_OPCODE_PROTECTED_FAIL = 6
1820 
1821 def test_eap_proto_gpsk(dev, apdev):
1822     """EAP-GPSK protocol tests"""
1823     def gpsk_handler(ctx, req):
1824         logger.info("gpsk_handler - RX " + binascii.hexlify(req).decode())
1825         if 'num' not in ctx:
1826             ctx['num'] = 0
1827         ctx['num'] = ctx['num'] + 1
1828         if 'id' not in ctx:
1829             ctx['id'] = 1
1830         ctx['id'] = (ctx['id'] + 1) % 256
1831 
1832         idx = 0
1833 
1834         idx += 1
1835         if ctx['num'] == idx:
1836             logger.info("Test: Missing payload")
1837             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
1838                                4 + 1,
1839                                EAP_TYPE_GPSK)
1840 
1841         idx += 1
1842         if ctx['num'] == idx:
1843             logger.info("Test: Unknown opcode")
1844             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1845                                4 + 1 + 1,
1846                                EAP_TYPE_GPSK,
1847                                255)
1848 
1849         idx += 1
1850         if ctx['num'] == idx:
1851             logger.info("Test: Unexpected GPSK-3")
1852             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1853                                4 + 1 + 1,
1854                                EAP_TYPE_GPSK,
1855                                EAP_GPSK_OPCODE_GPSK_3)
1856 
1857         idx += 1
1858         if ctx['num'] == idx:
1859             logger.info("Test: GPSK-1 Too short GPSK-1")
1860             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1861                                4 + 1 + 1,
1862                                EAP_TYPE_GPSK,
1863                                EAP_GPSK_OPCODE_GPSK_1)
1864 
1865         idx += 1
1866         if ctx['num'] == idx:
1867             logger.info("Test: GPSK-1 Truncated ID_Server")
1868             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
1869                                4 + 1 + 1 + 2,
1870                                EAP_TYPE_GPSK,
1871                                EAP_GPSK_OPCODE_GPSK_1, 1)
1872 
1873         idx += 1
1874         if ctx['num'] == idx:
1875             logger.info("Test: GPSK-1 Missing RAND_Server")
1876             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
1877                                4 + 1 + 1 + 2,
1878                                EAP_TYPE_GPSK,
1879                                EAP_GPSK_OPCODE_GPSK_1, 0)
1880 
1881         idx += 1
1882         if ctx['num'] == idx:
1883             logger.info("Test: GPSK-1 Missing CSuite_List")
1884             return struct.pack(">BBHBBH8L", EAP_CODE_REQUEST, ctx['id'],
1885                                4 + 1 + 1 + 2 + 32,
1886                                EAP_TYPE_GPSK,
1887                                EAP_GPSK_OPCODE_GPSK_1, 0,
1888                                0, 0, 0, 0, 0, 0, 0, 0)
1889 
1890         idx += 1
1891         if ctx['num'] == idx:
1892             logger.info("Test: GPSK-1 Truncated CSuite_List")
1893             return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
1894                                4 + 1 + 1 + 2 + 32 + 2,
1895                                EAP_TYPE_GPSK,
1896                                EAP_GPSK_OPCODE_GPSK_1, 0,
1897                                0, 0, 0, 0, 0, 0, 0, 0,
1898                                1)
1899 
1900         idx += 1
1901         if ctx['num'] == idx:
1902             logger.info("Test: GPSK-1 Empty CSuite_List")
1903             return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
1904                                4 + 1 + 1 + 2 + 32 + 2,
1905                                EAP_TYPE_GPSK,
1906                                EAP_GPSK_OPCODE_GPSK_1, 0,
1907                                0, 0, 0, 0, 0, 0, 0, 0,
1908                                0)
1909 
1910         idx += 1
1911         if ctx['num'] == idx:
1912             logger.info("Test: GPSK-1 Invalid CSuite_List")
1913             return struct.pack(">BBHBBH8LHB", EAP_CODE_REQUEST, ctx['id'],
1914                                4 + 1 + 1 + 2 + 32 + 2 + 1,
1915                                EAP_TYPE_GPSK,
1916                                EAP_GPSK_OPCODE_GPSK_1, 0,
1917                                0, 0, 0, 0, 0, 0, 0, 0,
1918                                1, 0)
1919 
1920         idx += 1
1921         if ctx['num'] == idx:
1922             logger.info("Test: GPSK-1 No supported CSuite")
1923             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1924                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1925                                EAP_TYPE_GPSK,
1926                                EAP_GPSK_OPCODE_GPSK_1, 0,
1927                                0, 0, 0, 0, 0, 0, 0, 0,
1928                                6, 0, 0)
1929 
1930         idx += 1
1931         if ctx['num'] == idx:
1932             logger.info("Test: GPSK-1 Supported CSuite")
1933             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1934                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1935                                EAP_TYPE_GPSK,
1936                                EAP_GPSK_OPCODE_GPSK_1, 0,
1937                                0, 0, 0, 0, 0, 0, 0, 0,
1938                                6, 0, 1)
1939         idx += 1
1940         if ctx['num'] == idx:
1941             logger.info("Test: Unexpected GPSK-1")
1942             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1943                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1944                                EAP_TYPE_GPSK,
1945                                EAP_GPSK_OPCODE_GPSK_1, 0,
1946                                0, 0, 0, 0, 0, 0, 0, 0,
1947                                6, 0, 1)
1948 
1949         idx += 1
1950         if ctx['num'] == idx:
1951             logger.info("Test: GPSK-1 Supported CSuite but too short key")
1952             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1953                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1954                                EAP_TYPE_GPSK,
1955                                EAP_GPSK_OPCODE_GPSK_1, 0,
1956                                0, 0, 0, 0, 0, 0, 0, 0,
1957                                6, 0, 1)
1958 
1959         idx += 1
1960         if ctx['num'] == idx:
1961             logger.info("Test: GPSK-1 Supported CSuite")
1962             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1963                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1964                                EAP_TYPE_GPSK,
1965                                EAP_GPSK_OPCODE_GPSK_1, 0,
1966                                0, 0, 0, 0, 0, 0, 0, 0,
1967                                6, 0, 1)
1968         idx += 1
1969         if ctx['num'] == idx:
1970             logger.info("Test: Too short GPSK-3")
1971             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
1972                                4 + 1 + 1,
1973                                EAP_TYPE_GPSK,
1974                                EAP_GPSK_OPCODE_GPSK_3)
1975 
1976         idx += 1
1977         if ctx['num'] == idx:
1978             logger.info("Test: GPSK-1 Supported CSuite")
1979             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1980                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1981                                EAP_TYPE_GPSK,
1982                                EAP_GPSK_OPCODE_GPSK_1, 0,
1983                                0, 0, 0, 0, 0, 0, 0, 0,
1984                                6, 0, 1)
1985         idx += 1
1986         if ctx['num'] == idx:
1987             logger.info("Test: GPSK-3 Mismatch in RAND_Peer")
1988             return struct.pack(">BBHBB8L", EAP_CODE_REQUEST, ctx['id'],
1989                                4 + 1 + 1 + 32,
1990                                EAP_TYPE_GPSK,
1991                                EAP_GPSK_OPCODE_GPSK_3,
1992                                0, 0, 0, 0, 0, 0, 0, 0)
1993 
1994         idx += 1
1995         if ctx['num'] == idx:
1996             logger.info("Test: GPSK-1 Supported CSuite")
1997             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
1998                                4 + 1 + 1 + 2 + 32 + 2 + 6,
1999                                EAP_TYPE_GPSK,
2000                                EAP_GPSK_OPCODE_GPSK_1, 0,
2001                                0, 0, 0, 0, 0, 0, 0, 0,
2002                                6, 0, 1)
2003         idx += 1
2004         if ctx['num'] == idx:
2005             logger.info("Test: GPSK-3 Missing RAND_Server")
2006             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2007                               4 + 1 + 1 + 32,
2008                               EAP_TYPE_GPSK,
2009                               EAP_GPSK_OPCODE_GPSK_3)
2010             msg += req[14:46]
2011             return msg
2012 
2013         idx += 1
2014         if ctx['num'] == idx:
2015             logger.info("Test: GPSK-1 Supported CSuite")
2016             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2017                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2018                                EAP_TYPE_GPSK,
2019                                EAP_GPSK_OPCODE_GPSK_1, 0,
2020                                0, 0, 0, 0, 0, 0, 0, 0,
2021                                6, 0, 1)
2022         idx += 1
2023         if ctx['num'] == idx:
2024             logger.info("Test: GPSK-3 Mismatch in RAND_Server")
2025             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2026                               4 + 1 + 1 + 32 + 32,
2027                               EAP_TYPE_GPSK,
2028                               EAP_GPSK_OPCODE_GPSK_3)
2029             msg += req[14:46]
2030             msg += struct.pack(">8L", 1, 1, 1, 1, 1, 1, 1, 1)
2031             return msg
2032 
2033         idx += 1
2034         if ctx['num'] == idx:
2035             logger.info("Test: GPSK-1 Supported CSuite")
2036             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2037                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2038                                EAP_TYPE_GPSK,
2039                                EAP_GPSK_OPCODE_GPSK_1, 0,
2040                                0, 0, 0, 0, 0, 0, 0, 0,
2041                                6, 0, 1)
2042         idx += 1
2043         if ctx['num'] == idx:
2044             logger.info("Test: GPSK-3 Missing ID_Server")
2045             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2046                               4 + 1 + 1 + 32 + 32,
2047                               EAP_TYPE_GPSK,
2048                               EAP_GPSK_OPCODE_GPSK_3)
2049             msg += req[14:46]
2050             msg += struct.pack(">8L", 0, 0, 0, 0, 0, 0, 0, 0)
2051             return msg
2052 
2053         idx += 1
2054         if ctx['num'] == idx:
2055             logger.info("Test: GPSK-1 Supported CSuite")
2056             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2057                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2058                                EAP_TYPE_GPSK,
2059                                EAP_GPSK_OPCODE_GPSK_1, 0,
2060                                0, 0, 0, 0, 0, 0, 0, 0,
2061                                6, 0, 1)
2062         idx += 1
2063         if ctx['num'] == idx:
2064             logger.info("Test: GPSK-3 Truncated ID_Server")
2065             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2066                               4 + 1 + 1 + 32 + 32 + 2,
2067                               EAP_TYPE_GPSK,
2068                               EAP_GPSK_OPCODE_GPSK_3)
2069             msg += req[14:46]
2070             msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 1)
2071             return msg
2072 
2073         idx += 1
2074         if ctx['num'] == idx:
2075             logger.info("Test: GPSK-1 Supported CSuite")
2076             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2077                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2078                                EAP_TYPE_GPSK,
2079                                EAP_GPSK_OPCODE_GPSK_1, 0,
2080                                0, 0, 0, 0, 0, 0, 0, 0,
2081                                6, 0, 1)
2082         idx += 1
2083         if ctx['num'] == idx:
2084             logger.info("Test: GPSK-3 Mismatch in ID_Server")
2085             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2086                               4 + 1 + 1 + 32 + 32 + 3,
2087                               EAP_TYPE_GPSK,
2088                               EAP_GPSK_OPCODE_GPSK_3)
2089             msg += req[14:46]
2090             msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
2091             return msg
2092 
2093         idx += 1
2094         if ctx['num'] == idx:
2095             logger.info("Test: GPSK-1 Supported CSuite")
2096             return struct.pack(">BBHBBHB8LHLH", EAP_CODE_REQUEST, ctx['id'],
2097                                4 + 1 + 1 + 3 + 32 + 2 + 6,
2098                                EAP_TYPE_GPSK,
2099                                EAP_GPSK_OPCODE_GPSK_1, 1, ord('A'),
2100                                0, 0, 0, 0, 0, 0, 0, 0,
2101                                6, 0, 1)
2102         idx += 1
2103         if ctx['num'] == idx:
2104             logger.info("Test: GPSK-3 Mismatch in ID_Server (same length)")
2105             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2106                               4 + 1 + 1 + 32 + 32 + 3,
2107                               EAP_TYPE_GPSK,
2108                               EAP_GPSK_OPCODE_GPSK_3)
2109             msg += req[15:47]
2110             msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
2111             return msg
2112 
2113         idx += 1
2114         if ctx['num'] == idx:
2115             logger.info("Test: GPSK-1 Supported CSuite")
2116             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2117                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2118                                EAP_TYPE_GPSK,
2119                                EAP_GPSK_OPCODE_GPSK_1, 0,
2120                                0, 0, 0, 0, 0, 0, 0, 0,
2121                                6, 0, 1)
2122         idx += 1
2123         if ctx['num'] == idx:
2124             logger.info("Test: GPSK-3 Missing CSuite_Sel")
2125             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2126                               4 + 1 + 1 + 32 + 32 + 2,
2127                               EAP_TYPE_GPSK,
2128                               EAP_GPSK_OPCODE_GPSK_3)
2129             msg += req[14:46]
2130             msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 0)
2131             return msg
2132 
2133         idx += 1
2134         if ctx['num'] == idx:
2135             logger.info("Test: GPSK-1 Supported CSuite")
2136             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2137                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2138                                EAP_TYPE_GPSK,
2139                                EAP_GPSK_OPCODE_GPSK_1, 0,
2140                                0, 0, 0, 0, 0, 0, 0, 0,
2141                                6, 0, 1)
2142         idx += 1
2143         if ctx['num'] == idx:
2144             logger.info("Test: GPSK-3 Mismatch in CSuite_Sel")
2145             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2146                               4 + 1 + 1 + 32 + 32 + 2 + 6,
2147                               EAP_TYPE_GPSK,
2148                               EAP_GPSK_OPCODE_GPSK_3)
2149             msg += req[14:46]
2150             msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2)
2151             return msg
2152 
2153         idx += 1
2154         if ctx['num'] == idx:
2155             logger.info("Test: GPSK-1 Supported CSuite")
2156             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2157                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2158                                EAP_TYPE_GPSK,
2159                                EAP_GPSK_OPCODE_GPSK_1, 0,
2160                                0, 0, 0, 0, 0, 0, 0, 0,
2161                                6, 0, 1)
2162         idx += 1
2163         if ctx['num'] == idx:
2164             logger.info("Test: GPSK-3 Missing len(PD_Payload_Block)")
2165             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2166                               4 + 1 + 1 + 32 + 32 + 2 + 6,
2167                               EAP_TYPE_GPSK,
2168                               EAP_GPSK_OPCODE_GPSK_3)
2169             msg += req[14:46]
2170             msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
2171             return msg
2172 
2173         idx += 1
2174         if ctx['num'] == idx:
2175             logger.info("Test: GPSK-1 Supported CSuite")
2176             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2177                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2178                                EAP_TYPE_GPSK,
2179                                EAP_GPSK_OPCODE_GPSK_1, 0,
2180                                0, 0, 0, 0, 0, 0, 0, 0,
2181                                6, 0, 1)
2182         idx += 1
2183         if ctx['num'] == idx:
2184             logger.info("Test: GPSK-3 Truncated PD_Payload_Block")
2185             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2186                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 2,
2187                               EAP_TYPE_GPSK,
2188                               EAP_GPSK_OPCODE_GPSK_3)
2189             msg += req[14:46]
2190             msg += struct.pack(">8LHLHH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
2191             return msg
2192 
2193         idx += 1
2194         if ctx['num'] == idx:
2195             logger.info("Test: GPSK-1 Supported CSuite")
2196             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2197                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2198                                EAP_TYPE_GPSK,
2199                                EAP_GPSK_OPCODE_GPSK_1, 0,
2200                                0, 0, 0, 0, 0, 0, 0, 0,
2201                                6, 0, 1)
2202         idx += 1
2203         if ctx['num'] == idx:
2204             logger.info("Test: GPSK-3 Missing MAC")
2205             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2206                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 3,
2207                               EAP_TYPE_GPSK,
2208                               EAP_GPSK_OPCODE_GPSK_3)
2209             msg += req[14:46]
2210             msg += struct.pack(">8LHLHHB",
2211                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123)
2212             return msg
2213 
2214         idx += 1
2215         if ctx['num'] == idx:
2216             logger.info("Test: GPSK-1 Supported CSuite")
2217             return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
2218                                4 + 1 + 1 + 2 + 32 + 2 + 6,
2219                                EAP_TYPE_GPSK,
2220                                EAP_GPSK_OPCODE_GPSK_1, 0,
2221                                0, 0, 0, 0, 0, 0, 0, 0,
2222                                6, 0, 1)
2223         idx += 1
2224         if ctx['num'] == idx:
2225             logger.info("Test: GPSK-3 Incorrect MAC")
2226             msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2227                               4 + 1 + 1 + 32 + 32 + 2 + 6 + 3 + 16,
2228                               EAP_TYPE_GPSK,
2229                               EAP_GPSK_OPCODE_GPSK_3)
2230             msg += req[14:46]
2231             msg += struct.pack(">8LHLHHB4L",
2232                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123,
2233                                0, 0, 0, 0)
2234             return msg
2235 
2236         return None
2237 
2238     srv = start_radius_server(gpsk_handler)
2239 
2240     try:
2241         hapd = start_ap(apdev[0])
2242         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
2243 
2244         for i in range(0, 27):
2245             if i == 12:
2246                 pw = "short"
2247             else:
2248                 pw = "abcdefghijklmnop0123456789abcdef"
2249             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2250                            eap="GPSK", identity="user", password=pw,
2251                            wait_connect=False)
2252             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2253                                    timeout=15)
2254             if ev is None:
2255                 raise Exception("Timeout on EAP start")
2256             time.sleep(0.05)
2257             dev[0].request("REMOVE_NETWORK all")
2258     finally:
2259         stop_radius_server(srv)
2260 
2261 def run_eap_gpsk_connect(dev):
2262     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
2263                 eap="GPSK", identity="gpsk user",
2264                 password="abcdefghijklmnop0123456789abcdef",
2265                 wait_connect=False)
2266     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
2267                          "CTRL-EVENT-DISCONNECTED"],
2268                         timeout=1)
2269     dev.request("REMOVE_NETWORK all")
2270     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
2271         dev.wait_disconnected()
2272     dev.dump_monitor()
2273 
2274 def test_eap_proto_gpsk_errors_server(dev, apdev):
2275     """EAP-GPSK local error cases on server"""
2276     check_eap_capa(dev[0], "GPSK")
2277     params = int_eap_server_params()
2278     params['erp_domain'] = 'example.com'
2279     params['eap_server_erp'] = '1'
2280     hapd = hostapd.add_ap(apdev[0], params)
2281     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
2282 
2283     tests = [(1, "eap_gpsk_init"),
2284              (1, "eap_msg_alloc;eap_gpsk_build_gpsk_1"),
2285              (1, "eap_msg_alloc;eap_gpsk_build_gpsk_3"),
2286              (1, "eap_gpsk_process_gpsk_2"),
2287              (1, "eap_gpsk_derive_keys;eap_gpsk_process_gpsk_2"),
2288              (1, "eap_gpsk_derive_session_id;eap_gpsk_process_gpsk_2"),
2289              (1, "eap_gpsk_getKey"),
2290              (1, "eap_gpsk_get_emsk"),
2291              (1, "eap_gpsk_get_session_id")]
2292     for count, func in tests:
2293         with alloc_fail(hapd, count, func):
2294             run_eap_gpsk_connect(dev[0])
2295 
2296     tests = [(1, "os_get_random;eap_gpsk_build_gpsk_1"),
2297              (1, "eap_gpsk_compute_mic;eap_gpsk_build_gpsk_3"),
2298              (1, "eap_gpsk_derive_keys;eap_gpsk_process_gpsk_2"),
2299              (1, "eap_gpsk_derive_session_id;eap_gpsk_process_gpsk_2"),
2300              (1, "eap_gpsk_compute_mic;eap_gpsk_process_gpsk_2"),
2301              (1, "eap_gpsk_compute_mic;eap_gpsk_process_gpsk_4")]
2302     for count, func in tests:
2303         with fail_test(hapd, count, func):
2304             run_eap_gpsk_connect(dev[0])
2305 
2306 def start_gpsk_assoc(dev, hapd):
2307     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
2308                 eap="GPSK", identity="gpsk user",
2309                 password="abcdefghijklmnop0123456789abcdef",
2310                 wait_connect=False)
2311     proxy_msg(hapd, dev) # EAP-Identity/Request
2312     proxy_msg(dev, hapd) # EAP-Identity/Response
2313     proxy_msg(hapd, dev) # GPSK-1
2314 
2315 def stop_gpsk_assoc(dev, hapd):
2316     dev.request("REMOVE_NETWORK all")
2317     dev.wait_disconnected()
2318     dev.dump_monitor()
2319     hapd.dump_monitor()
2320 
2321 def test_eap_proto_gpsk_server(dev, apdev):
2322     """EAP-GPSK protocol testing for the server"""
2323     check_eap_capa(dev[0], "GPSK")
2324     params = int_eap_server_params()
2325     params['erp_domain'] = 'example.com'
2326     params['eap_server_erp'] = '1'
2327     hapd = hostapd.add_ap(apdev[0], params)
2328     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
2329     hapd.request("SET ext_eapol_frame_io 1")
2330     dev[0].request("SET ext_eapol_frame_io 1")
2331 
2332     # Successful exchange to verify proxying mechanism
2333     start_gpsk_assoc(dev[0], hapd)
2334     proxy_msg(dev[0], hapd) # GPSK-2
2335     proxy_msg(hapd, dev[0]) # GPSK-3
2336     proxy_msg(dev[0], hapd) # GPSK-4
2337     proxy_msg(hapd, dev[0]) # EAP-Success
2338     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 1/4
2339     proxy_msg(dev[0], hapd) # EAPOL-Key msg 2/4
2340     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 3/4
2341     proxy_msg(dev[0], hapd) # EAPOL-Key msg 4/4
2342     dev[0].wait_connected()
2343     stop_gpsk_assoc(dev[0], hapd)
2344 
2345     start_gpsk_assoc(dev[0], hapd)
2346     resp = rx_msg(dev[0])
2347     # Too short EAP-GPSK header (no OP-Code)
2348     # --> EAP-GPSK: Invalid frame
2349     msg = resp[0:4] + "0005" + resp[8:12] + "0005" + "33"
2350     tx_msg(dev[0], hapd, msg)
2351     # Unknown OP-Code
2352     # --> EAP-GPSK: Unexpected opcode=7 in state=0
2353     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "3307"
2354     tx_msg(dev[0], hapd, msg)
2355     # Too short GPSK-2
2356     # --> EAP-GPSK: Too short message for ID_Peer length
2357     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "3302"
2358     tx_msg(dev[0], hapd, msg)
2359     rx_msg(hapd)
2360     stop_gpsk_assoc(dev[0], hapd)
2361 
2362     start_gpsk_assoc(dev[0], hapd)
2363     resp = rx_msg(dev[0])
2364     # Too short GPSK-2
2365     # --> EAP-GPSK: Too short message for ID_Peer
2366     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "33020001"
2367     tx_msg(dev[0], hapd, msg)
2368     rx_msg(hapd)
2369     stop_gpsk_assoc(dev[0], hapd)
2370 
2371     start_gpsk_assoc(dev[0], hapd)
2372     resp = rx_msg(dev[0])
2373     # Too short GPSK-2
2374     # --> EAP-GPSK: Too short message for ID_Server length
2375     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "33020000"
2376     tx_msg(dev[0], hapd, msg)
2377     rx_msg(hapd)
2378     stop_gpsk_assoc(dev[0], hapd)
2379 
2380     start_gpsk_assoc(dev[0], hapd)
2381     resp = rx_msg(dev[0])
2382     # Too short GPSK-2
2383     # --> EAP-GPSK: Too short message for ID_Server
2384     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "330200000001"
2385     tx_msg(dev[0], hapd, msg)
2386     rx_msg(hapd)
2387     stop_gpsk_assoc(dev[0], hapd)
2388 
2389     start_gpsk_assoc(dev[0], hapd)
2390     resp = rx_msg(dev[0])
2391     # ID_Server mismatch
2392     # --> EAP-GPSK: ID_Server in GPSK-1 and GPSK-2 did not match
2393     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "330200000000"
2394     tx_msg(dev[0], hapd, msg)
2395     rx_msg(hapd)
2396     stop_gpsk_assoc(dev[0], hapd)
2397 
2398     start_gpsk_assoc(dev[0], hapd)
2399     resp = rx_msg(dev[0])
2400     # Too short GPSK-2
2401     # --> EAP-GPSK: Too short message for RAND_Peer
2402     msg = resp[0:4] + "0011" + resp[8:12] + "0011" + "330200000007" + binascii.hexlify(b"hostapd").decode()
2403     tx_msg(dev[0], hapd, msg)
2404     rx_msg(hapd)
2405     stop_gpsk_assoc(dev[0], hapd)
2406 
2407     start_gpsk_assoc(dev[0], hapd)
2408     resp = rx_msg(dev[0])
2409     # Too short GPSK-2
2410     # --> EAP-GPSK: Too short message for RAND_Server
2411     msg = resp[0:4] + "0031" + resp[8:12] + "0031" + "330200000007" + binascii.hexlify(b"hostapd").decode() + 32*"00"
2412     tx_msg(dev[0], hapd, msg)
2413     rx_msg(hapd)
2414     stop_gpsk_assoc(dev[0], hapd)
2415 
2416     start_gpsk_assoc(dev[0], hapd)
2417     resp = rx_msg(dev[0])
2418     # RAND_Server mismatch
2419     # --> EAP-GPSK: RAND_Server in GPSK-1 and GPSK-2 did not match
2420     msg = resp[0:4] + "0051" + resp[8:12] + "0051" + "330200000007" + binascii.hexlify(b"hostapd").decode() + 32*"00" + 32*"00"
2421     tx_msg(dev[0], hapd, msg)
2422     rx_msg(hapd)
2423     stop_gpsk_assoc(dev[0], hapd)
2424 
2425     start_gpsk_assoc(dev[0], hapd)
2426     resp = rx_msg(dev[0])
2427     # Too short GPSK-2
2428     # --> EAP-GPSK: Too short message for CSuite_List length
2429     msg = resp[0:4] + "005a" + resp[8:12] + "005a" + resp[16:188]
2430     tx_msg(dev[0], hapd, msg)
2431     rx_msg(hapd)
2432     stop_gpsk_assoc(dev[0], hapd)
2433 
2434     start_gpsk_assoc(dev[0], hapd)
2435     resp = rx_msg(dev[0])
2436     # Too short GPSK-2
2437     # --> EAP-GPSK: Too short message for CSuite_List
2438     msg = resp[0:4] + "005c" + resp[8:12] + "005c" + resp[16:192]
2439     tx_msg(dev[0], hapd, msg)
2440     rx_msg(hapd)
2441     stop_gpsk_assoc(dev[0], hapd)
2442 
2443     start_gpsk_assoc(dev[0], hapd)
2444     resp = rx_msg(dev[0])
2445     # Too short GPSK-2
2446     # --> EAP-GPSK: CSuite_List in GPSK-1 and GPSK-2 did not match
2447     msg = resp[0:4] + "005c" + resp[8:12] + "005c" + resp[16:188] + "0000"
2448     tx_msg(dev[0], hapd, msg)
2449     rx_msg(hapd)
2450     stop_gpsk_assoc(dev[0], hapd)
2451 
2452     start_gpsk_assoc(dev[0], hapd)
2453     resp = rx_msg(dev[0])
2454     # Too short GPSK-2
2455     # --> EAP-GPSK: Too short message for CSuite_Sel
2456     msg = resp[0:4] + "0068" + resp[8:12] + "0068" + resp[16:216]
2457     tx_msg(dev[0], hapd, msg)
2458     rx_msg(hapd)
2459     stop_gpsk_assoc(dev[0], hapd)
2460 
2461     start_gpsk_assoc(dev[0], hapd)
2462     resp = rx_msg(dev[0])
2463     # Unsupported CSuite_Sel
2464     # --> EAP-GPSK: Peer selected unsupported ciphersuite 0:255
2465     msg = resp[0:4] + "006e" + resp[8:12] + "006e" + resp[16:226] + "ff"
2466     tx_msg(dev[0], hapd, msg)
2467     rx_msg(hapd)
2468     stop_gpsk_assoc(dev[0], hapd)
2469 
2470     start_gpsk_assoc(dev[0], hapd)
2471     resp = rx_msg(dev[0])
2472     # Too short GPSK-2
2473     # --> EAP-GPSK: Too short message for PD_Payload_1 length
2474     msg = resp[0:4] + "006e" + resp[8:12] + "006e" + resp[16:228]
2475     tx_msg(dev[0], hapd, msg)
2476     rx_msg(hapd)
2477     stop_gpsk_assoc(dev[0], hapd)
2478 
2479     start_gpsk_assoc(dev[0], hapd)
2480     resp = rx_msg(dev[0])
2481     # Too short GPSK-2
2482     # --> EAP-GPSK: Too short message for PD_Payload_1
2483     msg = resp[0:4] + "0070" + resp[8:12] + "0070" + resp[16:230] + "ff"
2484     tx_msg(dev[0], hapd, msg)
2485     rx_msg(hapd)
2486     stop_gpsk_assoc(dev[0], hapd)
2487 
2488     start_gpsk_assoc(dev[0], hapd)
2489     resp = rx_msg(dev[0])
2490     # Too short GPSK-2
2491     # --> EAP-GPSK: Message too short for MIC (left=0 miclen=16)
2492     msg = resp[0:4] + "0070" + resp[8:12] + "0070" + resp[16:232]
2493     tx_msg(dev[0], hapd, msg)
2494     rx_msg(hapd)
2495     stop_gpsk_assoc(dev[0], hapd)
2496 
2497     start_gpsk_assoc(dev[0], hapd)
2498     resp = rx_msg(dev[0])
2499     # Extra data in the end of GPSK-2
2500     # --> EAP-GPSK: Ignored 1 bytes of extra data in the end of GPSK-2
2501     msg = resp[0:4] + "0081" + resp[8:12] + "0081" + resp[16:264] + "00"
2502     tx_msg(dev[0], hapd, msg)
2503     proxy_msg(hapd, dev[0]) # GPSK-3
2504     resp = rx_msg(dev[0])
2505     # Too short GPSK-4
2506     # --> EAP-GPSK: Too short message for PD_Payload_1 length
2507     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "3304"
2508     tx_msg(dev[0], hapd, msg)
2509     rx_msg(hapd) # EAP-Failure
2510     stop_gpsk_assoc(dev[0], hapd)
2511 
2512     start_gpsk_assoc(dev[0], hapd)
2513     proxy_msg(dev[0], hapd) # GPSK-2
2514     proxy_msg(hapd, dev[0]) # GPSK-3
2515     resp = rx_msg(dev[0])
2516     # Too short GPSK-4
2517     # --> EAP-GPSK: Too short message for PD_Payload_1
2518     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "33040001"
2519     tx_msg(dev[0], hapd, msg)
2520     rx_msg(hapd) # EAP-Failure
2521     stop_gpsk_assoc(dev[0], hapd)
2522 
2523     start_gpsk_assoc(dev[0], hapd)
2524     proxy_msg(dev[0], hapd) # GPSK-2
2525     proxy_msg(hapd, dev[0]) # GPSK-3
2526     resp = rx_msg(dev[0])
2527     # Too short GPSK-4
2528     # --> EAP-GPSK: Message too short for MIC (left=0 miclen=16)
2529     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "33040000"
2530     tx_msg(dev[0], hapd, msg)
2531     rx_msg(hapd) # EAP-Failure
2532     stop_gpsk_assoc(dev[0], hapd)
2533 
2534     start_gpsk_assoc(dev[0], hapd)
2535     proxy_msg(dev[0], hapd) # GPSK-2
2536     proxy_msg(hapd, dev[0]) # GPSK-3
2537     resp = rx_msg(dev[0])
2538     # Incorrect MIC in GPSK-4
2539     # --> EAP-GPSK: Incorrect MIC in GPSK-4
2540     msg = resp[0:4] + "0018" + resp[8:12] + "0018" + "33040000" + 16*"00"
2541     tx_msg(dev[0], hapd, msg)
2542     rx_msg(hapd) # EAP-Failure
2543     stop_gpsk_assoc(dev[0], hapd)
2544 
2545     start_gpsk_assoc(dev[0], hapd)
2546     proxy_msg(dev[0], hapd) # GPSK-2
2547     proxy_msg(hapd, dev[0]) # GPSK-3
2548     resp = rx_msg(dev[0])
2549     # Incorrect MIC in GPSK-4
2550     # --> EAP-GPSK: Ignored 1 bytes of extra data in the end of GPSK-4
2551     msg = resp[0:4] + "0019" + resp[8:12] + "0019" + resp[16:] + "00"
2552     tx_msg(dev[0], hapd, msg)
2553     rx_msg(hapd) # EAP-Success
2554     stop_gpsk_assoc(dev[0], hapd)
2555 
2556 EAP_EKE_ID = 1
2557 EAP_EKE_COMMIT = 2
2558 EAP_EKE_CONFIRM = 3
2559 EAP_EKE_FAILURE = 4
2560 
2561 def test_eap_proto_eke(dev, apdev):
2562     """EAP-EKE protocol tests"""
2563     def eke_handler(ctx, req):
2564         logger.info("eke_handler - RX " + binascii.hexlify(req).decode())
2565         if 'num' not in ctx:
2566             ctx['num'] = 0
2567         ctx['num'] = ctx['num'] + 1
2568         if 'id' not in ctx:
2569             ctx['id'] = 1
2570         ctx['id'] = (ctx['id'] + 1) % 256
2571 
2572         idx = 0
2573 
2574         idx += 1
2575         if ctx['num'] == idx:
2576             logger.info("Test: Missing payload")
2577             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
2578                                4 + 1,
2579                                EAP_TYPE_EKE)
2580 
2581         idx += 1
2582         if ctx['num'] == idx:
2583             logger.info("Test: Unknown exchange")
2584             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2585                                4 + 1 + 1,
2586                                EAP_TYPE_EKE,
2587                                255)
2588 
2589         idx += 1
2590         if ctx['num'] == idx:
2591             logger.info("Test: No NumProposals in EAP-EKE-ID/Request")
2592             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
2593                                4 + 1 + 1,
2594                                EAP_TYPE_EKE,
2595                                EAP_EKE_ID)
2596         idx += 1
2597         if ctx['num'] == idx:
2598             logger.info("Test: EAP-Failure")
2599             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2600 
2601         idx += 1
2602         if ctx['num'] == idx:
2603             logger.info("Test: NumProposals=0 in EAP-EKE-ID/Request")
2604             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
2605                                4 + 1 + 1 + 1,
2606                                EAP_TYPE_EKE,
2607                                EAP_EKE_ID,
2608                                0)
2609         idx += 1
2610         if ctx['num'] == idx:
2611             logger.info("Test: EAP-Failure")
2612             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2613 
2614         idx += 1
2615         if ctx['num'] == idx:
2616             logger.info("Test: Truncated Proposals list in EAP-EKE-ID/Request")
2617             return struct.pack(">BBHBBBB4B", EAP_CODE_REQUEST, ctx['id'],
2618                                4 + 1 + 1 + 2 + 4,
2619                                EAP_TYPE_EKE,
2620                                EAP_EKE_ID,
2621                                2, 0, 0, 0, 0, 0)
2622         idx += 1
2623         if ctx['num'] == idx:
2624             logger.info("Test: EAP-Failure")
2625             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2626 
2627         idx += 1
2628         if ctx['num'] == idx:
2629             logger.info("Test: Unsupported proposals in EAP-EKE-ID/Request")
2630             return struct.pack(">BBHBBBB4B4B4B4B", EAP_CODE_REQUEST, ctx['id'],
2631                                4 + 1 + 1 + 2 + 4 * 4,
2632                                EAP_TYPE_EKE,
2633                                EAP_EKE_ID,
2634                                4, 0,
2635                                0, 0, 0, 0,
2636                                3, 0, 0, 0,
2637                                3, 1, 0, 0,
2638                                3, 1, 1, 0)
2639         idx += 1
2640         if ctx['num'] == idx:
2641             logger.info("Test: EAP-Failure")
2642             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2643 
2644         idx += 1
2645         if ctx['num'] == idx:
2646             logger.info("Test: Missing IDType/Identity in EAP-EKE-ID/Request")
2647             return struct.pack(">BBHBBBB4B4B4B4B4B",
2648                                EAP_CODE_REQUEST, ctx['id'],
2649                                4 + 1 + 1 + 2 + 5 * 4,
2650                                EAP_TYPE_EKE,
2651                                EAP_EKE_ID,
2652                                5, 0,
2653                                0, 0, 0, 0,
2654                                3, 0, 0, 0,
2655                                3, 1, 0, 0,
2656                                3, 1, 1, 0,
2657                                3, 1, 1, 1)
2658         idx += 1
2659         if ctx['num'] == idx:
2660             logger.info("Test: EAP-Failure")
2661             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2662 
2663         idx += 1
2664         if ctx['num'] == idx:
2665             logger.info("Test: Valid EAP-EKE-ID/Request")
2666             return struct.pack(">BBHBBBB4BB",
2667                                EAP_CODE_REQUEST, ctx['id'],
2668                                4 + 1 + 1 + 2 + 4 + 1,
2669                                EAP_TYPE_EKE,
2670                                EAP_EKE_ID,
2671                                1, 0,
2672                                3, 1, 1, 1,
2673                                255)
2674         idx += 1
2675         if ctx['num'] == idx:
2676             logger.info("Test: Unexpected EAP-EKE-ID/Request")
2677             return struct.pack(">BBHBBBB4BB",
2678                                EAP_CODE_REQUEST, ctx['id'],
2679                                4 + 1 + 1 + 2 + 4 + 1,
2680                                EAP_TYPE_EKE,
2681                                EAP_EKE_ID,
2682                                1, 0,
2683                                3, 1, 1, 1,
2684                                255)
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: Valid EAP-EKE-ID/Request")
2693             return struct.pack(">BBHBBBB4BB",
2694                                EAP_CODE_REQUEST, ctx['id'],
2695                                4 + 1 + 1 + 2 + 4 + 1,
2696                                EAP_TYPE_EKE,
2697                                EAP_EKE_ID,
2698                                1, 0,
2699                                3, 1, 1, 1,
2700                                255)
2701         idx += 1
2702         if ctx['num'] == idx:
2703             logger.info("Test: Unexpected EAP-EKE-Confirm/Request")
2704             return struct.pack(">BBHBB",
2705                                EAP_CODE_REQUEST, ctx['id'],
2706                                4 + 1 + 1,
2707                                EAP_TYPE_EKE,
2708                                EAP_EKE_CONFIRM)
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: Too short EAP-EKE-Failure/Request")
2717             return struct.pack(">BBHBB",
2718                                EAP_CODE_REQUEST, ctx['id'],
2719                                4 + 1 + 1,
2720                                EAP_TYPE_EKE,
2721                                EAP_EKE_FAILURE)
2722         idx += 1
2723         if ctx['num'] == idx:
2724             logger.info("Test: EAP-Failure")
2725             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2726 
2727         idx += 1
2728         if ctx['num'] == idx:
2729             logger.info("Test: Unexpected EAP-EKE-Commit/Request")
2730             return struct.pack(">BBHBB",
2731                                EAP_CODE_REQUEST, ctx['id'],
2732                                4 + 1 + 1,
2733                                EAP_TYPE_EKE,
2734                                EAP_EKE_COMMIT)
2735         idx += 1
2736         if ctx['num'] == idx:
2737             logger.info("Test: EAP-Failure")
2738             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2739 
2740         idx += 1
2741         if ctx['num'] == idx:
2742             logger.info("Test: Valid EAP-EKE-ID/Request")
2743             return struct.pack(">BBHBBBB4BB",
2744                                EAP_CODE_REQUEST, ctx['id'],
2745                                4 + 1 + 1 + 2 + 4 + 1,
2746                                EAP_TYPE_EKE,
2747                                EAP_EKE_ID,
2748                                1, 0,
2749                                3, 1, 1, 1,
2750                                255)
2751         idx += 1
2752         if ctx['num'] == idx:
2753             logger.info("Test: Too short EAP-EKE-Commit/Request")
2754             return struct.pack(">BBHBB",
2755                                EAP_CODE_REQUEST, ctx['id'],
2756                                4 + 1 + 1,
2757                                EAP_TYPE_EKE,
2758                                EAP_EKE_COMMIT)
2759         idx += 1
2760         if ctx['num'] == idx:
2761             logger.info("Test: EAP-Failure")
2762             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2763 
2764         idx += 1
2765         if ctx['num'] == idx:
2766             logger.info("Test: Valid EAP-EKE-ID/Request")
2767             return struct.pack(">BBHBBBB4BB",
2768                                EAP_CODE_REQUEST, ctx['id'],
2769                                4 + 1 + 1 + 2 + 4 + 1,
2770                                EAP_TYPE_EKE,
2771                                EAP_EKE_ID,
2772                                1, 0,
2773                                1, 1, 1, 1,
2774                                255)
2775         idx += 1
2776         if ctx['num'] == idx:
2777             logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
2778             return struct.pack(">BBHBB4L32L",
2779                                EAP_CODE_REQUEST, ctx['id'],
2780                                4 + 1 + 1 + 16 + 128,
2781                                EAP_TYPE_EKE,
2782                                EAP_EKE_COMMIT,
2783                                0, 0, 0, 0,
2784                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2785                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2786         idx += 1
2787         if ctx['num'] == idx:
2788             logger.info("Test: Too short EAP-EKE-Confirm/Request")
2789             return struct.pack(">BBHBB",
2790                                EAP_CODE_REQUEST, ctx['id'],
2791                                4 + 1 + 1,
2792                                EAP_TYPE_EKE,
2793                                EAP_EKE_CONFIRM)
2794         idx += 1
2795         if ctx['num'] == idx:
2796             logger.info("Test: EAP-Failure")
2797             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2798 
2799         idx += 1
2800         if ctx['num'] == idx:
2801             logger.info("Test: Valid EAP-EKE-ID/Request")
2802             return struct.pack(">BBHBBBB4BB",
2803                                EAP_CODE_REQUEST, ctx['id'],
2804                                4 + 1 + 1 + 2 + 4 + 1,
2805                                EAP_TYPE_EKE,
2806                                EAP_EKE_ID,
2807                                1, 0,
2808                                1, 1, 1, 1,
2809                                255)
2810         idx += 1
2811         if ctx['num'] == idx:
2812             logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
2813             return struct.pack(">BBHBB4L32L",
2814                                EAP_CODE_REQUEST, ctx['id'],
2815                                4 + 1 + 1 + 16 + 128,
2816                                EAP_TYPE_EKE,
2817                                EAP_EKE_COMMIT,
2818                                0, 0, 0, 0,
2819                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2820                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
2821         idx += 1
2822         if ctx['num'] == idx:
2823             logger.info("Test: Invalid PNonce_PS and Auth_S values in EAP-EKE-Confirm/Request")
2824             return struct.pack(">BBHBB4L8L5L5L",
2825                                EAP_CODE_REQUEST, ctx['id'],
2826                                4 + 1 + 1 + 16 + 2 * 16 + 20 + 20,
2827                                EAP_TYPE_EKE,
2828                                EAP_EKE_CONFIRM,
2829                                0, 0, 0, 0,
2830                                0, 0, 0, 0, 0, 0, 0, 0,
2831                                0, 0, 0, 0, 0,
2832                                0, 0, 0, 0, 0)
2833         idx += 1
2834         if ctx['num'] == idx:
2835             logger.info("Test: EAP-Failure")
2836             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
2837 
2838         return None
2839 
2840     srv = start_radius_server(eke_handler)
2841 
2842     try:
2843         hapd = start_ap(apdev[0])
2844         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
2845 
2846         for i in range(0, 14):
2847             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2848                            eap="EKE", identity="user", password="password",
2849                            wait_connect=False)
2850             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
2851                                    timeout=15)
2852             if ev is None:
2853                 raise Exception("Timeout on EAP start")
2854             if i in [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]:
2855                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
2856                                        timeout=10)
2857                 if ev is None:
2858                     raise Exception("Timeout on EAP failure")
2859             else:
2860                 time.sleep(0.05)
2861             dev[0].request("REMOVE_NETWORK all")
2862             dev[0].dump_monitor()
2863     finally:
2864         stop_radius_server(srv)
2865 
2866 def eap_eke_test_fail(dev, phase1=None, success=False):
2867     dev.connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2868                 eap="EKE", identity="eke user@domain", password="hello",
2869                 phase1=phase1, erp="1", wait_connect=False)
2870     ev = dev.wait_event(["CTRL-EVENT-EAP-FAILURE",
2871                          "CTRL-EVENT-EAP-SUCCESS"], timeout=5)
2872     if ev is None:
2873         raise Exception("Timeout on EAP failure")
2874     if not success and "CTRL-EVENT-EAP-FAILURE" not in ev:
2875         raise Exception("EAP did not fail during failure test")
2876     dev.request("REMOVE_NETWORK all")
2877     dev.wait_disconnected()
2878 
2879 def test_eap_proto_eke_errors(dev, apdev):
2880     """EAP-EKE local error cases"""
2881     check_eap_capa(dev[0], "EKE")
2882     params = hostapd.wpa2_eap_params(ssid="eap-test")
2883     hapd = hostapd.add_ap(apdev[0], params)
2884     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
2885 
2886     for i in range(1, 3):
2887         with alloc_fail(dev[0], i, "eap_eke_init"):
2888             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
2889                            eap="EKE", identity="eke user", password="hello",
2890                            wait_connect=False)
2891             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
2892                                    timeout=15)
2893             if ev is None:
2894                 raise Exception("Timeout on EAP start")
2895             dev[0].request("REMOVE_NETWORK all")
2896             dev[0].wait_disconnected()
2897 
2898     tests = [(1, "eap_eke_dh_init", None),
2899              (1, "eap_eke_prf_hmac_sha1", "dhgroup=3 encr=1 prf=1 mac=1"),
2900              (1, "eap_eke_prf_hmac_sha256", "dhgroup=5 encr=1 prf=2 mac=2"),
2901              (1, "eap_eke_prf_*", None),
2902              (1, "os_get_random;eap_eke_dhcomp", None),
2903              (1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
2904              (1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
2905              (1, "hmac_sha256_vector;eap_eke_shared_secret", None),
2906              (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ke_ki", None),
2907              (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ka", None),
2908              (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_msk", None),
2909              (1, "os_get_random;eap_eke_prot", None),
2910              (1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
2911              (1, "eap_eke_derive_key;eap_eke_process_commit", None),
2912              (1, "eap_eke_dh_init;eap_eke_process_commit", None),
2913              (1, "eap_eke_shared_secret;eap_eke_process_commit", None),
2914              (1, "eap_eke_derive_ke_ki;eap_eke_process_commit", None),
2915              (1, "eap_eke_dhcomp;eap_eke_process_commit", None),
2916              (1, "os_get_random;eap_eke_process_commit", None),
2917              (1, "os_get_random;=eap_eke_process_commit", None),
2918              (1, "eap_eke_prot;eap_eke_process_commit", None),
2919              (1, "eap_eke_decrypt_prot;eap_eke_process_confirm", None),
2920              (1, "eap_eke_derive_ka;eap_eke_process_confirm", None),
2921              (1, "eap_eke_auth;eap_eke_process_confirm", None),
2922              (2, "eap_eke_auth;eap_eke_process_confirm", None),
2923              (1, "eap_eke_prot;eap_eke_process_confirm", None),
2924              (1, "aes_128_cbc_encrypt;eap_eke_prot;eap_eke_process_confirm", None),
2925              (1, "hmac_sha256;eap_eke_prot;eap_eke_process_confirm", None),
2926              (1, "eap_eke_derive_msk;eap_eke_process_confirm", None)]
2927     for count, func, phase1 in tests:
2928         with fail_test(dev[0], count, func):
2929             eap_eke_test_fail(dev[0], phase1)
2930 
2931     tests = [(1, "=eap_eke_derive_ke_ki", None),
2932              (1, "=eap_eke_derive_ka", None),
2933              (1, "=eap_eke_derive_msk", None),
2934              (1, "eap_eke_build_msg;eap_eke_process_id", None),
2935              (1, "wpabuf_alloc;eap_eke_process_id", None),
2936              (1, "=eap_eke_process_id", None),
2937              (1, "wpabuf_alloc;=eap_eke_process_id", None),
2938              (1, "wpabuf_alloc;eap_eke_process_id", None),
2939              (1, "eap_eke_build_msg;eap_eke_process_commit", None),
2940              (1, "wpabuf_resize;eap_eke_process_commit", None),
2941              (1, "eap_eke_build_msg;eap_eke_process_confirm", None)]
2942     for count, func, phase1 in tests:
2943         with alloc_fail(dev[0], count, func):
2944             eap_eke_test_fail(dev[0], phase1)
2945 
2946     tests = [(1, "eap_eke_getKey", None),
2947              (1, "eap_eke_get_emsk", None),
2948              (1, "eap_eke_get_session_id", None)]
2949     for count, func, phase1 in tests:
2950         with alloc_fail(dev[0], count, func):
2951             eap_eke_test_fail(dev[0], phase1, success=True)
2952 
2953 EAP_PAX_OP_STD_1 = 0x01
2954 EAP_PAX_OP_STD_2 = 0x02
2955 EAP_PAX_OP_STD_3 = 0x03
2956 EAP_PAX_OP_SEC_1 = 0x11
2957 EAP_PAX_OP_SEC_2 = 0x12
2958 EAP_PAX_OP_SEC_3 = 0x13
2959 EAP_PAX_OP_SEC_4 = 0x14
2960 EAP_PAX_OP_SEC_5 = 0x15
2961 EAP_PAX_OP_ACK = 0x21
2962 
2963 EAP_PAX_FLAGS_MF = 0x01
2964 EAP_PAX_FLAGS_CE = 0x02
2965 EAP_PAX_FLAGS_AI = 0x04
2966 
2967 EAP_PAX_MAC_HMAC_SHA1_128 = 0x01
2968 EAP_PAX_HMAC_SHA256_128 = 0x02
2969 
2970 EAP_PAX_DH_GROUP_NONE = 0x00
2971 EAP_PAX_DH_GROUP_2048_MODP = 0x01
2972 EAP_PAX_DH_GROUP_3072_MODP = 0x02
2973 EAP_PAX_DH_GROUP_NIST_ECC_P_256 = 0x03
2974 
2975 EAP_PAX_PUBLIC_KEY_NONE = 0x00
2976 EAP_PAX_PUBLIC_KEY_RSAES_OAEP = 0x01
2977 EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 = 0x02
2978 EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC = 0x03
2979 
2980 EAP_PAX_ADE_VENDOR_SPECIFIC = 0x01
2981 EAP_PAX_ADE_CLIENT_CHANNEL_BINDING = 0x02
2982 EAP_PAX_ADE_SERVER_CHANNEL_BINDING = 0x03
2983 
2984 def test_eap_proto_pax(dev, apdev):
2985     """EAP-PAX protocol tests"""
2986     def pax_std_1(ctx):
2987             logger.info("Test: STD-1")
2988             ctx['id'] = 10
2989             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
2990                                4 + 1 + 5 + 2 + 32 + 16,
2991                                EAP_TYPE_PAX,
2992                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
2993                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
2994                                32, 0, 0, 0, 0, 0, 0, 0, 0,
2995                                0x16, 0xc9, 0x08, 0x9d, 0x98, 0xa5, 0x6e, 0x1f,
2996                                0xf0, 0xac, 0xcf, 0xc4, 0x66, 0xcd, 0x2d, 0xbf)
2997 
2998     def pax_handler(ctx, req):
2999         logger.info("pax_handler - RX " + binascii.hexlify(req).decode())
3000         if 'num' not in ctx:
3001             ctx['num'] = 0
3002         ctx['num'] = ctx['num'] + 1
3003         if 'id' not in ctx:
3004             ctx['id'] = 1
3005         ctx['id'] = (ctx['id'] + 1) % 256
3006 
3007         idx = 0
3008 
3009         idx += 1
3010         if ctx['num'] == idx:
3011             logger.info("Test: Missing payload")
3012             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3013                                4 + 1,
3014                                EAP_TYPE_PAX)
3015 
3016         idx += 1
3017         if ctx['num'] == idx:
3018             logger.info("Test: Minimum length payload")
3019             return struct.pack(">BBHB4L", EAP_CODE_REQUEST, ctx['id'],
3020                                4 + 1 + 16,
3021                                EAP_TYPE_PAX,
3022                                0, 0, 0, 0)
3023 
3024         idx += 1
3025         if ctx['num'] == idx:
3026             logger.info("Test: Unsupported MAC ID")
3027             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
3028                                4 + 1 + 5 + 16,
3029                                EAP_TYPE_PAX,
3030                                EAP_PAX_OP_STD_1, 0, 255, EAP_PAX_DH_GROUP_NONE,
3031                                EAP_PAX_PUBLIC_KEY_NONE,
3032                                0, 0, 0, 0)
3033 
3034         idx += 1
3035         if ctx['num'] == idx:
3036             logger.info("Test: Unsupported DH Group ID")
3037             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
3038                                4 + 1 + 5 + 16,
3039                                EAP_TYPE_PAX,
3040                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3041                                255, EAP_PAX_PUBLIC_KEY_NONE,
3042                                0, 0, 0, 0)
3043 
3044         idx += 1
3045         if ctx['num'] == idx:
3046             logger.info("Test: Unsupported Public Key ID")
3047             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
3048                                4 + 1 + 5 + 16,
3049                                EAP_TYPE_PAX,
3050                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3051                                EAP_PAX_DH_GROUP_NONE, 255,
3052                                0, 0, 0, 0)
3053 
3054         idx += 1
3055         if ctx['num'] == idx:
3056             logger.info("Test: More fragments")
3057             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
3058                                4 + 1 + 5 + 16,
3059                                EAP_TYPE_PAX,
3060                                EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_MF,
3061                                EAP_PAX_MAC_HMAC_SHA1_128,
3062                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3063                                0, 0, 0, 0)
3064 
3065         idx += 1
3066         if ctx['num'] == idx:
3067             logger.info("Test: Invalid ICV")
3068             return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
3069                                4 + 1 + 5 + 16,
3070                                EAP_TYPE_PAX,
3071                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3072                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3073                                0, 0, 0, 0)
3074 
3075         idx += 1
3076         if ctx['num'] == idx:
3077             logger.info("Test: Invalid ICV in short frame")
3078             return struct.pack(">BBHBBBBBB3L", EAP_CODE_REQUEST, ctx['id'],
3079                                4 + 1 + 5 + 12,
3080                                EAP_TYPE_PAX,
3081                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3082                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3083                                0, 0, 0)
3084 
3085         idx += 1
3086         if ctx['num'] == idx:
3087             logger.info("Test: Correct ICV - unsupported op_code")
3088             ctx['id'] = 10
3089             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
3090                                4 + 1 + 5 + 16,
3091                                EAP_TYPE_PAX,
3092                                255, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3093                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3094                                0x90, 0x78, 0x97, 0x38, 0x29, 0x94, 0x32, 0xd4,
3095                                0x81, 0x27, 0xe0, 0xf6, 0x3b, 0x0d, 0xb2, 0xb2)
3096 
3097         idx += 1
3098         if ctx['num'] == idx:
3099             logger.info("Test: Correct ICV - CE flag in STD-1")
3100             ctx['id'] = 10
3101             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
3102                                4 + 1 + 5 + 16,
3103                                EAP_TYPE_PAX,
3104                                EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_CE,
3105                                EAP_PAX_MAC_HMAC_SHA1_128,
3106                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3107                                0x9c, 0x98, 0xb4, 0x0b, 0x94, 0x90, 0xde, 0x88,
3108                                0xb7, 0x72, 0x63, 0x44, 0x1d, 0xe3, 0x7c, 0x5c)
3109 
3110         idx += 1
3111         if ctx['num'] == idx:
3112             logger.info("Test: Correct ICV - too short STD-1 payload")
3113             ctx['id'] = 10
3114             return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
3115                                4 + 1 + 5 + 16,
3116                                EAP_TYPE_PAX,
3117                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3118                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3119                                0xda, 0xab, 0x2c, 0xe7, 0x84, 0x41, 0xb5, 0x5c,
3120                                0xee, 0xcf, 0x62, 0x03, 0xc5, 0x69, 0xcb, 0xf4)
3121 
3122         idx += 1
3123         if ctx['num'] == idx:
3124             logger.info("Test: Correct ICV - incorrect A length in STD-1")
3125             ctx['id'] = 10
3126             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3127                                4 + 1 + 5 + 2 + 32 + 16,
3128                                EAP_TYPE_PAX,
3129                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3130                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3131                                0, 0, 0, 0, 0, 0, 0, 0, 0,
3132                                0xc4, 0xb0, 0x81, 0xe4, 0x6c, 0x8c, 0x20, 0x23,
3133                                0x60, 0x46, 0x89, 0xea, 0x94, 0x60, 0xf3, 0x2a)
3134 
3135         idx += 1
3136         if ctx['num'] == idx:
3137             logger.info("Test: Correct ICV - extra data in STD-1")
3138             ctx['id'] = 10
3139             return struct.pack(">BBHBBBBBBH8LB16B", EAP_CODE_REQUEST, ctx['id'],
3140                                4 + 1 + 5 + 2 + 32 + 1 + 16,
3141                                EAP_TYPE_PAX,
3142                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3143                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3144                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3145                                1,
3146                                0x61, 0x49, 0x65, 0x37, 0x21, 0xe8, 0xd8, 0xbf,
3147                                0xf3, 0x02, 0x01, 0xe5, 0x42, 0x51, 0xd3, 0x34)
3148         idx += 1
3149         if ctx['num'] == idx:
3150             logger.info("Test: Unexpected STD-1")
3151             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3152                                4 + 1 + 5 + 2 + 32 + 16,
3153                                EAP_TYPE_PAX,
3154                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3155                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3156                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3157                                0xe5, 0x1d, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
3158                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
3159 
3160         idx += 1
3161         if ctx['num'] == idx:
3162             return pax_std_1(ctx)
3163         idx += 1
3164         if ctx['num'] == idx:
3165             logger.info("Test: MAC ID changed during session")
3166             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3167                                4 + 1 + 5 + 2 + 32 + 16,
3168                                EAP_TYPE_PAX,
3169                                EAP_PAX_OP_STD_1, 0, EAP_PAX_HMAC_SHA256_128,
3170                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3171                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3172                                0xee, 0x00, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
3173                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
3174 
3175         idx += 1
3176         if ctx['num'] == idx:
3177             return pax_std_1(ctx)
3178         idx += 1
3179         if ctx['num'] == idx:
3180             logger.info("Test: DH Group ID changed during session")
3181             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3182                                4 + 1 + 5 + 2 + 32 + 16,
3183                                EAP_TYPE_PAX,
3184                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3185                                EAP_PAX_DH_GROUP_2048_MODP,
3186                                EAP_PAX_PUBLIC_KEY_NONE,
3187                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3188                                0xee, 0x01, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
3189                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
3190 
3191         idx += 1
3192         if ctx['num'] == idx:
3193             return pax_std_1(ctx)
3194         idx += 1
3195         if ctx['num'] == idx:
3196             logger.info("Test: Public Key ID changed during session")
3197             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3198                                4 + 1 + 5 + 2 + 32 + 16,
3199                                EAP_TYPE_PAX,
3200                                EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3201                                EAP_PAX_DH_GROUP_NONE,
3202                                EAP_PAX_PUBLIC_KEY_RSAES_OAEP,
3203                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3204                                0xee, 0x02, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
3205                                0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
3206 
3207         idx += 1
3208         if ctx['num'] == idx:
3209             logger.info("Test: Unexpected STD-3")
3210             ctx['id'] = 10
3211             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3212                                4 + 1 + 5 + 2 + 32 + 16,
3213                                EAP_TYPE_PAX,
3214                                EAP_PAX_OP_STD_3, 0, EAP_PAX_MAC_HMAC_SHA1_128,
3215                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3216                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3217                                0x47, 0xbb, 0xc0, 0xf9, 0xb9, 0x69, 0xf5, 0xcb,
3218                                0x3a, 0xe8, 0xe7, 0xd6, 0x80, 0x28, 0xf2, 0x59)
3219 
3220         idx += 1
3221         if ctx['num'] == idx:
3222             return pax_std_1(ctx)
3223         idx += 1
3224         if ctx['num'] == idx:
3225             # TODO: MAC calculation; for now, this gets dropped due to incorrect
3226             # ICV
3227             logger.info("Test: STD-3 with CE flag")
3228             return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
3229                                4 + 1 + 5 + 2 + 32 + 16,
3230                                EAP_TYPE_PAX,
3231                                EAP_PAX_OP_STD_3, EAP_PAX_FLAGS_CE,
3232                                EAP_PAX_MAC_HMAC_SHA1_128,
3233                                EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
3234                                32, 0, 0, 0, 0, 0, 0, 0, 0,
3235                                0x8a, 0xc2, 0xf9, 0xf4, 0x8b, 0x75, 0x72, 0xa2,
3236                                0x4d, 0xd3, 0x1e, 0x54, 0x77, 0x04, 0x05, 0xe2)
3237 
3238         idx += 1
3239         if ctx['num'] & 0x1 == idx & 0x1:
3240             logger.info("Test: Default request")
3241             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3242                                4 + 1,
3243                                EAP_TYPE_PAX)
3244         else:
3245             logger.info("Test: Default EAP-Failure")
3246             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3247 
3248     srv = start_radius_server(pax_handler)
3249 
3250     try:
3251         hapd = start_ap(apdev[0])
3252         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3253 
3254         for i in range(0, 18):
3255             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3256                            eap="PAX", identity="user",
3257                            password_hex="0123456789abcdef0123456789abcdef",
3258                            wait_connect=False)
3259             logger.info("Waiting for EAP method to start")
3260             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3261                                    timeout=15)
3262             if ev is None:
3263                 raise Exception("Timeout on EAP start")
3264             time.sleep(0.05)
3265             dev[0].request("REMOVE_NETWORK all")
3266             dev[0].dump_monitor()
3267 
3268         logger.info("Too short password")
3269         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3270                        eap="PAX", identity="user",
3271                        password_hex="0123456789abcdef0123456789abcd",
3272                        wait_connect=False)
3273         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
3274         if ev is None:
3275             raise Exception("Timeout on EAP start")
3276         time.sleep(0.1)
3277         dev[0].request("REMOVE_NETWORK all")
3278         dev[0].dump_monitor()
3279 
3280         logger.info("No password")
3281         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3282                        eap="PAX", identity="user",
3283                        wait_connect=False)
3284         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
3285         if ev is None:
3286             raise Exception("Timeout on EAP start")
3287         time.sleep(0.1)
3288         dev[0].request("REMOVE_NETWORK all")
3289         dev[0].dump_monitor()
3290     finally:
3291         stop_radius_server(srv)
3292 
3293 def test_eap_proto_pax_errors(dev, apdev):
3294     """EAP-PAX local error cases"""
3295     check_eap_capa(dev[0], "PAX")
3296     params = hostapd.wpa2_eap_params(ssid="eap-test")
3297     hapd = hostapd.add_ap(apdev[0], params)
3298     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3299 
3300     for i in range(1, 3):
3301         with alloc_fail(dev[0], i, "eap_pax_init"):
3302             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3303                            eap="PAX", identity="pax.user@example.com",
3304                            password_hex="0123456789abcdef0123456789abcdef",
3305                            wait_connect=False)
3306             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
3307                                    timeout=15)
3308             if ev is None:
3309                 raise Exception("Timeout on EAP start")
3310             dev[0].request("REMOVE_NETWORK all")
3311             dev[0].wait_disconnected()
3312 
3313     tests = ["eap_msg_alloc;eap_pax_alloc_resp;eap_pax_process_std_1",
3314              "eap_msg_alloc;eap_pax_alloc_resp;eap_pax_process_std_3",
3315              "eap_pax_getKey",
3316              "eap_pax_get_emsk",
3317              "eap_pax_get_session_id"]
3318     for func in tests:
3319         with alloc_fail(dev[0], 1, func):
3320             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3321                            eap="PAX", identity="pax.user@example.com",
3322                            password_hex="0123456789abcdef0123456789abcdef",
3323                            erp="1", wait_connect=False)
3324             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
3325             dev[0].request("REMOVE_NETWORK all")
3326             dev[0].wait_disconnected()
3327 
3328     tests = [(1, "os_get_random;eap_pax_process_std_1"),
3329              (1, "eap_pax_initial_key_derivation"),
3330              (1, "eap_pax_mac;eap_pax_process_std_3"),
3331              (2, "eap_pax_mac;eap_pax_process_std_3"),
3332              (1, "eap_pax_kdf;eap_pax_getKey"),
3333              (1, "eap_pax_kdf;eap_pax_get_emsk")]
3334     for count, func in tests:
3335         with fail_test(dev[0], count, func):
3336             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3337                            eap="PAX", identity="pax.user@example.com",
3338                            password_hex="0123456789abcdef0123456789abcdef",
3339                            erp="1", wait_connect=False)
3340             wait_fail_trigger(dev[0], "GET_FAIL")
3341             dev[0].request("REMOVE_NETWORK all")
3342             dev[0].wait_disconnected()
3343 
3344 def run_eap_pax_connect(dev):
3345     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
3346                 eap="PAX", identity="pax.user@example.com",
3347                 password_hex="0123456789abcdef0123456789abcdef",
3348                 wait_connect=False)
3349     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
3350                          "CTRL-EVENT-DISCONNECTED"],
3351                         timeout=1)
3352     dev.request("REMOVE_NETWORK all")
3353     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
3354         dev.wait_disconnected()
3355     dev.dump_monitor()
3356 
3357 def test_eap_proto_pax_errors_server(dev, apdev):
3358     """EAP-PAX local error cases on server"""
3359     check_eap_capa(dev[0], "PAX")
3360     params = int_eap_server_params()
3361     params['erp_domain'] = 'example.com'
3362     params['eap_server_erp'] = '1'
3363     hapd = hostapd.add_ap(apdev[0], params)
3364     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3365 
3366     tests = [(1, "eap_pax_init"),
3367              (1, "eap_msg_alloc;eap_pax_build_std_1"),
3368              (1, "eap_msg_alloc;eap_pax_build_std_3"),
3369              (1, "=eap_pax_process_std_2"),
3370              (1, "eap_pax_getKey"),
3371              (1, "eap_pax_get_emsk"),
3372              (1, "eap_pax_get_session_id")]
3373     for count, func in tests:
3374         with alloc_fail(hapd, count, func):
3375             run_eap_pax_connect(dev[0])
3376 
3377     tests = [(1, "os_get_random;eap_pax_build_std_1"),
3378              (1, "eap_pax_mac;eap_pax_build_std_1"),
3379              (1, "eap_pax_mac;eap_pax_build_std_3"),
3380              (2, "eap_pax_mac;=eap_pax_build_std_3"),
3381              (1, "eap_pax_initial_key_derivation;eap_pax_process_std_2"),
3382              (1, "eap_pax_mac;eap_pax_process_std_2"),
3383              (2, "eap_pax_mac;=eap_pax_process_std_2"),
3384              (1, "eap_pax_mac;eap_pax_check")]
3385     for count, func in tests:
3386         with fail_test(hapd, count, func):
3387             run_eap_pax_connect(dev[0])
3388 
3389 def start_pax_assoc(dev, hapd):
3390     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
3391                 eap="PAX", identity="pax.user@example.com",
3392                 password_hex="0123456789abcdef0123456789abcdef",
3393                 wait_connect=False)
3394     proxy_msg(hapd, dev) # EAP-Identity/Request
3395     proxy_msg(dev, hapd) # EAP-Identity/Response
3396     proxy_msg(hapd, dev) # PAX_STD-1
3397 
3398 def stop_pax_assoc(dev, hapd):
3399     dev.request("REMOVE_NETWORK all")
3400     dev.wait_disconnected()
3401     dev.dump_monitor()
3402     hapd.dump_monitor()
3403 
3404 def test_eap_proto_pax_server(dev, apdev):
3405     """EAP-PAX protocol testing for the server"""
3406     check_eap_capa(dev[0], "PAX")
3407     params = int_eap_server_params()
3408     params['erp_domain'] = 'example.com'
3409     params['eap_server_erp'] = '1'
3410     hapd = hostapd.add_ap(apdev[0], params)
3411     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3412     hapd.request("SET ext_eapol_frame_io 1")
3413     dev[0].request("SET ext_eapol_frame_io 1")
3414 
3415     # Successful exchange to verify proxying mechanism
3416     start_pax_assoc(dev[0], hapd)
3417     proxy_msg(dev[0], hapd) # PAX_STD-2
3418     proxy_msg(hapd, dev[0]) # PAX_STD-3
3419     proxy_msg(dev[0], hapd) # PAX-ACK
3420     proxy_msg(hapd, dev[0]) # EAP-Success
3421     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 1/4
3422     proxy_msg(dev[0], hapd) # EAPOL-Key msg 2/4
3423     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 3/4
3424     proxy_msg(dev[0], hapd) # EAPOL-Key msg 4/4
3425     dev[0].wait_connected()
3426     stop_pax_assoc(dev[0], hapd)
3427 
3428     start_pax_assoc(dev[0], hapd)
3429     resp = rx_msg(dev[0])
3430     # Too short EAP-PAX header (no OP-Code)
3431     hapd.note("EAP-PAX: Invalid frame")
3432     msg = resp[0:4] + "0005" + resp[8:12] + "0005" + "2e"
3433     tx_msg(dev[0], hapd, msg)
3434     # Too short EAP-PAX message (no payload)
3435     hapd.note("EAP-PAX: Invalid frame")
3436     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "2e1100000000"
3437     tx_msg(dev[0], hapd, msg)
3438     # Unexpected PAX_SEC-2
3439     hapd.note("EAP-PAX: Expected PAX_STD-2 - ignore op 17")
3440     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e1100000000" + 16*"00"
3441     tx_msg(dev[0], hapd, msg)
3442     # Unexpected MAC ID
3443     hapd.note("EAP-PAX: Expected MAC ID 0x1, received 0xff")
3444     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e0200ff0000" + 16*"00"
3445     tx_msg(dev[0], hapd, msg)
3446     # Unexpected DH Group ID
3447     hapd.note("EAP-PAX: Expected DH Group ID 0x0, received 0xff")
3448     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e020001ff00" + 16*"00"
3449     tx_msg(dev[0], hapd, msg)
3450     # Unexpected Public Key ID
3451     hapd.note("EAP-PAX: Expected Public Key ID 0x0, received 0xff")
3452     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e02000100ff" + 16*"00"
3453     tx_msg(dev[0], hapd, msg)
3454     # Unsupported Flags - MF
3455     hapd.note("EAP-PAX: fragmentation not supported")
3456     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e0201010000" + 16*"00"
3457     tx_msg(dev[0], hapd, msg)
3458     # Unsupported Flags - CE
3459     hapd.note("EAP-PAX: Unexpected CE flag")
3460     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e0202010000" + 16*"00"
3461     tx_msg(dev[0], hapd, msg)
3462     # Too short Payload in PAX_STD-2
3463     hapd.note("EAP-PAX: Too short PAX_STD-2 (B)")
3464     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e0200010000" + 16*"00"
3465     tx_msg(dev[0], hapd, msg)
3466     rx_msg(hapd)
3467     stop_pax_assoc(dev[0], hapd)
3468 
3469     start_pax_assoc(dev[0], hapd)
3470     resp = rx_msg(dev[0])
3471     # Too short Payload in PAX_STD-2
3472     hapd.note("EAP-PAX: Too short PAX_STD-2 (CID)")
3473     msg = resp[0:4] + "002c" + resp[8:12] + "002c" + "2e0200010000" + "0020" + 32*"00"
3474     tx_msg(dev[0], hapd, msg)
3475     rx_msg(hapd)
3476     stop_pax_assoc(dev[0], hapd)
3477 
3478     start_pax_assoc(dev[0], hapd)
3479     resp = rx_msg(dev[0])
3480     # Too short Payload in PAX_STD-2
3481     hapd.note("EAP-PAX: Too short PAX_STD-2 (CID)")
3482     msg = resp[0:4] + "002e" + resp[8:12] + "002e" + "2e0200010000" + "0020" + 32*"00" + "ffff"
3483     tx_msg(dev[0], hapd, msg)
3484     rx_msg(hapd)
3485     stop_pax_assoc(dev[0], hapd)
3486 
3487     start_pax_assoc(dev[0], hapd)
3488     resp = rx_msg(dev[0])
3489     # Too long CID in PAX_STD-2
3490     hapd.note("EAP-PAX: Too long CID")
3491     msg = resp[0:4] + "062e" + resp[8:12] + "062e" + "2e0200010000" + "0020" + 32*"00" + "0600" + 1536*"00"
3492     tx_msg(dev[0], hapd, msg)
3493     rx_msg(hapd)
3494     stop_pax_assoc(dev[0], hapd)
3495 
3496     start_pax_assoc(dev[0], hapd)
3497     resp = rx_msg(dev[0])
3498     # Too short Payload in PAX_STD-2
3499     hapd.note("EAP-PAX: Too short PAX_STD-2 (MAC_CK)")
3500     msg = resp[0:4] + "003c" + resp[8:12] + "003c" + "2e0200010000" + "0020" + 32*"00" + 16*"00"
3501     tx_msg(dev[0], hapd, msg)
3502     rx_msg(hapd)
3503     stop_pax_assoc(dev[0], hapd)
3504 
3505     start_pax_assoc(dev[0], hapd)
3506     resp = rx_msg(dev[0])
3507     # Unknown CID for PAX
3508     hapd.note("EAP-PAX: EAP-PAX not enabled for CID")
3509     msg = resp[0:4] + "0041" + resp[8:12] + "0041" + "2e0200010000" + "0020" + 32*"00" + "0001" + "00" + "0010" + 16*"00"
3510     tx_msg(dev[0], hapd, msg)
3511     rx_msg(hapd)
3512     stop_pax_assoc(dev[0], hapd)
3513 
3514     start_pax_assoc(dev[0], hapd)
3515     resp = rx_msg(dev[0])
3516     # Too short ICV
3517     hapd.note("EAP-PAX: Too short ICV (15) in PAX_STD-2")
3518     msg = resp[0:4] + "0063" + resp[8:12] + "0063" + resp[16:206]
3519     tx_msg(dev[0], hapd, msg)
3520     rx_msg(hapd)
3521     stop_pax_assoc(dev[0], hapd)
3522 
3523     start_pax_assoc(dev[0], hapd)
3524     proxy_msg(dev[0], hapd) # PAX_STD-2
3525     proxy_msg(hapd, dev[0]) # PAX_STD-3
3526     resp = rx_msg(dev[0])
3527     # Unexpected PAX_STD-2
3528     hapd.note("EAP-PAX: Expected PAX-ACK - ignore op 1")
3529     msg = resp[0:4] + "001a" + resp[8:12] + "001a" + "2e0100000000" + 16*"00"
3530     tx_msg(dev[0], hapd, msg)
3531     stop_pax_assoc(dev[0], hapd)
3532 
3533 def test_eap_proto_psk(dev, apdev):
3534     """EAP-PSK protocol tests"""
3535     def psk_handler(ctx, req):
3536         logger.info("psk_handler - RX " + binascii.hexlify(req).decode())
3537         if 'num' not in ctx:
3538             ctx['num'] = 0
3539         ctx['num'] = ctx['num'] + 1
3540         if 'id' not in ctx:
3541             ctx['id'] = 1
3542         ctx['id'] = (ctx['id'] + 1) % 256
3543 
3544         idx = 0
3545 
3546         idx += 1
3547         if ctx['num'] == idx:
3548             logger.info("Test: Missing payload")
3549             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3550                                4 + 1,
3551                                EAP_TYPE_PSK)
3552 
3553         idx += 1
3554         if ctx['num'] == idx:
3555             logger.info("Test: Non-zero T in first message")
3556             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
3557                                4 + 1 + 1 + 16,
3558                                EAP_TYPE_PSK, 0xc0, 0, 0, 0, 0)
3559 
3560         idx += 1
3561         if ctx['num'] == idx:
3562             logger.info("Test: Valid first message")
3563             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
3564                                4 + 1 + 1 + 16,
3565                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
3566         idx += 1
3567         if ctx['num'] == idx:
3568             logger.info("Test: Too short third message")
3569             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3570                                4 + 1,
3571                                EAP_TYPE_PSK)
3572 
3573         idx += 1
3574         if ctx['num'] == idx:
3575             logger.info("Test: Valid first message")
3576             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
3577                                4 + 1 + 1 + 16,
3578                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
3579         idx += 1
3580         if ctx['num'] == idx:
3581             logger.info("Test: Incorrect T in third message")
3582             return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
3583                                4 + 1 + 1 + 16 + 16,
3584                                EAP_TYPE_PSK, 0, 0, 0, 0, 0, 0, 0, 0, 0)
3585 
3586         idx += 1
3587         if ctx['num'] == idx:
3588             logger.info("Test: Valid first message")
3589             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
3590                                4 + 1 + 1 + 16,
3591                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
3592         idx += 1
3593         if ctx['num'] == idx:
3594             logger.info("Test: Missing PCHANNEL in third message")
3595             return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
3596                                4 + 1 + 1 + 16 + 16,
3597                                EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0)
3598 
3599         idx += 1
3600         if ctx['num'] == idx:
3601             logger.info("Test: Valid first message")
3602             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
3603                                4 + 1 + 1 + 16,
3604                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
3605         idx += 1
3606         if ctx['num'] == idx:
3607             logger.info("Test: Invalic MAC_S in third message")
3608             return struct.pack(">BBHBB4L4L5LB", EAP_CODE_REQUEST, ctx['id'],
3609                                4 + 1 + 1 + 16 + 16 + 21,
3610                                EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
3611                                0, 0, 0, 0, 0, 0)
3612 
3613         idx += 1
3614         if ctx['num'] == idx:
3615             logger.info("Test: Valid first message")
3616             return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
3617                                4 + 1 + 1 + 16,
3618                                EAP_TYPE_PSK, 0, 0, 0, 0, 0)
3619         idx += 1
3620         if ctx['num'] == idx:
3621             logger.info("Test: EAP-Failure")
3622             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3623 
3624         return None
3625 
3626     srv = start_radius_server(psk_handler)
3627 
3628     try:
3629         hapd = start_ap(apdev[0])
3630         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3631 
3632         for i in range(0, 6):
3633             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3634                            eap="PSK", identity="user",
3635                            password_hex="0123456789abcdef0123456789abcdef",
3636                            wait_connect=False)
3637             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3638                                    timeout=15)
3639             if ev is None:
3640                 raise Exception("Timeout on EAP start")
3641             time.sleep(0.1)
3642             dev[0].request("REMOVE_NETWORK all")
3643 
3644         logger.info("Test: Invalid PSK length")
3645         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3646                        eap="PSK", identity="user",
3647                        password_hex="0123456789abcdef0123456789abcd",
3648                        wait_connect=False)
3649         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3650                                timeout=15)
3651         if ev is None:
3652             raise Exception("Timeout on EAP start")
3653         time.sleep(0.1)
3654         dev[0].request("REMOVE_NETWORK all")
3655     finally:
3656         stop_radius_server(srv)
3657 
3658 def test_eap_proto_psk_errors(dev, apdev):
3659     """EAP-PSK local error cases"""
3660     check_eap_capa(dev[0], "PSK")
3661     params = hostapd.wpa2_eap_params(ssid="eap-test")
3662     hapd = hostapd.add_ap(apdev[0], params)
3663     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3664 
3665     for i in range(1, 3):
3666         with alloc_fail(dev[0], i, "eap_psk_init"):
3667             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3668                            eap="PSK", identity="psk.user@example.com",
3669                            password_hex="0123456789abcdef0123456789abcdef",
3670                            wait_connect=False)
3671             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
3672                                    timeout=15)
3673             if ev is None:
3674                 raise Exception("Timeout on EAP start")
3675             dev[0].request("REMOVE_NETWORK all")
3676             dev[0].wait_disconnected()
3677 
3678     for i in range(1, 4):
3679         with fail_test(dev[0], i, "eap_psk_key_setup;eap_psk_init"):
3680             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3681                            eap="PSK", identity="psk.user@example.com",
3682                            password_hex="0123456789abcdef0123456789abcdef",
3683                            wait_connect=False)
3684             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
3685                                    timeout=15)
3686             if ev is None:
3687                 raise Exception("Timeout on EAP start")
3688             dev[0].request("REMOVE_NETWORK all")
3689             dev[0].wait_disconnected()
3690 
3691     tests = [(1, "=eap_psk_process_1"),
3692              (2, "=eap_psk_process_1"),
3693              (1, "eap_msg_alloc;eap_psk_process_1"),
3694              (1, "=eap_psk_process_3"),
3695              (2, "=eap_psk_process_3"),
3696              (1, "eap_msg_alloc;eap_psk_process_3"),
3697              (1, "eap_psk_getKey"),
3698              (1, "eap_psk_get_session_id"),
3699              (1, "eap_psk_get_emsk")]
3700     for count, func in tests:
3701         with alloc_fail(dev[0], count, func):
3702             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3703                            eap="PSK", identity="psk.user@example.com",
3704                            password_hex="0123456789abcdef0123456789abcdef",
3705                            erp="1", wait_connect=False)
3706             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3707                                    timeout=15)
3708             if ev is None:
3709                 raise Exception("Timeout on EAP start")
3710             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
3711                               note="No allocation failure seen for %d:%s" % (count, func))
3712             dev[0].request("REMOVE_NETWORK all")
3713             dev[0].wait_disconnected()
3714 
3715     tests = [(1, "os_get_random;eap_psk_process_1"),
3716              (1, "omac1_aes_128;eap_psk_process_3"),
3717              (1, "=omac1_aes_vector;omac1_aes_128;aes_128_eax_encrypt"),
3718              (2, "=omac1_aes_vector;omac1_aes_128;aes_128_eax_encrypt"),
3719              (3, "=omac1_aes_vector;omac1_aes_128;aes_128_eax_encrypt"),
3720              (1, "=omac1_aes_vector;omac1_aes_128;aes_128_eax_decrypt"),
3721              (2, "=omac1_aes_vector;omac1_aes_128;aes_128_eax_decrypt"),
3722              (3, "=omac1_aes_vector;omac1_aes_128;aes_128_eax_decrypt"),
3723              (1, "aes_128_eax_decrypt;eap_psk_process_3"),
3724              (2, "aes_128_eax_decrypt;eap_psk_process_3"),
3725              (3, "aes_128_eax_decrypt;eap_psk_process_3"),
3726              (1, "aes_128_eax_encrypt;eap_psk_process_3"),
3727              (2, "aes_128_eax_encrypt;eap_psk_process_3"),
3728              (3, "aes_128_eax_encrypt;eap_psk_process_3"),
3729              (1, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3730              (2, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3731              (3, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3732              (4, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3733              (5, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3734              (6, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3735              (7, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3736              (8, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3737              (9, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3738              (10, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
3739              (1, "aes_ctr_encrypt;aes_128_eax_decrypt;eap_psk_process_3"),
3740              (1, "aes_ctr_encrypt;aes_128_eax_encrypt;eap_psk_process_3")]
3741     for count, func in tests:
3742         with fail_test(dev[0], count, func):
3743             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
3744                            eap="PSK", identity="psk.user@example.com",
3745                            password_hex="0123456789abcdef0123456789abcdef",
3746                            wait_connect=False)
3747             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
3748                                    timeout=15)
3749             if ev is None:
3750                 raise Exception("Timeout on EAP start")
3751             wait_fail_trigger(dev[0], "GET_FAIL",
3752                               note="No failure seen for %d:%s" % (count, func))
3753             dev[0].request("REMOVE_NETWORK all")
3754             dev[0].wait_disconnected()
3755             dev[0].dump_monitor()
3756 
3757 def run_eap_psk_connect(dev):
3758     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
3759                 eap="PSK", identity="psk.user@example.com",
3760                 password_hex="0123456789abcdef0123456789abcdef",
3761                 wait_connect=False)
3762     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
3763                          "CTRL-EVENT-DISCONNECTED"],
3764                         timeout=1)
3765     dev.request("REMOVE_NETWORK all")
3766     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
3767         dev.wait_disconnected()
3768     dev.dump_monitor()
3769 
3770 def test_eap_proto_psk_errors_server(dev, apdev):
3771     """EAP-PSK local error cases on server"""
3772     check_eap_capa(dev[0], "PSK")
3773     params = int_eap_server_params()
3774     params['erp_domain'] = 'example.com'
3775     params['eap_server_erp'] = '1'
3776     hapd = hostapd.add_ap(apdev[0], params)
3777     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3778 
3779     tests = [(1, "eap_psk_init"),
3780              (1, "eap_msg_alloc;eap_psk_build_1"),
3781              (1, "eap_msg_alloc;eap_psk_build_3"),
3782              (1, "=eap_psk_build_3"),
3783              (1, "=eap_psk_process_2"),
3784              (2, "=eap_psk_process_2"),
3785              (1, "=eap_psk_process_4"),
3786              (1, "aes_128_eax_decrypt;eap_psk_process_4"),
3787              (1, "eap_psk_getKey"),
3788              (1, "eap_psk_get_emsk"),
3789              (1, "eap_psk_get_session_id")]
3790     for count, func in tests:
3791         with alloc_fail(hapd, count, func):
3792             run_eap_psk_connect(dev[0])
3793 
3794     tests = [(1, "os_get_random;eap_psk_build_1"),
3795              (1, "omac1_aes_128;eap_psk_build_3"),
3796              (1, "eap_psk_derive_keys;eap_psk_build_3"),
3797              (1, "aes_128_eax_encrypt;eap_psk_build_3"),
3798              (1, "eap_psk_key_setup;eap_psk_process_2"),
3799              (1, "omac1_aes_128;eap_psk_process_2"),
3800              (1, "aes_128_eax_decrypt;eap_psk_process_4")]
3801     for count, func in tests:
3802         with fail_test(hapd, count, func):
3803             run_eap_psk_connect(dev[0])
3804 
3805 def start_psk_assoc(dev, hapd):
3806     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
3807                 eap="PSK", identity="psk.user@example.com",
3808                 password_hex="0123456789abcdef0123456789abcdef",
3809                 wait_connect=False)
3810     proxy_msg(hapd, dev) # EAP-Identity/Request
3811     proxy_msg(dev, hapd) # EAP-Identity/Response
3812     proxy_msg(hapd, dev) # PSK-1
3813 
3814 def stop_psk_assoc(dev, hapd):
3815     dev.request("REMOVE_NETWORK all")
3816     dev.wait_disconnected()
3817     dev.dump_monitor()
3818     hapd.dump_monitor()
3819 
3820 def test_eap_proto_psk_server(dev, apdev):
3821     """EAP-PSK protocol testing for the server"""
3822     check_eap_capa(dev[0], "PSK")
3823     params = int_eap_server_params()
3824     params['erp_domain'] = 'example.com'
3825     params['eap_server_erp'] = '1'
3826     hapd = hostapd.add_ap(apdev[0], params)
3827     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
3828     hapd.request("SET ext_eapol_frame_io 1")
3829     dev[0].request("SET ext_eapol_frame_io 1")
3830 
3831     # Successful exchange to verify proxying mechanism
3832     start_psk_assoc(dev[0], hapd)
3833     proxy_msg(dev[0], hapd) # PSK-2
3834     proxy_msg(hapd, dev[0]) # PSK-3
3835     proxy_msg(dev[0], hapd) # PSK-4
3836     proxy_msg(hapd, dev[0]) # EAP-Success
3837     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 1/4
3838     proxy_msg(dev[0], hapd) # EAPOL-Key msg 2/4
3839     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 3/4
3840     proxy_msg(dev[0], hapd) # EAPOL-Key msg 4/4
3841     dev[0].wait_connected()
3842     stop_psk_assoc(dev[0], hapd)
3843 
3844     start_psk_assoc(dev[0], hapd)
3845     resp = rx_msg(dev[0])
3846     # Too short EAP-PSK header (no Flags)
3847     hapd.note("EAP-PSK: Invalid frame")
3848     msg = resp[0:4] + "0005" + resp[8:12] + "0005" + "2f"
3849     tx_msg(dev[0], hapd, msg)
3850     # Unexpected PSK-1
3851     hapd.note("EAP-PSK: Expected PSK-2 - ignore T=0")
3852     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "2f00"
3853     tx_msg(dev[0], hapd, msg)
3854     # Too short PSK-2
3855     hapd.note("EAP-PSK: Too short frame")
3856     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "2f40"
3857     tx_msg(dev[0], hapd, msg)
3858     # PSK-2 with unknown ID_P
3859     hapd.note("EAP-PSK: EAP-PSK not enabled for ID_P")
3860     msg = resp[0:4] + "004a" + resp[8:12] + "004a" + "2f40" + 3*16*"00" + 20*"00"
3861     tx_msg(dev[0], hapd, msg)
3862     rx_msg(hapd) # EAP-Failure
3863     stop_psk_assoc(dev[0], hapd)
3864 
3865     start_psk_assoc(dev[0], hapd)
3866     proxy_msg(dev[0], hapd) # PSK-2
3867     proxy_msg(hapd, dev[0]) # PSK-3
3868     resp = rx_msg(dev[0])
3869     # Unexpected PSK-2
3870     hapd.note("EAP-PSK: Expected PSK-4 - ignore T=1")
3871     msg = resp[0:4] + "0016" + resp[8:12] + "0016" + "2f40" + 16*"00"
3872     tx_msg(dev[0], hapd, msg)
3873     # Too short PSK-4 (no PCHANNEL)
3874     hapd.note("EAP-PSK: Too short PCHANNEL data in PSK-4 (len=0, expected 21)")
3875     msg = resp[0:4] + "0016" + resp[8:12] + "0016" + "2fc0" + 16*"00"
3876     tx_msg(dev[0], hapd, msg)
3877     rx_msg(hapd) # PSK-3 retry
3878     stop_psk_assoc(dev[0], hapd)
3879 
3880     start_psk_assoc(dev[0], hapd)
3881     proxy_msg(dev[0], hapd) # PSK-2
3882     proxy_msg(hapd, dev[0]) # PSK-3
3883     resp = rx_msg(dev[0])
3884     # PCHANNEL Nonce did not increase
3885     hapd.note("EAP-PSK: Nonce did not increase")
3886     msg = resp[0:4] + "002b" + resp[8:12] + "002b" + "2fc0" + 16*"00" + 21*"00"
3887     tx_msg(dev[0], hapd, msg)
3888     rx_msg(hapd) # PSK-3 retry
3889     stop_psk_assoc(dev[0], hapd)
3890 
3891     start_psk_assoc(dev[0], hapd)
3892     proxy_msg(dev[0], hapd) # PSK-2
3893     proxy_msg(hapd, dev[0]) # PSK-3
3894     resp = rx_msg(dev[0])
3895     # Invalid PCHANNEL encryption
3896     hapd.note("EAP-PSK: PCHANNEL decryption failed")
3897     msg = resp[0:4] + "002b" + resp[8:12] + "002b" + "2fc0" + 16*"00" + 21*"11"
3898     tx_msg(dev[0], hapd, msg)
3899     rx_msg(hapd) # PSK-3 retry
3900     stop_psk_assoc(dev[0], hapd)
3901 
3902 EAP_SIM_SUBTYPE_START = 10
3903 EAP_SIM_SUBTYPE_CHALLENGE = 11
3904 EAP_SIM_SUBTYPE_NOTIFICATION = 12
3905 EAP_SIM_SUBTYPE_REAUTHENTICATION = 13
3906 EAP_SIM_SUBTYPE_CLIENT_ERROR = 14
3907 
3908 EAP_AKA_SUBTYPE_CHALLENGE = 1
3909 EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT = 2
3910 EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE = 4
3911 EAP_AKA_SUBTYPE_IDENTITY = 5
3912 EAP_AKA_SUBTYPE_NOTIFICATION = 12
3913 EAP_AKA_SUBTYPE_REAUTHENTICATION = 13
3914 EAP_AKA_SUBTYPE_CLIENT_ERROR = 14
3915 
3916 EAP_SIM_AT_RAND = 1
3917 EAP_SIM_AT_AUTN = 2
3918 EAP_SIM_AT_RES = 3
3919 EAP_SIM_AT_AUTS = 4
3920 EAP_SIM_AT_PADDING = 6
3921 EAP_SIM_AT_NONCE_MT = 7
3922 EAP_SIM_AT_PERMANENT_ID_REQ = 10
3923 EAP_SIM_AT_MAC = 11
3924 EAP_SIM_AT_NOTIFICATION = 12
3925 EAP_SIM_AT_ANY_ID_REQ = 13
3926 EAP_SIM_AT_IDENTITY = 14
3927 EAP_SIM_AT_VERSION_LIST = 15
3928 EAP_SIM_AT_SELECTED_VERSION = 16
3929 EAP_SIM_AT_FULLAUTH_ID_REQ = 17
3930 EAP_SIM_AT_COUNTER = 19
3931 EAP_SIM_AT_COUNTER_TOO_SMALL = 20
3932 EAP_SIM_AT_NONCE_S = 21
3933 EAP_SIM_AT_CLIENT_ERROR_CODE = 22
3934 EAP_SIM_AT_KDF_INPUT = 23
3935 EAP_SIM_AT_KDF = 24
3936 EAP_SIM_AT_IV = 129
3937 EAP_SIM_AT_ENCR_DATA = 130
3938 EAP_SIM_AT_NEXT_PSEUDONYM = 132
3939 EAP_SIM_AT_NEXT_REAUTH_ID = 133
3940 EAP_SIM_AT_CHECKCODE = 134
3941 EAP_SIM_AT_RESULT_IND = 135
3942 EAP_SIM_AT_BIDDING = 136
3943 
3944 def test_eap_proto_aka(dev, apdev):
3945     """EAP-AKA protocol tests"""
3946     def aka_handler(ctx, req):
3947         logger.info("aka_handler - RX " + binascii.hexlify(req).decode())
3948         if 'num' not in ctx:
3949             ctx['num'] = 0
3950         ctx['num'] = ctx['num'] + 1
3951         if 'id' not in ctx:
3952             ctx['id'] = 1
3953         ctx['id'] = (ctx['id'] + 1) % 256
3954 
3955         idx = 0
3956 
3957         idx += 1
3958         if ctx['num'] == idx:
3959             logger.info("Test: Missing payload")
3960             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
3961                                4 + 1,
3962                                EAP_TYPE_AKA)
3963 
3964         idx += 1
3965         if ctx['num'] == idx:
3966             logger.info("Test: Unknown subtype")
3967             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3968                                4 + 1 + 3,
3969                                EAP_TYPE_AKA, 255, 0)
3970         idx += 1
3971         if ctx['num'] == idx:
3972             logger.info("Test: EAP-Failure")
3973             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3974 
3975         idx += 1
3976         if ctx['num'] == idx:
3977             logger.info("Test: Client Error")
3978             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
3979                                4 + 1 + 3,
3980                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR, 0)
3981         idx += 1
3982         if ctx['num'] == idx:
3983             logger.info("Test: EAP-Failure")
3984             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3985 
3986         idx += 1
3987         if ctx['num'] == idx:
3988             logger.info("Test: Too short attribute header")
3989             return struct.pack(">BBHBBHB", EAP_CODE_REQUEST, ctx['id'],
3990                                4 + 1 + 1 + 3,
3991                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255)
3992         idx += 1
3993         if ctx['num'] == idx:
3994             logger.info("Test: EAP-Failure")
3995             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
3996 
3997         idx += 1
3998         if ctx['num'] == idx:
3999             logger.info("Test: Truncated attribute")
4000             return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
4001                                4 + 1 + 1 + 4,
4002                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
4003                                255)
4004         idx += 1
4005         if ctx['num'] == idx:
4006             logger.info("Test: EAP-Failure")
4007             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4008 
4009         idx += 1
4010         if ctx['num'] == idx:
4011             logger.info("Test: Too short attribute data")
4012             return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
4013                                4 + 1 + 1 + 4,
4014                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
4015                                0)
4016         idx += 1
4017         if ctx['num'] == idx:
4018             logger.info("Test: EAP-Failure")
4019             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4020 
4021         idx += 1
4022         if ctx['num'] == idx:
4023             logger.info("Test: Skippable/non-skippable unrecognzized attribute")
4024             return struct.pack(">BBHBBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4025                                4 + 1 + 1 + 10,
4026                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4027                                255, 1, 0, 127, 1, 0)
4028         idx += 1
4029         if ctx['num'] == idx:
4030             logger.info("Test: EAP-Failure")
4031             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4032 
4033         idx += 1
4034         if ctx['num'] == idx:
4035             logger.info("Test: Identity request without ID type")
4036             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4037                                4 + 1 + 3,
4038                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0)
4039         idx += 1
4040         if ctx['num'] == idx:
4041             logger.info("Test: Identity request ANY_ID")
4042             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4043                                4 + 1 + 3 + 4,
4044                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4045                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4046         idx += 1
4047         if ctx['num'] == idx:
4048             logger.info("Test: Identity request ANY_ID (duplicate)")
4049             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4050                                4 + 1 + 3 + 4,
4051                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4052                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4053         idx += 1
4054         if ctx['num'] == idx:
4055             logger.info("Test: EAP-Failure")
4056             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4057 
4058         idx += 1
4059         if ctx['num'] == idx:
4060             logger.info("Test: Identity request ANY_ID")
4061             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4062                                4 + 1 + 3 + 4,
4063                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4064                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4065         idx += 1
4066         if ctx['num'] == idx:
4067             logger.info("Test: Identity request FULLAUTH_ID")
4068             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4069                                4 + 1 + 3 + 4,
4070                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4071                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
4072         idx += 1
4073         if ctx['num'] == idx:
4074             logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
4075             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4076                                4 + 1 + 3 + 4,
4077                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4078                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
4079         idx += 1
4080         if ctx['num'] == idx:
4081             logger.info("Test: EAP-Failure")
4082             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4083 
4084         idx += 1
4085         if ctx['num'] == idx:
4086             logger.info("Test: Identity request ANY_ID")
4087             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4088                                4 + 1 + 3 + 4,
4089                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4090                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4091         idx += 1
4092         if ctx['num'] == idx:
4093             logger.info("Test: Identity request FULLAUTH_ID")
4094             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4095                                4 + 1 + 3 + 4,
4096                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4097                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
4098         idx += 1
4099         if ctx['num'] == idx:
4100             logger.info("Test: Identity request PERMANENT_ID")
4101             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4102                                4 + 1 + 3 + 4,
4103                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4104                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
4105         idx += 1
4106         if ctx['num'] == idx:
4107             logger.info("Test: Identity request PERMANENT_ID (duplicate)")
4108             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4109                                4 + 1 + 3 + 4,
4110                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4111                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
4112         idx += 1
4113         if ctx['num'] == idx:
4114             logger.info("Test: EAP-Failure")
4115             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4116 
4117         idx += 1
4118         if ctx['num'] == idx:
4119             logger.info("Test: Challenge with no attributes")
4120             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4121                                4 + 1 + 3,
4122                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0)
4123         idx += 1
4124         if ctx['num'] == idx:
4125             logger.info("Test: EAP-Failure")
4126             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4127 
4128         idx += 1
4129         if ctx['num'] == idx:
4130             logger.info("Test: AKA Challenge with BIDDING")
4131             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4132                                4 + 1 + 3 + 4,
4133                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4134                                EAP_SIM_AT_BIDDING, 1, 0x8000)
4135         idx += 1
4136         if ctx['num'] == idx:
4137             logger.info("Test: EAP-Failure")
4138             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4139 
4140         idx += 1
4141         if ctx['num'] == idx:
4142             logger.info("Test: Notification with no attributes")
4143             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4144                                4 + 1 + 3,
4145                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0)
4146         idx += 1
4147         if ctx['num'] == idx:
4148             logger.info("Test: EAP-Failure")
4149             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4150 
4151         idx += 1
4152         if ctx['num'] == idx:
4153             logger.info("Test: Notification indicating success, but no MAC")
4154             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4155                                4 + 1 + 3 + 4,
4156                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4157                                EAP_SIM_AT_NOTIFICATION, 1, 32768)
4158         idx += 1
4159         if ctx['num'] == idx:
4160             logger.info("Test: EAP-Failure")
4161             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4162 
4163         idx += 1
4164         if ctx['num'] == idx:
4165             logger.info("Test: Notification indicating success, but invalid MAC value")
4166             return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
4167                                4 + 1 + 3 + 4 + 20,
4168                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4169                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
4170                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
4171         idx += 1
4172         if ctx['num'] == idx:
4173             logger.info("Test: EAP-Failure")
4174             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4175 
4176         idx += 1
4177         if ctx['num'] == idx:
4178             logger.info("Test: Notification indicating success with zero-key MAC")
4179             return struct.pack(">BBHBBHBBHBBH16B", EAP_CODE_REQUEST,
4180                                ctx['id'] - 2,
4181                                4 + 1 + 3 + 4 + 20,
4182                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4183                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
4184                                EAP_SIM_AT_MAC, 5, 0,
4185                                0xbe, 0x2e, 0xbb, 0xa9, 0xfa, 0x2e, 0x82, 0x36,
4186                                0x37, 0x8c, 0x32, 0x41, 0xb7, 0xc7, 0x58, 0xa3)
4187         idx += 1
4188         if ctx['num'] == idx:
4189             logger.info("Test: EAP-Success")
4190             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
4191 
4192         idx += 1
4193         if ctx['num'] == idx:
4194             logger.info("Test: Notification before auth")
4195             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4196                                4 + 1 + 3 + 4,
4197                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4198                                EAP_SIM_AT_NOTIFICATION, 1, 16384)
4199         idx += 1
4200         if ctx['num'] == idx:
4201             logger.info("Test: EAP-Failure")
4202             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4203 
4204         idx += 1
4205         if ctx['num'] == idx:
4206             logger.info("Test: Notification before auth")
4207             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4208                                4 + 1 + 3 + 4,
4209                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4210                                EAP_SIM_AT_NOTIFICATION, 1, 16385)
4211         idx += 1
4212         if ctx['num'] == idx:
4213             logger.info("Test: EAP-Failure")
4214             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4215 
4216         idx += 1
4217         if ctx['num'] == idx:
4218             logger.info("Test: Notification with unrecognized non-failure")
4219             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4220                                4 + 1 + 3 + 4,
4221                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4222                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
4223         idx += 1
4224         if ctx['num'] == idx:
4225             logger.info("Test: Notification before auth (duplicate)")
4226             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4227                                4 + 1 + 3 + 4,
4228                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
4229                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
4230         idx += 1
4231         if ctx['num'] == idx:
4232             logger.info("Test: EAP-Failure")
4233             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4234 
4235         idx += 1
4236         if ctx['num'] == idx:
4237             logger.info("Test: Re-authentication (unexpected) with no attributes")
4238             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4239                                4 + 1 + 3,
4240                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
4241                                0)
4242         idx += 1
4243         if ctx['num'] == idx:
4244             logger.info("Test: EAP-Failure")
4245             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4246 
4247         idx += 1
4248         if ctx['num'] == idx:
4249             logger.info("Test: AKA Challenge with Checkcode claiming identity round was used")
4250             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
4251                                4 + 1 + 3 + 24,
4252                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4253                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
4254         idx += 1
4255         if ctx['num'] == idx:
4256             logger.info("Test: EAP-Failure")
4257             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4258 
4259         idx += 1
4260         if ctx['num'] == idx:
4261             logger.info("Test: Identity request ANY_ID")
4262             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4263                                4 + 1 + 3 + 4,
4264                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4265                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4266         idx += 1
4267         if ctx['num'] == idx:
4268             logger.info("Test: AKA Challenge with Checkcode claiming no identity round was used")
4269             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4270                                4 + 1 + 3 + 4,
4271                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4272                                EAP_SIM_AT_CHECKCODE, 1, 0)
4273         idx += 1
4274         if ctx['num'] == idx:
4275             logger.info("Test: EAP-Failure")
4276             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4277 
4278         idx += 1
4279         if ctx['num'] == idx:
4280             logger.info("Test: Identity request ANY_ID")
4281             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4282                                4 + 1 + 3 + 4,
4283                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4284                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
4285         idx += 1
4286         if ctx['num'] == idx:
4287             logger.info("Test: AKA Challenge with mismatching Checkcode value")
4288             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
4289                                4 + 1 + 3 + 24,
4290                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4291                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
4292         idx += 1
4293         if ctx['num'] == idx:
4294             logger.info("Test: EAP-Failure")
4295             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4296 
4297         idx += 1
4298         if ctx['num'] == idx:
4299             logger.info("Test: Re-authentication (unexpected) with Checkcode claimin identity round was used")
4300             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
4301                                4 + 1 + 3 + 24,
4302                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
4303                                0,
4304                                EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
4305         idx += 1
4306         if ctx['num'] == idx:
4307             logger.info("Test: EAP-Failure")
4308             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4309 
4310         idx += 1
4311         if ctx['num'] == idx:
4312             logger.info("Test: Invalid AT_RAND length")
4313             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4314                                4 + 1 + 3 + 4,
4315                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4316                                EAP_SIM_AT_RAND, 1, 0)
4317         idx += 1
4318         if ctx['num'] == idx:
4319             logger.info("Test: EAP-Failure")
4320             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4321 
4322         idx += 1
4323         if ctx['num'] == idx:
4324             logger.info("Test: Invalid AT_AUTN length")
4325             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4326                                4 + 1 + 3 + 4,
4327                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4328                                EAP_SIM_AT_AUTN, 1, 0)
4329         idx += 1
4330         if ctx['num'] == idx:
4331             logger.info("Test: EAP-Failure")
4332             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4333 
4334         idx += 1
4335         if ctx['num'] == idx:
4336             logger.info("Test: Unencrypted AT_PADDING")
4337             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4338                                4 + 1 + 3 + 4,
4339                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4340                                EAP_SIM_AT_PADDING, 1, 0)
4341         idx += 1
4342         if ctx['num'] == idx:
4343             logger.info("Test: EAP-Failure")
4344             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4345 
4346         idx += 1
4347         if ctx['num'] == idx:
4348             logger.info("Test: Invalid AT_NONCE_MT length")
4349             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4350                                4 + 1 + 3 + 4,
4351                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4352                                EAP_SIM_AT_NONCE_MT, 1, 0)
4353         idx += 1
4354         if ctx['num'] == idx:
4355             logger.info("Test: EAP-Failure")
4356             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4357 
4358         idx += 1
4359         if ctx['num'] == idx:
4360             logger.info("Test: Invalid AT_MAC length")
4361             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4362                                4 + 1 + 3 + 4,
4363                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4364                                EAP_SIM_AT_MAC, 1, 0)
4365         idx += 1
4366         if ctx['num'] == idx:
4367             logger.info("Test: EAP-Failure")
4368             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4369 
4370         idx += 1
4371         if ctx['num'] == idx:
4372             logger.info("Test: Invalid AT_NOTIFICATION length")
4373             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4374                                4 + 1 + 3 + 8,
4375                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4376                                EAP_SIM_AT_NOTIFICATION, 2, 0, 0)
4377         idx += 1
4378         if ctx['num'] == idx:
4379             logger.info("Test: EAP-Failure")
4380             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4381 
4382         idx += 1
4383         if ctx['num'] == idx:
4384             logger.info("Test: AT_IDENTITY overflow")
4385             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4386                                4 + 1 + 3 + 4,
4387                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4388                                EAP_SIM_AT_IDENTITY, 1, 0xffff)
4389         idx += 1
4390         if ctx['num'] == idx:
4391             logger.info("Test: EAP-Failure")
4392             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4393 
4394         idx += 1
4395         if ctx['num'] == idx:
4396             logger.info("Test: Unexpected AT_VERSION_LIST")
4397             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4398                                4 + 1 + 3 + 4,
4399                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4400                                EAP_SIM_AT_VERSION_LIST, 1, 0)
4401         idx += 1
4402         if ctx['num'] == idx:
4403             logger.info("Test: EAP-Failure")
4404             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4405 
4406         idx += 1
4407         if ctx['num'] == idx:
4408             logger.info("Test: Invalid AT_SELECTED_VERSION length")
4409             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4410                                4 + 1 + 3 + 8,
4411                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4412                                EAP_SIM_AT_SELECTED_VERSION, 2, 0, 0)
4413         idx += 1
4414         if ctx['num'] == idx:
4415             logger.info("Test: EAP-Failure")
4416             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4417 
4418         idx += 1
4419         if ctx['num'] == idx:
4420             logger.info("Test: Unencrypted AT_COUNTER")
4421             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4422                                4 + 1 + 3 + 4,
4423                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4424                                EAP_SIM_AT_COUNTER, 1, 0)
4425         idx += 1
4426         if ctx['num'] == idx:
4427             logger.info("Test: EAP-Failure")
4428             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4429 
4430         idx += 1
4431         if ctx['num'] == idx:
4432             logger.info("Test: Unencrypted AT_COUNTER_TOO_SMALL")
4433             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4434                                4 + 1 + 3 + 4,
4435                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4436                                EAP_SIM_AT_COUNTER_TOO_SMALL, 1, 0)
4437         idx += 1
4438         if ctx['num'] == idx:
4439             logger.info("Test: EAP-Failure")
4440             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4441 
4442         idx += 1
4443         if ctx['num'] == idx:
4444             logger.info("Test: Unencrypted AT_NONCE_S")
4445             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4446                                4 + 1 + 3 + 4,
4447                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4448                                EAP_SIM_AT_NONCE_S, 1, 0)
4449         idx += 1
4450         if ctx['num'] == idx:
4451             logger.info("Test: EAP-Failure")
4452             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4453 
4454         idx += 1
4455         if ctx['num'] == idx:
4456             logger.info("Test: Invalid AT_CLIENT_ERROR_CODE length")
4457             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4458                                4 + 1 + 3 + 8,
4459                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4460                                EAP_SIM_AT_CLIENT_ERROR_CODE, 2, 0, 0)
4461         idx += 1
4462         if ctx['num'] == idx:
4463             logger.info("Test: EAP-Failure")
4464             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4465 
4466         idx += 1
4467         if ctx['num'] == idx:
4468             logger.info("Test: Invalid AT_IV length")
4469             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4470                                4 + 1 + 3 + 4,
4471                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4472                                EAP_SIM_AT_IV, 1, 0)
4473         idx += 1
4474         if ctx['num'] == idx:
4475             logger.info("Test: EAP-Failure")
4476             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4477 
4478         idx += 1
4479         if ctx['num'] == idx:
4480             logger.info("Test: Invalid AT_ENCR_DATA length")
4481             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4482                                4 + 1 + 3 + 8,
4483                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4484                                EAP_SIM_AT_ENCR_DATA, 2, 0, 0)
4485         idx += 1
4486         if ctx['num'] == idx:
4487             logger.info("Test: EAP-Failure")
4488             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4489 
4490         idx += 1
4491         if ctx['num'] == idx:
4492             logger.info("Test: Unencrypted AT_NEXT_PSEUDONYM")
4493             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4494                                4 + 1 + 3 + 4,
4495                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4496                                EAP_SIM_AT_NEXT_PSEUDONYM, 1, 0)
4497         idx += 1
4498         if ctx['num'] == idx:
4499             logger.info("Test: EAP-Failure")
4500             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4501 
4502         idx += 1
4503         if ctx['num'] == idx:
4504             logger.info("Test: Unencrypted AT_NEXT_REAUTH_ID")
4505             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4506                                4 + 1 + 3 + 4,
4507                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4508                                EAP_SIM_AT_NEXT_REAUTH_ID, 1, 0)
4509         idx += 1
4510         if ctx['num'] == idx:
4511             logger.info("Test: EAP-Failure")
4512             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4513 
4514         idx += 1
4515         if ctx['num'] == idx:
4516             logger.info("Test: Invalid AT_RES length")
4517             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4518                                4 + 1 + 3 + 4,
4519                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4520                                EAP_SIM_AT_RES, 1, 0)
4521         idx += 1
4522         if ctx['num'] == idx:
4523             logger.info("Test: EAP-Failure")
4524             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4525 
4526         idx += 1
4527         if ctx['num'] == idx:
4528             logger.info("Test: Invalid AT_RES length")
4529             return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
4530                                4 + 1 + 3 + 24,
4531                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4532                                EAP_SIM_AT_RES, 6, 0xffff, 0, 0, 0, 0, 0)
4533         idx += 1
4534         if ctx['num'] == idx:
4535             logger.info("Test: EAP-Failure")
4536             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4537 
4538         idx += 1
4539         if ctx['num'] == idx:
4540             logger.info("Test: Invalid AT_AUTS length")
4541             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4542                                4 + 1 + 3 + 8,
4543                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4544                                EAP_SIM_AT_AUTS, 2, 0, 0)
4545         idx += 1
4546         if ctx['num'] == idx:
4547             logger.info("Test: EAP-Failure")
4548             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4549 
4550         idx += 1
4551         if ctx['num'] == idx:
4552             logger.info("Test: Invalid AT_CHECKCODE length")
4553             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4554                                4 + 1 + 3 + 8,
4555                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4556                                EAP_SIM_AT_CHECKCODE, 2, 0, 0)
4557         idx += 1
4558         if ctx['num'] == idx:
4559             logger.info("Test: EAP-Failure")
4560             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4561 
4562         idx += 1
4563         if ctx['num'] == idx:
4564             logger.info("Test: Invalid AT_RESULT_IND length")
4565             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4566                                4 + 1 + 3 + 8,
4567                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4568                                EAP_SIM_AT_RESULT_IND, 2, 0, 0)
4569         idx += 1
4570         if ctx['num'] == idx:
4571             logger.info("Test: EAP-Failure")
4572             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4573 
4574         idx += 1
4575         if ctx['num'] == idx:
4576             logger.info("Test: Unexpected AT_KDF_INPUT")
4577             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4578                                4 + 1 + 3 + 8,
4579                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4580                                EAP_SIM_AT_KDF_INPUT, 2, 0, 0)
4581         idx += 1
4582         if ctx['num'] == idx:
4583             logger.info("Test: EAP-Failure")
4584             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4585 
4586         idx += 1
4587         if ctx['num'] == idx:
4588             logger.info("Test: Unexpected AT_KDF")
4589             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4590                                4 + 1 + 3 + 8,
4591                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4592                                EAP_SIM_AT_KDF, 2, 0, 0)
4593         idx += 1
4594         if ctx['num'] == idx:
4595             logger.info("Test: EAP-Failure")
4596             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4597 
4598         idx += 1
4599         if ctx['num'] == idx:
4600             logger.info("Test: Invalid AT_BIDDING length")
4601             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4602                                4 + 1 + 3 + 8,
4603                                EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
4604                                EAP_SIM_AT_BIDDING, 2, 0, 0)
4605         idx += 1
4606         if ctx['num'] == idx:
4607             logger.info("Test: EAP-Failure")
4608             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4609 
4610         return None
4611 
4612     srv = start_radius_server(aka_handler)
4613 
4614     try:
4615         hapd = start_ap(apdev[0])
4616         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
4617 
4618         for i in range(0, 49):
4619             eap = "AKA AKA'" if i == 11 else "AKA"
4620             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
4621                            eap=eap, identity="0232010000000000",
4622                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
4623                            wait_connect=False)
4624             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
4625                                    timeout=15)
4626             if ev is None:
4627                 raise Exception("Timeout on EAP start")
4628             if i in [0, 15]:
4629                 time.sleep(0.1)
4630             else:
4631                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
4632                                        timeout=10)
4633                 if ev is None:
4634                     raise Exception("Timeout on EAP failure")
4635             dev[0].request("REMOVE_NETWORK all")
4636             dev[0].dump_monitor()
4637     finally:
4638         stop_radius_server(srv)
4639 
4640 def test_eap_proto_aka_prime(dev, apdev):
4641     """EAP-AKA' protocol tests"""
4642     def aka_prime_handler(ctx, req):
4643         logger.info("aka_prime_handler - RX " + binascii.hexlify(req).decode())
4644         if 'num' not in ctx:
4645             ctx['num'] = 0
4646         ctx['num'] = ctx['num'] + 1
4647         if 'id' not in ctx:
4648             ctx['id'] = 1
4649         ctx['id'] = (ctx['id'] + 1) % 256
4650 
4651         idx = 0
4652 
4653         idx += 1
4654         if ctx['num'] == idx:
4655             logger.info("Test: Missing payload")
4656             dev[0].note("Missing payload")
4657             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4658                                4 + 1,
4659                                EAP_TYPE_AKA_PRIME)
4660 
4661         idx += 1
4662         if ctx['num'] == idx:
4663             logger.info("Test: Challenge with no attributes")
4664             dev[0].note("Challenge with no attributes")
4665             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
4666                                4 + 1 + 3,
4667                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0)
4668         idx += 1
4669         if ctx['num'] == idx:
4670             logger.info("Test: EAP-Failure")
4671             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4672 
4673         idx += 1
4674         if ctx['num'] == idx:
4675             logger.info("Test: Challenge with empty AT_KDF_INPUT")
4676             dev[0].note("Challenge with empty AT_KDF_INPUT")
4677             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
4678                                4 + 1 + 3 + 4,
4679                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4680                                EAP_SIM_AT_KDF_INPUT, 1, 0)
4681         idx += 1
4682         if ctx['num'] == idx:
4683             logger.info("Test: EAP-Failure")
4684             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4685 
4686         idx += 1
4687         if ctx['num'] == idx:
4688             logger.info("Test: Challenge with AT_KDF_INPUT")
4689             dev[0].note("Test: Challenge with AT_KDF_INPUT")
4690             return struct.pack(">BBHBBHBBHBBBB", EAP_CODE_REQUEST, ctx['id'],
4691                                4 + 1 + 3 + 8,
4692                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4693                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4694                                ord('c'), ord('d'))
4695         idx += 1
4696         if ctx['num'] == idx:
4697             logger.info("Test: EAP-Failure")
4698             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4699 
4700         idx += 1
4701         if ctx['num'] == idx:
4702             logger.info("Test: Challenge with duplicated KDF")
4703             dev[0].note("Challenge with duplicated KDF")
4704             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
4705                                EAP_CODE_REQUEST, ctx['id'],
4706                                4 + 1 + 3 + 8 + 3 * 4,
4707                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4708                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4709                                ord('c'), ord('d'),
4710                                EAP_SIM_AT_KDF, 1, 1,
4711                                EAP_SIM_AT_KDF, 1, 2,
4712                                EAP_SIM_AT_KDF, 1, 1)
4713         idx += 1
4714         if ctx['num'] == idx:
4715             logger.info("Test: EAP-Failure")
4716             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4717 
4718         idx += 1
4719         if ctx['num'] == idx:
4720             logger.info("Test: Challenge with multiple KDF proposals")
4721             dev[0].note("Challenge with multiple KDF proposals (preparation)")
4722             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
4723                                EAP_CODE_REQUEST, ctx['id'],
4724                                4 + 1 + 3 + 8 + 3 * 4,
4725                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4726                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4727                                ord('c'), ord('d'),
4728                                EAP_SIM_AT_KDF, 1, 255,
4729                                EAP_SIM_AT_KDF, 1, 254,
4730                                EAP_SIM_AT_KDF, 1, 1)
4731         idx += 1
4732         if ctx['num'] == idx:
4733             logger.info("Test: Challenge with incorrect KDF selected")
4734             dev[0].note("Challenge with incorrect KDF selected")
4735             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
4736                                EAP_CODE_REQUEST, ctx['id'],
4737                                4 + 1 + 3 + 8 + 4 * 4,
4738                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4739                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4740                                ord('c'), ord('d'),
4741                                EAP_SIM_AT_KDF, 1, 255,
4742                                EAP_SIM_AT_KDF, 1, 255,
4743                                EAP_SIM_AT_KDF, 1, 254,
4744                                EAP_SIM_AT_KDF, 1, 1)
4745         idx += 1
4746         if ctx['num'] == idx:
4747             logger.info("Test: EAP-Failure")
4748             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4749 
4750         idx += 1
4751         if ctx['num'] == idx:
4752             logger.info("Test: Challenge with multiple KDF proposals")
4753             dev[0].note("Challenge with multiple KDF proposals (preparation)")
4754             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
4755                                EAP_CODE_REQUEST, ctx['id'],
4756                                4 + 1 + 3 + 8 + 3 * 4,
4757                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4758                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4759                                ord('c'), ord('d'),
4760                                EAP_SIM_AT_KDF, 1, 255,
4761                                EAP_SIM_AT_KDF, 1, 254,
4762                                EAP_SIM_AT_KDF, 1, 1)
4763         idx += 1
4764         if ctx['num'] == idx:
4765             logger.info("Test: Challenge with selected KDF not duplicated")
4766             dev[0].note("Challenge with selected KDF not duplicated")
4767             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
4768                                EAP_CODE_REQUEST, ctx['id'],
4769                                4 + 1 + 3 + 8 + 3 * 4,
4770                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4771                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4772                                ord('c'), ord('d'),
4773                                EAP_SIM_AT_KDF, 1, 1,
4774                                EAP_SIM_AT_KDF, 1, 255,
4775                                EAP_SIM_AT_KDF, 1, 254)
4776         idx += 1
4777         if ctx['num'] == idx:
4778             logger.info("Test: EAP-Failure")
4779             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4780 
4781         idx += 1
4782         if ctx['num'] == idx:
4783             logger.info("Test: Challenge with multiple KDF proposals")
4784             dev[0].note("Challenge with multiple KDF proposals (preparation)")
4785             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
4786                                EAP_CODE_REQUEST, ctx['id'],
4787                                4 + 1 + 3 + 8 + 3 * 4,
4788                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4789                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4790                                ord('c'), ord('d'),
4791                                EAP_SIM_AT_KDF, 1, 255,
4792                                EAP_SIM_AT_KDF, 1, 254,
4793                                EAP_SIM_AT_KDF, 1, 1)
4794         idx += 1
4795         if ctx['num'] == idx:
4796             logger.info("Test: Challenge with selected KDF duplicated (missing MAC, RAND, AUTN)")
4797             dev[0].note("Challenge with selected KDF duplicated (missing MAC, RAND, AUTN)")
4798             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
4799                                EAP_CODE_REQUEST, ctx['id'],
4800                                4 + 1 + 3 + 8 + 4 * 4,
4801                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4802                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4803                                ord('c'), ord('d'),
4804                                EAP_SIM_AT_KDF, 1, 1,
4805                                EAP_SIM_AT_KDF, 1, 255,
4806                                EAP_SIM_AT_KDF, 1, 254,
4807                                EAP_SIM_AT_KDF, 1, 1)
4808         idx += 1
4809         if ctx['num'] == idx:
4810             logger.info("Test: EAP-Failure")
4811             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4812 
4813         idx += 1
4814         if ctx['num'] == idx:
4815             logger.info("Test: Challenge with multiple unsupported KDF proposals")
4816             dev[0].note("Challenge with multiple unsupported KDF proposals")
4817             return struct.pack(">BBHBBHBBHBBBBBBHBBH",
4818                                EAP_CODE_REQUEST, ctx['id'],
4819                                4 + 1 + 3 + 8 + 2 * 4,
4820                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4821                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4822                                ord('c'), ord('d'),
4823                                EAP_SIM_AT_KDF, 1, 255,
4824                                EAP_SIM_AT_KDF, 1, 254)
4825         idx += 1
4826         if ctx['num'] == idx:
4827             logger.info("Test: EAP-Failure")
4828             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4829 
4830         idx += 1
4831         if ctx['num'] == idx:
4832             logger.info("Test: Challenge with multiple KDF proposals")
4833             dev[0].note("Challenge with multiple KDF proposals (preparation)")
4834             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
4835                                EAP_CODE_REQUEST, ctx['id'],
4836                                4 + 1 + 3 + 8 + 3 * 4,
4837                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4838                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4839                                ord('c'), ord('d'),
4840                                EAP_SIM_AT_KDF, 1, 255,
4841                                EAP_SIM_AT_KDF, 1, 254,
4842                                EAP_SIM_AT_KDF, 1, 1)
4843         idx += 1
4844         if ctx['num'] == idx:
4845             logger.info("Test: Challenge with invalid MAC, RAND, AUTN values)")
4846             dev[0].note("Challenge with invalid MAC, RAND, AUTN values)")
4847             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBHBBH4LBBH4LBBH4L",
4848                                EAP_CODE_REQUEST, ctx['id'],
4849                                4 + 1 + 3 + 8 + 4 * 4 + 20 + 20 + 20,
4850                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4851                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4852                                ord('c'), ord('d'),
4853                                EAP_SIM_AT_KDF, 1, 1,
4854                                EAP_SIM_AT_KDF, 1, 255,
4855                                EAP_SIM_AT_KDF, 1, 254,
4856                                EAP_SIM_AT_KDF, 1, 1,
4857                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0,
4858                                EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
4859                                EAP_SIM_AT_AUTN, 5, 0, 0, 0, 0, 0)
4860         idx += 1
4861         if ctx['num'] == idx:
4862             logger.info("Test: EAP-Failure")
4863             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4864 
4865         idx += 1
4866         if ctx['num'] == idx:
4867             logger.info("Test: Challenge - AMF separation bit not set)")
4868             dev[0].note("Challenge - AMF separation bit not set)")
4869             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
4870                                EAP_CODE_REQUEST, ctx['id'],
4871                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
4872                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4873                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4874                                ord('c'), ord('d'),
4875                                EAP_SIM_AT_KDF, 1, 1,
4876                                EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
4877                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
4878                                EAP_SIM_AT_AUTN, 5, 0, 9, 10,
4879                                0x2fda8ef7, 0xbba518cc)
4880         idx += 1
4881         if ctx['num'] == idx:
4882             logger.info("Test: EAP-Failure")
4883             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4884 
4885         idx += 1
4886         if ctx['num'] == idx:
4887             logger.info("Test: Challenge - Invalid MAC")
4888             dev[0].note("Challenge - Invalid MAC")
4889             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
4890                                EAP_CODE_REQUEST, ctx['id'],
4891                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
4892                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4893                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4894                                ord('c'), ord('d'),
4895                                EAP_SIM_AT_KDF, 1, 1,
4896                                EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
4897                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
4898                                EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
4899                                0xd1f90322, 0x40514cb4)
4900         idx += 1
4901         if ctx['num'] == idx:
4902             logger.info("Test: EAP-Failure")
4903             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4904 
4905         idx += 1
4906         if ctx['num'] == idx:
4907             logger.info("Test: Challenge - Valid MAC")
4908             dev[0].note("Challenge - Valid MAC")
4909             return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
4910                                EAP_CODE_REQUEST, ctx['id'],
4911                                4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
4912                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4913                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4914                                ord('c'), ord('d'),
4915                                EAP_SIM_AT_KDF, 1, 1,
4916                                EAP_SIM_AT_MAC, 5, 0,
4917                                0xf4a3c1d3, 0x7c901401, 0x34bd8b01, 0x6f7fa32f,
4918                                EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
4919                                EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
4920                                0xd1f90322, 0x40514cb4)
4921         idx += 1
4922         if ctx['num'] == idx:
4923             logger.info("Test: EAP-Failure")
4924             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4925 
4926         idx += 1
4927         if ctx['num'] == idx:
4928             logger.info("Test: Invalid AT_KDF_INPUT length")
4929             dev[0].note("Invalid AT_KDF_INPUT length")
4930             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4931                                4 + 1 + 3 + 8,
4932                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
4933                                EAP_SIM_AT_KDF_INPUT, 2, 0xffff, 0)
4934         idx += 1
4935         if ctx['num'] == idx:
4936             logger.info("Test: EAP-Failure")
4937             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4938 
4939         idx += 1
4940         if ctx['num'] == idx:
4941             logger.info("Test: Invalid AT_KDF length")
4942             dev[0].note("Invalid AT_KDF length")
4943             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
4944                                4 + 1 + 3 + 8,
4945                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
4946                                EAP_SIM_AT_KDF, 2, 0, 0)
4947         idx += 1
4948         if ctx['num'] == idx:
4949             logger.info("Test: EAP-Failure")
4950             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4951 
4952         idx += 1
4953         if ctx['num'] == idx:
4954             logger.info("Test: Challenge with large number of KDF proposals")
4955             dev[0].note("Challenge with large number of KDF proposals")
4956             return struct.pack(">BBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
4957                                EAP_CODE_REQUEST, ctx['id'],
4958                                4 + 1 + 3 + 12 * 4,
4959                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4960                                EAP_SIM_AT_KDF, 1, 255,
4961                                EAP_SIM_AT_KDF, 1, 254,
4962                                EAP_SIM_AT_KDF, 1, 253,
4963                                EAP_SIM_AT_KDF, 1, 252,
4964                                EAP_SIM_AT_KDF, 1, 251,
4965                                EAP_SIM_AT_KDF, 1, 250,
4966                                EAP_SIM_AT_KDF, 1, 249,
4967                                EAP_SIM_AT_KDF, 1, 248,
4968                                EAP_SIM_AT_KDF, 1, 247,
4969                                EAP_SIM_AT_KDF, 1, 246,
4970                                EAP_SIM_AT_KDF, 1, 245,
4971                                EAP_SIM_AT_KDF, 1, 244)
4972         idx += 1
4973         if ctx['num'] == idx:
4974             logger.info("Test: EAP-Failure")
4975             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
4976 
4977         idx += 1
4978         if ctx['num'] == idx:
4979             logger.info("Test: Challenge with multiple KDF proposals")
4980             dev[0].note("Challenge with multiple KDF proposals (preparation)")
4981             return struct.pack(">BBHBBHBBHBBBBBBHBBH",
4982                                EAP_CODE_REQUEST, ctx['id'],
4983                                4 + 1 + 3 + 8 + 2 * 4,
4984                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4985                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4986                                ord('c'), ord('d'),
4987                                EAP_SIM_AT_KDF, 1, 2,
4988                                EAP_SIM_AT_KDF, 1, 1)
4989         idx += 1
4990         if ctx['num'] == idx:
4991             logger.info("Test: Challenge with an extra KDF appended")
4992             dev[0].note("Challenge with an extra KDF appended")
4993             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
4994                                EAP_CODE_REQUEST, ctx['id'],
4995                                4 + 1 + 3 + 8 + 4 * 4,
4996                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
4997                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
4998                                ord('c'), ord('d'),
4999                                EAP_SIM_AT_KDF, 1, 1,
5000                                EAP_SIM_AT_KDF, 1, 2,
5001                                EAP_SIM_AT_KDF, 1, 1,
5002                                EAP_SIM_AT_KDF, 1, 0)
5003         idx += 1
5004         if ctx['num'] == idx:
5005             logger.info("Test: EAP-Failure")
5006             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5007 
5008         idx += 1
5009         if ctx['num'] == idx:
5010             logger.info("Test: Challenge with multiple KDF proposals")
5011             dev[0].note("Challenge with multiple KDF proposals (preparation)")
5012             return struct.pack(">BBHBBHBBHBBBBBBHBBH",
5013                                EAP_CODE_REQUEST, ctx['id'],
5014                                4 + 1 + 3 + 8 + 2 * 4,
5015                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
5016                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
5017                                ord('c'), ord('d'),
5018                                EAP_SIM_AT_KDF, 1, 2,
5019                                EAP_SIM_AT_KDF, 1, 1)
5020         idx += 1
5021         if ctx['num'] == idx:
5022             logger.info("Test: Challenge with a modified KDF")
5023             dev[0].note("Challenge with a modified KDF")
5024             return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
5025                                EAP_CODE_REQUEST, ctx['id'],
5026                                4 + 1 + 3 + 8 + 3 * 4,
5027                                EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
5028                                EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
5029                                ord('c'), ord('d'),
5030                                EAP_SIM_AT_KDF, 1, 1,
5031                                EAP_SIM_AT_KDF, 1, 0,
5032                                EAP_SIM_AT_KDF, 1, 1)
5033         idx += 1
5034         if ctx['num'] == idx:
5035             logger.info("Test: EAP-Failure")
5036             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5037 
5038         return None
5039 
5040     srv = start_radius_server(aka_prime_handler)
5041 
5042     try:
5043         hapd = start_ap(apdev[0])
5044         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
5045 
5046         for i in range(0, 18):
5047             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5048                            eap="AKA'", identity="6555444333222111",
5049                            password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
5050                            wait_connect=False)
5051             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5052                                    timeout=15)
5053             if ev is None:
5054                 raise Exception("Timeout on EAP start")
5055             if i in [0]:
5056                 time.sleep(0.1)
5057             else:
5058                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
5059                                        timeout=10)
5060                 if ev is None:
5061                     raise Exception("Timeout on EAP failure")
5062             dev[0].request("REMOVE_NETWORK all")
5063             dev[0].dump_monitor()
5064     finally:
5065         stop_radius_server(srv)
5066 
5067 def test_eap_proto_sim(dev, apdev):
5068     """EAP-SIM protocol tests"""
5069     def sim_handler(ctx, req):
5070         logger.info("sim_handler - RX " + binascii.hexlify(req).decode())
5071         if 'num' not in ctx:
5072             ctx['num'] = 0
5073         ctx['num'] = ctx['num'] + 1
5074         if 'id' not in ctx:
5075             ctx['id'] = 1
5076         ctx['id'] = (ctx['id'] + 1) % 256
5077 
5078         idx = 0
5079 
5080         idx += 1
5081         if ctx['num'] == idx:
5082             logger.info("Test: Missing payload")
5083             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
5084                                4 + 1,
5085                                EAP_TYPE_SIM)
5086 
5087         idx += 1
5088         if ctx['num'] == idx:
5089             logger.info("Test: Unexpected AT_AUTN")
5090             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
5091                                4 + 1 + 3 + 8,
5092                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5093                                EAP_SIM_AT_AUTN, 2, 0, 0)
5094         idx += 1
5095         if ctx['num'] == idx:
5096             logger.info("Test: EAP-Failure")
5097             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5098 
5099         idx += 1
5100         if ctx['num'] == idx:
5101             logger.info("Test: Too short AT_VERSION_LIST")
5102             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5103                                4 + 1 + 3 + 4,
5104                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5105                                EAP_SIM_AT_VERSION_LIST, 1, 0)
5106         idx += 1
5107         if ctx['num'] == idx:
5108             logger.info("Test: EAP-Failure")
5109             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5110 
5111         idx += 1
5112         if ctx['num'] == idx:
5113             logger.info("Test: AT_VERSION_LIST overflow")
5114             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5115                                4 + 1 + 3 + 4,
5116                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5117                                EAP_SIM_AT_VERSION_LIST, 1, 0xffff)
5118         idx += 1
5119         if ctx['num'] == idx:
5120             logger.info("Test: EAP-Failure")
5121             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5122 
5123         idx += 1
5124         if ctx['num'] == idx:
5125             logger.info("Test: Unexpected AT_AUTS")
5126             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
5127                                4 + 1 + 3 + 8,
5128                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5129                                EAP_SIM_AT_AUTS, 2, 0, 0)
5130         idx += 1
5131         if ctx['num'] == idx:
5132             logger.info("Test: EAP-Failure")
5133             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5134 
5135         idx += 1
5136         if ctx['num'] == idx:
5137             logger.info("Test: Unexpected AT_CHECKCODE")
5138             return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
5139                                4 + 1 + 3 + 8,
5140                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5141                                EAP_SIM_AT_CHECKCODE, 2, 0, 0)
5142         idx += 1
5143         if ctx['num'] == idx:
5144             logger.info("Test: EAP-Failure")
5145             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5146 
5147         idx += 1
5148         if ctx['num'] == idx:
5149             logger.info("Test: No AT_VERSION_LIST in Start")
5150             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
5151                                4 + 1 + 3,
5152                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0)
5153         idx += 1
5154         if ctx['num'] == idx:
5155             logger.info("Test: EAP-Failure")
5156             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5157 
5158         idx += 1
5159         if ctx['num'] == idx:
5160             logger.info("Test: No support version in AT_VERSION_LIST")
5161             return struct.pack(">BBHBBHBBH4B", EAP_CODE_REQUEST, ctx['id'],
5162                                4 + 1 + 3 + 8,
5163                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5164                                EAP_SIM_AT_VERSION_LIST, 2, 3, 2, 3, 4, 5)
5165         idx += 1
5166         if ctx['num'] == idx:
5167             logger.info("Test: EAP-Failure")
5168             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5169 
5170 
5171         idx += 1
5172         if ctx['num'] == idx:
5173             logger.info("Test: Identity request without ID type")
5174             return struct.pack(">BBHBBHBBH2H", EAP_CODE_REQUEST, ctx['id'],
5175                                4 + 1 + 3 + 8,
5176                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5177                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0)
5178         idx += 1
5179         if ctx['num'] == idx:
5180             logger.info("Test: Identity request ANY_ID")
5181             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5182                                4 + 1 + 3 + 8 + 4,
5183                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5184                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5185                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
5186         idx += 1
5187         if ctx['num'] == idx:
5188             logger.info("Test: Identity request ANY_ID (duplicate)")
5189             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5190                                4 + 1 + 3 + 8 + 4,
5191                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5192                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5193                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
5194         idx += 1
5195         if ctx['num'] == idx:
5196             logger.info("Test: EAP-Failure")
5197             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5198 
5199         idx += 1
5200         if ctx['num'] == idx:
5201             logger.info("Test: Identity request ANY_ID")
5202             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5203                                4 + 1 + 3 + 8 + 4,
5204                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5205                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5206                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
5207         idx += 1
5208         if ctx['num'] == idx:
5209             logger.info("Test: Identity request FULLAUTH_ID")
5210             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5211                                4 + 1 + 3 + 8 + 4,
5212                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5213                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5214                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
5215         idx += 1
5216         if ctx['num'] == idx:
5217             logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
5218             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5219                                4 + 1 + 3 + 8 + 4,
5220                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5221                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5222                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
5223         idx += 1
5224         if ctx['num'] == idx:
5225             logger.info("Test: EAP-Failure")
5226             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5227 
5228         idx += 1
5229         if ctx['num'] == idx:
5230             logger.info("Test: Identity request ANY_ID")
5231             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5232                                4 + 1 + 3 + 8 + 4,
5233                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5234                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5235                                EAP_SIM_AT_ANY_ID_REQ, 1, 0)
5236         idx += 1
5237         if ctx['num'] == idx:
5238             logger.info("Test: Identity request FULLAUTH_ID")
5239             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5240                                4 + 1 + 3 + 8 + 4,
5241                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5242                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5243                                EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
5244         idx += 1
5245         if ctx['num'] == idx:
5246             logger.info("Test: Identity request PERMANENT_ID")
5247             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5248                                4 + 1 + 3 + 8 + 4,
5249                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5250                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5251                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
5252         idx += 1
5253         if ctx['num'] == idx:
5254             logger.info("Test: Identity request PERMANENT_ID (duplicate)")
5255             return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
5256                                4 + 1 + 3 + 8 + 4,
5257                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
5258                                EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
5259                                EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
5260         idx += 1
5261         if ctx['num'] == idx:
5262             logger.info("Test: EAP-Failure")
5263             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5264 
5265         idx += 1
5266         if ctx['num'] == idx:
5267             logger.info("Test: No AT_MAC and AT_RAND in Challenge")
5268             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
5269                                4 + 1 + 3,
5270                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0)
5271         idx += 1
5272         if ctx['num'] == idx:
5273             logger.info("Test: EAP-Failure")
5274             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5275 
5276         idx += 1
5277         if ctx['num'] == idx:
5278             logger.info("Test: No AT_RAND in Challenge")
5279             return struct.pack(">BBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
5280                                4 + 1 + 3 + 20,
5281                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
5282                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
5283         idx += 1
5284         if ctx['num'] == idx:
5285             logger.info("Test: EAP-Failure")
5286             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5287 
5288         idx += 1
5289         if ctx['num'] == idx:
5290             logger.info("Test: Insufficient number of challenges in Challenge")
5291             return struct.pack(">BBHBBHBBH4LBBH4L", EAP_CODE_REQUEST, ctx['id'],
5292                                4 + 1 + 3 + 20 + 20,
5293                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
5294                                EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
5295                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
5296         idx += 1
5297         if ctx['num'] == idx:
5298             logger.info("Test: EAP-Failure")
5299             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5300 
5301         idx += 1
5302         if ctx['num'] == idx:
5303             logger.info("Test: Too many challenges in Challenge")
5304             return struct.pack(">BBHBBHBBH4L4L4L4LBBH4L", EAP_CODE_REQUEST,
5305                                ctx['id'],
5306                                4 + 1 + 3 + 4 + 4 * 16 + 20,
5307                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
5308                                EAP_SIM_AT_RAND, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5309                                0, 0, 0, 0, 0, 0, 0, 0,
5310                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
5311         idx += 1
5312         if ctx['num'] == idx:
5313             logger.info("Test: EAP-Failure")
5314             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5315 
5316         idx += 1
5317         if ctx['num'] == idx:
5318             logger.info("Test: Same RAND multiple times in Challenge")
5319             return struct.pack(">BBHBBHBBH4L4L4LBBH4L", EAP_CODE_REQUEST,
5320                                ctx['id'],
5321                                4 + 1 + 3 + 4 + 3 * 16 + 20,
5322                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
5323                                EAP_SIM_AT_RAND, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1,
5324                                0, 0, 0, 0,
5325                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
5326         idx += 1
5327         if ctx['num'] == idx:
5328             logger.info("Test: EAP-Failure")
5329             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5330 
5331         idx += 1
5332         if ctx['num'] == idx:
5333             logger.info("Test: Notification with no attributes")
5334             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
5335                                4 + 1 + 3,
5336                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0)
5337         idx += 1
5338         if ctx['num'] == idx:
5339             logger.info("Test: EAP-Failure")
5340             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5341 
5342         idx += 1
5343         if ctx['num'] == idx:
5344             logger.info("Test: Notification indicating success, but no MAC")
5345             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5346                                4 + 1 + 3 + 4,
5347                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
5348                                EAP_SIM_AT_NOTIFICATION, 1, 32768)
5349         idx += 1
5350         if ctx['num'] == idx:
5351             logger.info("Test: EAP-Failure")
5352             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5353 
5354         idx += 1
5355         if ctx['num'] == idx:
5356             logger.info("Test: Notification indicating success, but invalid MAC value")
5357             return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
5358                                4 + 1 + 3 + 4 + 20,
5359                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
5360                                EAP_SIM_AT_NOTIFICATION, 1, 32768,
5361                                EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
5362         idx += 1
5363         if ctx['num'] == idx:
5364             logger.info("Test: EAP-Failure")
5365             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5366 
5367         idx += 1
5368         if ctx['num'] == idx:
5369             logger.info("Test: Notification before auth")
5370             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5371                                4 + 1 + 3 + 4,
5372                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
5373                                EAP_SIM_AT_NOTIFICATION, 1, 16384)
5374         idx += 1
5375         if ctx['num'] == idx:
5376             logger.info("Test: EAP-Failure")
5377             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5378 
5379         idx += 1
5380         if ctx['num'] == idx:
5381             logger.info("Test: Notification before auth")
5382             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5383                                4 + 1 + 3 + 4,
5384                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
5385                                EAP_SIM_AT_NOTIFICATION, 1, 16385)
5386         idx += 1
5387         if ctx['num'] == idx:
5388             logger.info("Test: EAP-Failure")
5389             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5390 
5391         idx += 1
5392         if ctx['num'] == idx:
5393             logger.info("Test: Notification with unrecognized non-failure")
5394             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5395                                4 + 1 + 3 + 4,
5396                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
5397                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
5398         idx += 1
5399         if ctx['num'] == idx:
5400             logger.info("Test: Notification before auth (duplicate)")
5401             return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
5402                                4 + 1 + 3 + 4,
5403                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
5404                                EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
5405         idx += 1
5406         if ctx['num'] == idx:
5407             logger.info("Test: EAP-Failure")
5408             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5409 
5410         idx += 1
5411         if ctx['num'] == idx:
5412             logger.info("Test: Re-authentication (unexpected) with no attributes")
5413             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
5414                                4 + 1 + 3,
5415                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION,
5416                                0)
5417         idx += 1
5418         if ctx['num'] == idx:
5419             logger.info("Test: EAP-Failure")
5420             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5421 
5422         idx += 1
5423         if ctx['num'] == idx:
5424             logger.info("Test: Client Error")
5425             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
5426                                4 + 1 + 3,
5427                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR, 0)
5428         idx += 1
5429         if ctx['num'] == idx:
5430             logger.info("Test: EAP-Failure")
5431             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5432 
5433         idx += 1
5434         if ctx['num'] == idx:
5435             logger.info("Test: Unknown subtype")
5436             return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
5437                                4 + 1 + 3,
5438                                EAP_TYPE_SIM, 255, 0)
5439         idx += 1
5440         if ctx['num'] == idx:
5441             logger.info("Test: EAP-Failure")
5442             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
5443 
5444         return None
5445 
5446     srv = start_radius_server(sim_handler)
5447 
5448     try:
5449         hapd = start_ap(apdev[0])
5450         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
5451 
5452         for i in range(0, 25):
5453             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5454                            eap="SIM", identity="1232010000000000",
5455                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
5456                            wait_connect=False)
5457             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
5458                                    timeout=15)
5459             if ev is None:
5460                 raise Exception("Timeout on EAP start")
5461             if i in [0]:
5462                 time.sleep(0.1)
5463             else:
5464                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
5465                                        timeout=10)
5466                 if ev is None:
5467                     raise Exception("Timeout on EAP failure")
5468             dev[0].request("REMOVE_NETWORK all")
5469             dev[0].dump_monitor()
5470     finally:
5471         stop_radius_server(srv)
5472 
5473 def test_eap_proto_sim_errors(dev, apdev):
5474     """EAP-SIM protocol tests (error paths)"""
5475     check_hlr_auc_gw_support()
5476     params = hostapd.wpa2_eap_params(ssid="eap-test")
5477     hapd = hostapd.add_ap(apdev[0], params)
5478     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
5479 
5480     with alloc_fail(dev[0], 1, "eap_sim_init"):
5481         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5482                        eap="SIM", identity="1232010000000000",
5483                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
5484                        wait_connect=False)
5485         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
5486                                timeout=15)
5487         if ev is None:
5488             raise Exception("Timeout on EAP start")
5489         dev[0].request("REMOVE_NETWORK all")
5490         dev[0].wait_disconnected()
5491 
5492     with fail_test(dev[0], 1, "os_get_random;eap_sim_init"):
5493         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5494                        eap="SIM", identity="1232010000000000",
5495                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
5496                        wait_connect=False)
5497         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
5498                                timeout=15)
5499         if ev is None:
5500             raise Exception("Timeout on EAP start")
5501         dev[0].request("REMOVE_NETWORK all")
5502         dev[0].wait_disconnected()
5503 
5504     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5505                    eap="SIM", identity="1232010000000000",
5506                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
5507 
5508     with fail_test(dev[0], 1, "aes_128_cbc_encrypt;eap_sim_response_reauth"):
5509         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
5510         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
5511         if ev is None:
5512             raise Exception("EAP re-authentication did not start")
5513         wait_fail_trigger(dev[0], "GET_FAIL")
5514         dev[0].request("REMOVE_NETWORK all")
5515         dev[0].dump_monitor()
5516 
5517     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5518                    eap="SIM", identity="1232010000000000",
5519                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
5520 
5521     with fail_test(dev[0], 1, "os_get_random;eap_sim_msg_add_encr_start"):
5522         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
5523         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
5524         if ev is None:
5525             raise Exception("EAP re-authentication did not start")
5526         wait_fail_trigger(dev[0], "GET_FAIL")
5527         dev[0].request("REMOVE_NETWORK all")
5528         dev[0].dump_monitor()
5529 
5530     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5531                    eap="SIM", identity="1232010000000000",
5532                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
5533 
5534     with fail_test(dev[0], 1, "os_get_random;eap_sim_init_for_reauth"):
5535         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
5536         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
5537         if ev is None:
5538             raise Exception("EAP re-authentication did not start")
5539         wait_fail_trigger(dev[0], "GET_FAIL")
5540         dev[0].request("REMOVE_NETWORK all")
5541         dev[0].dump_monitor()
5542 
5543     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5544                    eap="SIM", identity="1232010000000000",
5545                    password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
5546 
5547     with alloc_fail(dev[0], 1, "eap_sim_parse_encr;eap_sim_process_reauthentication"):
5548         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
5549         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
5550         if ev is None:
5551             raise Exception("EAP re-authentication did not start")
5552         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5553         dev[0].request("REMOVE_NETWORK all")
5554         dev[0].dump_monitor()
5555 
5556     tests = [(1, "eap_sim_verify_mac"),
5557              (1, "eap_sim_parse_encr;eap_sim_process_challenge"),
5558              (1, "eap_sim_msg_init;eap_sim_response_start"),
5559              (1, "wpabuf_alloc;eap_sim_msg_init;eap_sim_response_start"),
5560              (1, "=eap_sim_learn_ids"),
5561              (2, "=eap_sim_learn_ids"),
5562              (2, "eap_sim_learn_ids"),
5563              (3, "eap_sim_learn_ids"),
5564              (1, "eap_sim_process_start"),
5565              (1, "eap_sim_getKey"),
5566              (1, "eap_sim_get_emsk"),
5567              (1, "eap_sim_get_session_id")]
5568     for count, func in tests:
5569         with alloc_fail(dev[0], count, func):
5570             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5571                            eap="SIM", identity="1232010000000000@domain",
5572                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
5573                            erp="1", wait_connect=False)
5574             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5575             dev[0].request("REMOVE_NETWORK all")
5576             dev[0].dump_monitor()
5577 
5578     tests = [(1, "aes_128_cbc_decrypt;eap_sim_parse_encr")]
5579     for count, func in tests:
5580         with fail_test(dev[0], count, func):
5581             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5582                            eap="SIM", identity="1232010000000000",
5583                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
5584                            wait_connect=False)
5585             wait_fail_trigger(dev[0], "GET_FAIL")
5586             dev[0].request("REMOVE_NETWORK all")
5587             dev[0].dump_monitor()
5588 
5589     params = int_eap_server_params()
5590     params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
5591     params['eap_sim_aka_result_ind'] = "1"
5592     hapd2 = hostapd.add_ap(apdev[1], params)
5593     dev[0].scan_for_bss(hapd2.own_addr(), freq=2412)
5594 
5595     with alloc_fail(dev[0], 1,
5596                     "eap_sim_msg_init;eap_sim_response_notification"):
5597         dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
5598                        scan_freq="2412",
5599                        eap="SIM", identity="1232010000000000",
5600                        phase1="result_ind=1",
5601                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
5602                        wait_connect=False)
5603         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5604         dev[0].request("REMOVE_NETWORK all")
5605         dev[0].dump_monitor()
5606 
5607     hapd2.dump_monitor()
5608     tests = ["eap_sim_msg_add_encr_start;eap_sim_response_notification",
5609              "aes_128_cbc_encrypt;eap_sim_response_notification"]
5610     for func in tests:
5611         with fail_test(dev[0], 1, func):
5612             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
5613                            scan_freq="2412",
5614                            eap="SIM", identity="1232010000000000",
5615                            phase1="result_ind=1",
5616                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
5617             hapd2.wait_sta()
5618             dev[0].request("REAUTHENTICATE")
5619             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
5620             if ev is None:
5621                 raise Exception("EAP method not started on reauthentication")
5622             time.sleep(0.1)
5623             wait_fail_trigger(dev[0], "GET_FAIL")
5624             dev[0].request("REMOVE_NETWORK all")
5625             dev[0].dump_monitor()
5626             hapd2.wait_sta_disconnect()
5627 
5628     hapd2.dump_monitor()
5629     tests = ["eap_sim_parse_encr;eap_sim_process_notification_reauth"]
5630     for func in tests:
5631         with alloc_fail(dev[0], 1, func):
5632             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
5633                            scan_freq="2412",
5634                            eap="SIM", identity="1232010000000000",
5635                            phase1="result_ind=1",
5636                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
5637             hapd2.wait_sta()
5638             dev[0].request("REAUTHENTICATE")
5639             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
5640             if ev is None:
5641                 raise Exception("EAP method not started on reauthentication")
5642             time.sleep(0.1)
5643             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5644             dev[0].request("REMOVE_NETWORK all")
5645             dev[0].dump_monitor()
5646             hapd2.wait_sta_disconnect()
5647 
5648 def test_eap_proto_aka_errors(dev, apdev):
5649     """EAP-AKA protocol tests (error paths)"""
5650     check_hlr_auc_gw_support()
5651     params = hostapd.wpa2_eap_params(ssid="eap-test")
5652     hapd = hostapd.add_ap(apdev[0], params)
5653     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
5654 
5655     with alloc_fail(dev[0], 1, "eap_aka_init"):
5656         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5657                        eap="AKA", identity="0232010000000000",
5658                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
5659                        wait_connect=False)
5660         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
5661                                timeout=15)
5662         if ev is None:
5663             raise Exception("Timeout on EAP start")
5664         dev[0].request("REMOVE_NETWORK all")
5665         dev[0].wait_disconnected()
5666 
5667     tests = [(1, "=eap_aka_learn_ids"),
5668              (2, "=eap_aka_learn_ids"),
5669              (1, "eap_sim_parse_encr;eap_aka_process_challenge"),
5670              (1, "wpabuf_alloc;eap_aka_add_id_msg"),
5671              (1, "eap_aka_getKey"),
5672              (1, "eap_aka_get_emsk"),
5673              (1, "eap_aka_get_session_id")]
5674     for count, func in tests:
5675         with alloc_fail(dev[0], count, func):
5676             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5677                            eap="AKA", identity="0232010000000000@domain",
5678                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
5679                            erp="1", wait_connect=False)
5680             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5681             dev[0].request("REMOVE_NETWORK all")
5682             dev[0].dump_monitor()
5683 
5684     params = int_eap_server_params()
5685     params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
5686     params['eap_sim_aka_result_ind'] = "1"
5687     hapd2 = hostapd.add_ap(apdev[1], params)
5688     dev[0].scan_for_bss(hapd2.own_addr(), freq=2412)
5689 
5690     with alloc_fail(dev[0], 1,
5691                     "eap_sim_msg_init;eap_aka_response_notification"):
5692         dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
5693                        eap="AKA", identity="0232010000000000",
5694                        phase1="result_ind=1",
5695                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
5696                        wait_connect=False)
5697         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5698         dev[0].request("REMOVE_NETWORK all")
5699         dev[0].dump_monitor()
5700 
5701     tests = [(1, "aes_128_encrypt_block;milenage_f1;milenage_check", None),
5702              (2, "aes_128_encrypt_block;milenage_f1;milenage_check", None),
5703              (1, "milenage_f2345;milenage_check", None),
5704              (7, "aes_128_encrypt_block;milenage_f2345;milenage_check",
5705               "ff0000000123"),
5706              (1, "aes_128_encrypt_block;milenage_f1;milenage_check",
5707               "fff000000123")]
5708     for count, func, seq in tests:
5709         if not seq:
5710             seq = "000000000123"
5711         with fail_test(dev[0], count, func):
5712             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
5713                            scan_freq="2412",
5714                            eap="AKA", identity="0232010000000000",
5715                            phase1="result_ind=1",
5716                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:" + seq,
5717                            wait_connect=False)
5718             wait_fail_trigger(dev[0], "GET_FAIL")
5719             dev[0].request("REMOVE_NETWORK all")
5720             dev[0].wait_disconnected()
5721             dev[0].dump_monitor()
5722 
5723     hapd2.dump_monitor()
5724     tests = ["eap_sim_msg_add_encr_start;eap_aka_response_notification",
5725              "aes_128_cbc_encrypt;eap_aka_response_notification"]
5726     for func in tests:
5727         with fail_test(dev[0], 1, func):
5728             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
5729                            scan_freq="2412",
5730                            eap="AKA", identity="0232010000000000",
5731                            phase1="result_ind=1",
5732                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
5733             hapd2.wait_sta()
5734             dev[0].request("REAUTHENTICATE")
5735             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
5736             if ev is None:
5737                 raise Exception("EAP method not started on reauthentication")
5738             time.sleep(0.1)
5739             wait_fail_trigger(dev[0], "GET_FAIL")
5740             dev[0].request("REMOVE_NETWORK all")
5741             dev[0].dump_monitor()
5742             hapd2.wait_sta_disconnect()
5743 
5744     hapd2.dump_monitor()
5745     tests = ["eap_sim_parse_encr;eap_aka_process_notification_reauth"]
5746     for func in tests:
5747         with alloc_fail(dev[0], 1, func):
5748             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
5749                            scan_freq="2412",
5750                            eap="AKA", identity="0232010000000000",
5751                            phase1="result_ind=1",
5752                            password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
5753             hapd2.wait_sta()
5754             dev[0].request("REAUTHENTICATE")
5755             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
5756             if ev is None:
5757                 raise Exception("EAP method not started on reauthentication")
5758             time.sleep(0.1)
5759             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5760             dev[0].request("REMOVE_NETWORK all")
5761             dev[0].dump_monitor()
5762             hapd2.wait_sta_disconnect()
5763 
5764 def test_eap_proto_aka_prime_errors(dev, apdev):
5765     """EAP-AKA' protocol tests (error paths)"""
5766     check_hlr_auc_gw_support()
5767     params = hostapd.wpa2_eap_params(ssid="eap-test")
5768     hapd = hostapd.add_ap(apdev[0], params)
5769     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
5770 
5771     with alloc_fail(dev[0], 1, "eap_aka_init"):
5772         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5773                        eap="AKA'", identity="6555444333222111",
5774                        password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
5775                        wait_connect=False)
5776         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
5777                                timeout=15)
5778         if ev is None:
5779             raise Exception("Timeout on EAP start")
5780         dev[0].request("REMOVE_NETWORK all")
5781         dev[0].wait_disconnected()
5782 
5783     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5784                    eap="AKA'", identity="6555444333222111",
5785                    password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
5786 
5787     with fail_test(dev[0], 1, "aes_128_cbc_encrypt;eap_aka_response_reauth"):
5788         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
5789         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
5790         if ev is None:
5791             raise Exception("EAP re-authentication did not start")
5792         wait_fail_trigger(dev[0], "GET_FAIL")
5793         dev[0].request("REMOVE_NETWORK all")
5794         dev[0].dump_monitor()
5795 
5796     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5797                    eap="AKA'", identity="6555444333222111",
5798                    password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
5799 
5800     with alloc_fail(dev[0], 1, "eap_sim_parse_encr;eap_aka_process_reauthentication"):
5801         hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
5802         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
5803         if ev is None:
5804             raise Exception("EAP re-authentication did not start")
5805         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5806         dev[0].request("REMOVE_NETWORK all")
5807         dev[0].dump_monitor()
5808 
5809     tests = [(1, "eap_sim_verify_mac_sha256"),
5810              (1, "=eap_aka_process_challenge")]
5811     for count, func in tests:
5812         with alloc_fail(dev[0], count, func):
5813             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
5814                            eap="AKA'", identity="6555444333222111",
5815                            password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
5816                            erp="1", wait_connect=False)
5817             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
5818             dev[0].request("REMOVE_NETWORK all")
5819             dev[0].dump_monitor()
5820 
5821 def test_eap_proto_ikev2(dev, apdev):
5822     """EAP-IKEv2 protocol tests"""
5823     check_eap_capa(dev[0], "IKEV2")
5824 
5825     global eap_proto_ikev2_test_done
5826     eap_proto_ikev2_test_done = False
5827 
5828     def ikev2_handler(ctx, req):
5829         logger.info("ikev2_handler - RX " + binascii.hexlify(req).decode())
5830         if 'num' not in ctx:
5831             ctx['num'] = 0
5832         ctx['num'] = ctx['num'] + 1
5833         if 'id' not in ctx:
5834             ctx['id'] = 1
5835         ctx['id'] = (ctx['id'] + 1) % 256
5836 
5837         idx = 0
5838 
5839         idx += 1
5840         if ctx['num'] == idx:
5841             logger.info("Test: Missing payload")
5842             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
5843                                4 + 1,
5844                                EAP_TYPE_IKEV2)
5845 
5846         idx += 1
5847         if ctx['num'] == idx:
5848             logger.info("Test: Truncated Message Length field")
5849             return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
5850                                4 + 1 + 1 + 3,
5851                                EAP_TYPE_IKEV2, 0x80, 0, 0, 0)
5852 
5853         idx += 1
5854         if ctx['num'] == idx:
5855             logger.info("Test: Too short Message Length value")
5856             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
5857                                4 + 1 + 1 + 4 + 1,
5858                                EAP_TYPE_IKEV2, 0x80, 0, 1)
5859 
5860         idx += 1
5861         if ctx['num'] == idx:
5862             logger.info("Test: Truncated message")
5863             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
5864                                4 + 1 + 1 + 4,
5865                                EAP_TYPE_IKEV2, 0x80, 1)
5866 
5867         idx += 1
5868         if ctx['num'] == idx:
5869             logger.info("Test: Truncated message(2)")
5870             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
5871                                4 + 1 + 1 + 4,
5872                                EAP_TYPE_IKEV2, 0x80, 0xffffffff)
5873 
5874         idx += 1
5875         if ctx['num'] == idx:
5876             logger.info("Test: Truncated message(3)")
5877             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
5878                                4 + 1 + 1 + 4,
5879                                EAP_TYPE_IKEV2, 0xc0, 0xffffffff)
5880 
5881         idx += 1
5882         if ctx['num'] == idx:
5883             logger.info("Test: Truncated message(4)")
5884             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
5885                                4 + 1 + 1 + 4,
5886                                EAP_TYPE_IKEV2, 0xc0, 10000000)
5887 
5888         idx += 1
5889         if ctx['num'] == idx:
5890             logger.info("Test: Too long fragments (first fragment)")
5891             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
5892                                4 + 1 + 1 + 4 + 1,
5893                                EAP_TYPE_IKEV2, 0xc0, 2, 1)
5894 
5895         idx += 1
5896         if ctx['num'] == idx:
5897             logger.info("Test: Too long fragments (second fragment)")
5898             return struct.pack(">BBHBB2B", EAP_CODE_REQUEST, ctx['id'],
5899                                4 + 1 + 1 + 2,
5900                                EAP_TYPE_IKEV2, 0x00, 2, 3)
5901 
5902         idx += 1
5903         if ctx['num'] == idx:
5904             logger.info("Test: No Message Length field in first fragment")
5905             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
5906                                4 + 1 + 1 + 1,
5907                                EAP_TYPE_IKEV2, 0x40, 1)
5908 
5909         idx += 1
5910         if ctx['num'] == idx:
5911             logger.info("Test: ICV before keys")
5912             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
5913                                4 + 1 + 1,
5914                                EAP_TYPE_IKEV2, 0x20)
5915 
5916         idx += 1
5917         if ctx['num'] == idx:
5918             logger.info("Test: Unsupported IKEv2 header version")
5919             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5920                                4 + 1 + 1 + 28,
5921                                EAP_TYPE_IKEV2, 0x00,
5922                                0, 0, 0, 0,
5923                                0, 0, 0, 0, 0, 0)
5924 
5925         idx += 1
5926         if ctx['num'] == idx:
5927             logger.info("Test: Incorrect IKEv2 header Length")
5928             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5929                                4 + 1 + 1 + 28,
5930                                EAP_TYPE_IKEV2, 0x00,
5931                                0, 0, 0, 0,
5932                                0, 0x20, 0, 0, 0, 0)
5933 
5934         idx += 1
5935         if ctx['num'] == idx:
5936             logger.info("Test: Unexpected IKEv2 Exchange Type in SA_INIT state")
5937             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5938                                4 + 1 + 1 + 28,
5939                                EAP_TYPE_IKEV2, 0x00,
5940                                0, 0, 0, 0,
5941                                0, 0x20, 0, 0, 0, 28)
5942 
5943         idx += 1
5944         if ctx['num'] == idx:
5945             logger.info("Test: Unexpected IKEv2 Message ID in SA_INIT state")
5946             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5947                                4 + 1 + 1 + 28,
5948                                EAP_TYPE_IKEV2, 0x00,
5949                                0, 0, 0, 0,
5950                                0, 0x20, 34, 0, 1, 28)
5951 
5952         idx += 1
5953         if ctx['num'] == idx:
5954             logger.info("Test: Unexpected IKEv2 Flags value")
5955             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5956                                4 + 1 + 1 + 28,
5957                                EAP_TYPE_IKEV2, 0x00,
5958                                0, 0, 0, 0,
5959                                0, 0x20, 34, 0, 0, 28)
5960 
5961         idx += 1
5962         if ctx['num'] == idx:
5963             logger.info("Test: Unexpected IKEv2 Flags value(2)")
5964             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5965                                4 + 1 + 1 + 28,
5966                                EAP_TYPE_IKEV2, 0x00,
5967                                0, 0, 0, 0,
5968                                0, 0x20, 34, 0x20, 0, 28)
5969 
5970         idx += 1
5971         if ctx['num'] == idx:
5972             logger.info("Test: No SAi1 in SA_INIT")
5973             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
5974                                4 + 1 + 1 + 28,
5975                                EAP_TYPE_IKEV2, 0x00,
5976                                0, 0, 0, 0,
5977                                0, 0x20, 34, 0x08, 0, 28)
5978 
5979         def build_ike(id, next=0, exch_type=34, flags=0x00, ike=b''):
5980             return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, id,
5981                                4 + 1 + 1 + 28 + len(ike),
5982                                EAP_TYPE_IKEV2, flags,
5983                                0, 0, 0, 0,
5984                                next, 0x20, exch_type, 0x08, 0,
5985                                28 + len(ike)) + ike
5986 
5987         idx += 1
5988         if ctx['num'] == idx:
5989             logger.info("Test: Unexpected extra data after payloads")
5990             return build_ike(ctx['id'], ike=struct.pack(">B", 1))
5991 
5992         idx += 1
5993         if ctx['num'] == idx:
5994             logger.info("Test: Truncated payload header")
5995             return build_ike(ctx['id'], next=128, ike=struct.pack(">B", 1))
5996 
5997         idx += 1
5998         if ctx['num'] == idx:
5999             logger.info("Test: Too small payload header length")
6000             ike = struct.pack(">BBH", 0, 0, 3)
6001             return build_ike(ctx['id'], next=128, ike=ike)
6002 
6003         idx += 1
6004         if ctx['num'] == idx:
6005             logger.info("Test: Too large payload header length")
6006             ike = struct.pack(">BBH", 0, 0, 5)
6007             return build_ike(ctx['id'], next=128, ike=ike)
6008 
6009         idx += 1
6010         if ctx['num'] == idx:
6011             logger.info("Test: Unsupported payload (non-critical and critical)")
6012             ike = struct.pack(">BBHBBH", 129, 0, 4, 0, 0x01, 4)
6013             return build_ike(ctx['id'], next=128, ike=ike)
6014 
6015         idx += 1
6016         if ctx['num'] == idx:
6017             logger.info("Test: Certificate and empty SAi1")
6018             ike = struct.pack(">BBHBBH", 33, 0, 4, 0, 0, 4)
6019             return build_ike(ctx['id'], next=37, ike=ike)
6020 
6021         idx += 1
6022         if ctx['num'] == idx:
6023             logger.info("Test: Too short proposal")
6024             ike = struct.pack(">BBHBBHBBB", 0, 0, 4 + 7,
6025                               0, 0, 7, 0, 0, 0)
6026             return build_ike(ctx['id'], next=33, ike=ike)
6027 
6028         idx += 1
6029         if ctx['num'] == idx:
6030             logger.info("Test: Too small proposal length in SAi1")
6031             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6032                               0, 0, 7, 0, 0, 0, 0)
6033             return build_ike(ctx['id'], next=33, ike=ike)
6034 
6035         idx += 1
6036         if ctx['num'] == idx:
6037             logger.info("Test: Too large proposal length in SAi1")
6038             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6039                               0, 0, 9, 0, 0, 0, 0)
6040             return build_ike(ctx['id'], next=33, ike=ike)
6041 
6042         idx += 1
6043         if ctx['num'] == idx:
6044             logger.info("Test: Unexpected proposal type in SAi1")
6045             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6046                               1, 0, 8, 0, 0, 0, 0)
6047             return build_ike(ctx['id'], next=33, ike=ike)
6048 
6049         idx += 1
6050         if ctx['num'] == idx:
6051             logger.info("Test: Unexpected Protocol ID in SAi1")
6052             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6053                               0, 0, 8, 0, 0, 0, 0)
6054             return build_ike(ctx['id'], next=33, ike=ike)
6055 
6056         idx += 1
6057         if ctx['num'] == idx:
6058             logger.info("Test: Unexpected proposal number in SAi1")
6059             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6060                               0, 0, 8, 0, 1, 0, 0)
6061             return build_ike(ctx['id'], next=33, ike=ike)
6062 
6063         idx += 1
6064         if ctx['num'] == idx:
6065             logger.info("Test: Not enough room for SPI in SAi1")
6066             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6067                               0, 0, 8, 1, 1, 1, 0)
6068             return build_ike(ctx['id'], next=33, ike=ike)
6069 
6070         idx += 1
6071         if ctx['num'] == idx:
6072             logger.info("Test: Unexpected SPI in SAi1")
6073             ike = struct.pack(">BBHBBHBBBBB", 0, 0, 4 + 9,
6074                               0, 0, 9, 1, 1, 1, 0, 1)
6075             return build_ike(ctx['id'], next=33, ike=ike)
6076 
6077         idx += 1
6078         if ctx['num'] == idx:
6079             logger.info("Test: No transforms in SAi1")
6080             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6081                               0, 0, 8, 1, 1, 0, 0)
6082             return build_ike(ctx['id'], next=33, ike=ike)
6083 
6084         idx += 1
6085         if ctx['num'] == idx:
6086             logger.info("Test: Too short transform in SAi1")
6087             ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
6088                               0, 0, 8, 1, 1, 0, 1)
6089             return build_ike(ctx['id'], next=33, ike=ike)
6090 
6091         idx += 1
6092         if ctx['num'] == idx:
6093             logger.info("Test: Too small transform length in SAi1")
6094             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
6095                               0, 0, 8 + 8, 1, 1, 0, 1,
6096                               0, 0, 7, 0, 0, 0)
6097             return build_ike(ctx['id'], next=33, ike=ike)
6098 
6099         idx += 1
6100         if ctx['num'] == idx:
6101             logger.info("Test: Too large transform length in SAi1")
6102             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
6103                               0, 0, 8 + 8, 1, 1, 0, 1,
6104                               0, 0, 9, 0, 0, 0)
6105             return build_ike(ctx['id'], next=33, ike=ike)
6106 
6107         idx += 1
6108         if ctx['num'] == idx:
6109             logger.info("Test: Unexpected Transform type in SAi1")
6110             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
6111                               0, 0, 8 + 8, 1, 1, 0, 1,
6112                               1, 0, 8, 0, 0, 0)
6113             return build_ike(ctx['id'], next=33, ike=ike)
6114 
6115         idx += 1
6116         if ctx['num'] == idx:
6117             logger.info("Test: No transform attributes in SAi1")
6118             ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
6119                               0, 0, 8 + 8, 1, 1, 0, 1,
6120                               0, 0, 8, 0, 0, 0)
6121             return build_ike(ctx['id'], next=33, ike=ike)
6122 
6123         idx += 1
6124         if ctx['num'] == idx:
6125             logger.info("Test: No transform attr for AES and unexpected data after transforms in SAi1")
6126             tlen1 = 8 + 3
6127             tlen2 = 8 + 4
6128             tlen3 = 8 + 4
6129             tlen = tlen1 + tlen2 + tlen3
6130             ike = struct.pack(">BBHBBHBBBBBBHBBH3BBBHBBHHHBBHBBHHHB",
6131                               0, 0, 4 + 8 + tlen + 1,
6132                               0, 0, 8 + tlen + 1, 1, 1, 0, 3,
6133                               3, 0, tlen1, 1, 0, 12, 1, 2, 3,
6134                               3, 0, tlen2, 1, 0, 12, 0, 128,
6135                               0, 0, tlen3, 1, 0, 12, 0x8000 | 14, 127,
6136                               1)
6137             return build_ike(ctx['id'], next=33, ike=ike)
6138 
6139         def build_sa(next=0):
6140             tlen = 5 * 8
6141             return struct.pack(">BBHBBHBBBBBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
6142                                next, 0, 4 + 8 + tlen,
6143                                0, 0, 8 + tlen, 1, 1, 0, 5,
6144                                3, 0, 8, 1, 0, 3,
6145                                3, 0, 8, 2, 0, 1,
6146                                3, 0, 8, 3, 0, 1,
6147                                3, 0, 8, 4, 0, 5,
6148                                0, 0, 8, 241, 0, 0)
6149 
6150         idx += 1
6151         if ctx['num'] == idx:
6152             logger.info("Test: Valid proposal, but no KEi in SAi1")
6153             ike = build_sa()
6154             return build_ike(ctx['id'], next=33, ike=ike)
6155 
6156         idx += 1
6157         if ctx['num'] == idx:
6158             logger.info("Test: Empty KEi in SAi1")
6159             ike = build_sa(next=34) + struct.pack(">BBH", 0, 0, 4)
6160             return build_ike(ctx['id'], next=33, ike=ike)
6161 
6162         idx += 1
6163         if ctx['num'] == idx:
6164             logger.info("Test: Mismatch in DH Group in SAi1")
6165             ike = build_sa(next=34)
6166             ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 12345, 0)
6167             ike += 96*b'\x00'
6168             return build_ike(ctx['id'], next=33, ike=ike)
6169         idx += 1
6170         if ctx['num'] == idx:
6171             logger.info("Test: EAP-Failure")
6172             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6173 
6174         idx += 1
6175         if ctx['num'] == idx:
6176             logger.info("Test: Invalid DH public value length in SAi1")
6177             ike = build_sa(next=34)
6178             ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 5, 0)
6179             ike += 96*b'\x00'
6180             return build_ike(ctx['id'], next=33, ike=ike)
6181 
6182         def build_ke(next=0):
6183             ke = struct.pack(">BBHHH", next, 0, 4 + 4 + 192, 5, 0)
6184             ke += 191*b'\x00'+b'\x02'
6185             return ke
6186 
6187         idx += 1
6188         if ctx['num'] == idx:
6189             logger.info("Test: Valid proposal and KEi, but no Ni in SAi1")
6190             ike = build_sa(next=34)
6191             ike += build_ke()
6192             return build_ike(ctx['id'], next=33, ike=ike)
6193 
6194         idx += 1
6195         if ctx['num'] == idx:
6196             logger.info("Test: Too short Ni in SAi1")
6197             ike = build_sa(next=34)
6198             ike += build_ke(next=40)
6199             ike += struct.pack(">BBH", 0, 0, 4)
6200             return build_ike(ctx['id'], next=33, ike=ike)
6201 
6202         idx += 1
6203         if ctx['num'] == idx:
6204             logger.info("Test: Too long Ni in SAi1")
6205             ike = build_sa(next=34)
6206             ike += build_ke(next=40)
6207             ike += struct.pack(">BBH", 0, 0, 4 + 257) + 257*b'\x00'
6208             return build_ike(ctx['id'], next=33, ike=ike)
6209 
6210         def build_ni(next=0):
6211             return struct.pack(">BBH", next, 0, 4 + 256) + 256*b'\x00'
6212 
6213         def build_sai1(id):
6214             ike = build_sa(next=34)
6215             ike += build_ke(next=40)
6216             ike += build_ni()
6217             return build_ike(ctx['id'], next=33, ike=ike)
6218 
6219         idx += 1
6220         if ctx['num'] == idx:
6221             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
6222             return build_sai1(ctx['id'])
6223         idx += 1
6224         if ctx['num'] == idx:
6225             logger.info("Test: EAP-Failure")
6226             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6227 
6228         idx += 1
6229         if ctx['num'] == idx:
6230             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
6231             return build_sai1(ctx['id'])
6232         idx += 1
6233         if ctx['num'] == idx:
6234             logger.info("Test: No integrity checksum")
6235             ike = b''
6236             return build_ike(ctx['id'], next=37, ike=ike)
6237 
6238         idx += 1
6239         if ctx['num'] == idx:
6240             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
6241             return build_sai1(ctx['id'])
6242         idx += 1
6243         if ctx['num'] == idx:
6244             logger.info("Test: Truncated integrity checksum")
6245             return struct.pack(">BBHBB",
6246                                EAP_CODE_REQUEST, ctx['id'],
6247                                4 + 1 + 1,
6248                                EAP_TYPE_IKEV2, 0x20)
6249 
6250         idx += 1
6251         if ctx['num'] == idx:
6252             logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
6253             return build_sai1(ctx['id'])
6254         idx += 1
6255         if ctx['num'] == idx:
6256             logger.info("Test: Invalid integrity checksum")
6257             ike = b''
6258             return build_ike(ctx['id'], next=37, flags=0x20, ike=ike)
6259 
6260         idx += 1
6261         if ctx['num'] == idx:
6262             logger.info("No more test responses available - test case completed")
6263             global eap_proto_ikev2_test_done
6264             eap_proto_ikev2_test_done = True
6265             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6266                                4 + 1,
6267                                EAP_TYPE_IKEV2)
6268         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6269 
6270     srv = start_radius_server(ikev2_handler)
6271 
6272     try:
6273         hapd = start_ap(apdev[0])
6274         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
6275 
6276         i = 0
6277         while not eap_proto_ikev2_test_done:
6278             i += 1
6279             logger.info("Running connection iteration %d" % i)
6280             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6281                            eap="IKEV2", identity="user",
6282                            password="password",
6283                            wait_connect=False)
6284             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
6285             if ev is None:
6286                 raise Exception("Timeout on EAP start")
6287             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6288                                    timeout=15)
6289             if ev is None:
6290                 raise Exception("Timeout on EAP method start")
6291             if i in [41, 46]:
6292                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
6293                                        timeout=10)
6294                 if ev is None:
6295                     raise Exception("Timeout on EAP failure")
6296             else:
6297                 time.sleep(0.05)
6298             dev[0].request("REMOVE_NETWORK all")
6299             dev[0].wait_disconnected()
6300             dev[0].dump_monitor()
6301             dev[1].dump_monitor()
6302             dev[2].dump_monitor()
6303     finally:
6304         stop_radius_server(srv)
6305 
6306 def NtPasswordHash(password):
6307     pw = password.encode('utf_16_le')
6308     return hashlib.new('md4', pw).digest()
6309 
6310 def HashNtPasswordHash(password_hash):
6311     return hashlib.new('md4', password_hash).digest()
6312 
6313 def ChallengeHash(peer_challenge, auth_challenge, username):
6314     data = peer_challenge + auth_challenge + username
6315     return hashlib.sha1(data).digest()[0:8]
6316 
6317 def GenerateAuthenticatorResponse(password, nt_response, peer_challenge,
6318                                   auth_challenge, username):
6319     magic1 = binascii.unhexlify("4D616769632073657276657220746F20636C69656E74207369676E696E6720636F6E7374616E74")
6320     magic2 = binascii.unhexlify("50616420746F206D616B6520697420646F206D6F7265207468616E206F6E6520697465726174696F6E")
6321 
6322     password_hash = NtPasswordHash(password)
6323     password_hash_hash = HashNtPasswordHash(password_hash)
6324     data = password_hash_hash + nt_response + magic1
6325     digest = hashlib.sha1(data).digest()
6326 
6327     challenge = ChallengeHash(peer_challenge, auth_challenge, username.encode())
6328 
6329     data = digest + challenge + magic2
6330     resp = hashlib.sha1(data).digest()
6331     return resp
6332 
6333 def test_eap_proto_ikev2_errors(dev, apdev):
6334     """EAP-IKEv2 local error cases"""
6335     check_eap_capa(dev[0], "IKEV2")
6336     params = hostapd.wpa2_eap_params(ssid="eap-test")
6337     hapd = hostapd.add_ap(apdev[0], params)
6338     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
6339 
6340     for i in range(1, 5):
6341         with alloc_fail(dev[0], i, "eap_ikev2_init"):
6342             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6343                            eap="IKEV2", identity="ikev2 user",
6344                            password="ike password",
6345                            wait_connect=False)
6346             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
6347                                    timeout=15)
6348             if ev is None:
6349                 raise Exception("Timeout on EAP start")
6350             dev[0].request("REMOVE_NETWORK all")
6351             dev[0].wait_disconnected()
6352 
6353     tests = [(1, "ikev2_encr_encrypt"),
6354              (1, "ikev2_encr_decrypt"),
6355              (1, "ikev2_derive_auth_data"),
6356              (2, "ikev2_derive_auth_data"),
6357              (1, "=ikev2_decrypt_payload"),
6358              (1, "ikev2_encr_decrypt;ikev2_decrypt_payload"),
6359              (1, "ikev2_encr_encrypt;ikev2_build_encrypted"),
6360              (1, "ikev2_derive_sk_keys"),
6361              (2, "ikev2_derive_sk_keys"),
6362              (3, "ikev2_derive_sk_keys"),
6363              (4, "ikev2_derive_sk_keys"),
6364              (5, "ikev2_derive_sk_keys"),
6365              (6, "ikev2_derive_sk_keys"),
6366              (7, "ikev2_derive_sk_keys"),
6367              (8, "ikev2_derive_sk_keys"),
6368              (1, "eap_ikev2_derive_keymat;eap_ikev2_peer_keymat"),
6369              (1, "eap_msg_alloc;eap_ikev2_build_msg"),
6370              (1, "eap_ikev2_getKey"),
6371              (1, "eap_ikev2_get_emsk"),
6372              (1, "eap_ikev2_get_session_id"),
6373              (1, "=ikev2_derive_keys"),
6374              (2, "=ikev2_derive_keys"),
6375              (1, "wpabuf_alloc;ikev2_process_kei"),
6376              (1, "=ikev2_process_idi"),
6377              (1, "ikev2_derive_auth_data;ikev2_build_auth"),
6378              (1, "wpabuf_alloc;ikev2_build_sa_init"),
6379              (2, "wpabuf_alloc;ikev2_build_sa_init"),
6380              (3, "wpabuf_alloc;ikev2_build_sa_init"),
6381              (4, "wpabuf_alloc;ikev2_build_sa_init"),
6382              (5, "wpabuf_alloc;ikev2_build_sa_init"),
6383              (6, "wpabuf_alloc;ikev2_build_sa_init"),
6384              (1, "wpabuf_alloc;ikev2_build_sa_auth"),
6385              (2, "wpabuf_alloc;ikev2_build_sa_auth"),
6386              (1, "ikev2_build_auth;ikev2_build_sa_auth")]
6387     for count, func in tests:
6388         with alloc_fail(dev[0], count, func):
6389             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6390                            eap="IKEV2", identity="ikev2 user@domain",
6391                            password="ike password", erp="1", wait_connect=False)
6392             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6393                                    timeout=15)
6394             if ev is None:
6395                 raise Exception("Timeout on EAP start")
6396             ok = False
6397             for j in range(10):
6398                 state = dev[0].request('GET_ALLOC_FAIL')
6399                 if state.startswith('0:'):
6400                     ok = True
6401                     break
6402                 time.sleep(0.1)
6403             if not ok:
6404                 raise Exception("No allocation failure seen for %d:%s" % (count, func))
6405             dev[0].request("REMOVE_NETWORK all")
6406             dev[0].wait_disconnected()
6407 
6408     tests = [(1, "wpabuf_alloc;ikev2_build_notify"),
6409              (2, "wpabuf_alloc;ikev2_build_notify"),
6410              (1, "ikev2_build_encrypted;ikev2_build_notify")]
6411     for count, func in tests:
6412         with alloc_fail(dev[0], count, func):
6413             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6414                            eap="IKEV2", identity="ikev2 user",
6415                            password="wrong password", erp="1",
6416                            wait_connect=False)
6417             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6418                                    timeout=15)
6419             if ev is None:
6420                 raise Exception("Timeout on EAP start")
6421             ok = False
6422             for j in range(10):
6423                 state = dev[0].request('GET_ALLOC_FAIL')
6424                 if state.startswith('0:'):
6425                     ok = True
6426                     break
6427                 time.sleep(0.1)
6428             if not ok:
6429                 raise Exception("No allocation failure seen for %d:%s" % (count, func))
6430             dev[0].request("REMOVE_NETWORK all")
6431             dev[0].wait_disconnected()
6432 
6433     tests = [(1, "ikev2_integ_hash"),
6434              (1, "ikev2_integ_hash;ikev2_decrypt_payload"),
6435              (1, "os_get_random;ikev2_build_encrypted"),
6436              (1, "ikev2_prf_plus;ikev2_derive_sk_keys"),
6437              (1, "eap_ikev2_derive_keymat;eap_ikev2_peer_keymat"),
6438              (1, "os_get_random;ikev2_build_sa_init"),
6439              (2, "os_get_random;ikev2_build_sa_init"),
6440              (1, "ikev2_integ_hash;eap_ikev2_validate_icv"),
6441              (1, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_keys"),
6442              (1, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data"),
6443              (2, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data"),
6444              (3, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data")]
6445     for count, func in tests:
6446         with fail_test(dev[0], count, func):
6447             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
6448                            eap="IKEV2", identity="ikev2 user",
6449                            password="ike password", wait_connect=False)
6450             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6451                                    timeout=15)
6452             if ev is None:
6453                 raise Exception("Timeout on EAP start")
6454             ok = False
6455             for j in range(10):
6456                 state = dev[0].request('GET_FAIL')
6457                 if state.startswith('0:'):
6458                     ok = True
6459                     break
6460                 time.sleep(0.1)
6461             if not ok:
6462                 raise Exception("No failure seen for %d:%s" % (count, func))
6463             dev[0].request("REMOVE_NETWORK all")
6464             dev[0].wait_disconnected()
6465 
6466     params = {"ssid": "eap-test2", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
6467               "rsn_pairwise": "CCMP", "ieee8021x": "1",
6468               "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
6469               "fragment_size": "50"}
6470     hapd2 = hostapd.add_ap(apdev[1], params)
6471     dev[0].scan_for_bss(hapd2.own_addr(), freq=2412)
6472 
6473     tests = [(1, "eap_ikev2_build_frag_ack"),
6474              (1, "wpabuf_alloc;eap_ikev2_process_fragment")]
6475     for count, func in tests:
6476         with alloc_fail(dev[0], count, func):
6477             dev[0].connect("eap-test2", key_mgmt="WPA-EAP", scan_freq="2412",
6478                            eap="IKEV2", identity="ikev2 user",
6479                            password="ike password", erp="1", wait_connect=False)
6480             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
6481                                    timeout=15)
6482             if ev is None:
6483                 raise Exception("Timeout on EAP start")
6484             ok = False
6485             for j in range(10):
6486                 state = dev[0].request('GET_ALLOC_FAIL')
6487                 if state.startswith('0:'):
6488                     ok = True
6489                     break
6490                 time.sleep(0.1)
6491             if not ok:
6492                 raise Exception("No allocation failure seen for %d:%s" % (count, func))
6493             dev[0].request("REMOVE_NETWORK all")
6494             dev[0].wait_disconnected()
6495 
6496 def run_eap_ikev2_connect(dev):
6497     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
6498                 eap="IKEV2", identity="ikev2 user",
6499                 password="ike password",
6500                 fragment_size="30", wait_connect=False)
6501     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
6502                          "CTRL-EVENT-DISCONNECTED"],
6503                         timeout=1)
6504     dev.request("REMOVE_NETWORK all")
6505     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
6506         dev.wait_disconnected()
6507     ev = dev.wait_event(["CTRL-EVENT-NETWORK-REMOVED"], timeout=1)
6508     if ev is None:
6509         raise Exception("Network removal not reported")
6510     time.sleep(0.01)
6511     dev.dump_monitor()
6512 
6513 def test_eap_proto_ikev2_errors_server(dev, apdev):
6514     """EAP-IKEV2 local error cases on server"""
6515     check_eap_capa(dev[0], "IKEV2")
6516     params = int_eap_server_params()
6517     params['erp_domain'] = 'example.com'
6518     params['eap_server_erp'] = '1'
6519     hapd = hostapd.add_ap(apdev[0], params)
6520     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
6521 
6522     tests = [(1, "eap_ikev2_init"),
6523              (2, "=eap_ikev2_init"),
6524              (3, "=eap_ikev2_init"),
6525              (1, "eap_msg_alloc;eap_ikev2_build_msg"),
6526              (1, "ikev2_initiator_build;eap_ikev2_buildReq"),
6527              (1, "eap_ikev2_process_fragment"),
6528              (1, "wpabuf_alloc_copy;ikev2_process_ker"),
6529              (1, "ikev2_process_idr"),
6530              (1, "ikev2_derive_auth_data;ikev2_process_auth_secret"),
6531              (1, "ikev2_decrypt_payload;ikev2_process_sa_auth"),
6532              (1, "ikev2_process_sa_auth_decrypted;ikev2_process_sa_auth"),
6533              (1, "dh_init;ikev2_build_kei"),
6534              (1, "ikev2_build_auth"),
6535              (1, "wpabuf_alloc;ikev2_build_sa_init"),
6536              (1, "ikev2_build_sa_auth"),
6537              (1, "=ikev2_build_sa_auth"),
6538              (2, "=ikev2_derive_auth_data"),
6539              (1, "wpabuf_alloc;ikev2_build_sa_auth"),
6540              (2, "wpabuf_alloc;=ikev2_build_sa_auth"),
6541              (1, "ikev2_decrypt_payload;ikev2_process_sa_init_encr"),
6542              (1, "dh_derive_shared;ikev2_derive_keys"),
6543              (1, "=ikev2_derive_keys"),
6544              (2, "=ikev2_derive_keys"),
6545              (1, "eap_ikev2_getKey"),
6546              (1, "eap_ikev2_get_emsk"),
6547              (1, "eap_ikev2_get_session_id")]
6548     for count, func in tests:
6549         with alloc_fail(hapd, count, func):
6550             run_eap_ikev2_connect(dev[0])
6551 
6552     tests = [(1, "eap_ikev2_validate_icv;eap_ikev2_process_icv"),
6553              (1, "eap_ikev2_server_keymat"),
6554              (1, "ikev2_build_auth"),
6555              (1, "os_get_random;ikev2_build_sa_init"),
6556              (2, "os_get_random;ikev2_build_sa_init"),
6557              (1, "ikev2_derive_keys"),
6558              (2, "ikev2_derive_keys"),
6559              (3, "ikev2_derive_keys"),
6560              (4, "ikev2_derive_keys"),
6561              (5, "ikev2_derive_keys"),
6562              (6, "ikev2_derive_keys"),
6563              (7, "ikev2_derive_keys"),
6564              (8, "ikev2_derive_keys"),
6565              (1, "ikev2_decrypt_payload;ikev2_process_sa_auth"),
6566              (1, "eap_ikev2_process_icv;eap_ikev2_process")]
6567     for count, func in tests:
6568         with fail_test(hapd, count, func):
6569             run_eap_ikev2_connect(dev[0])
6570 
6571 def start_ikev2_assoc(dev, hapd):
6572     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
6573                 eap="IKEV2", identity="ikev2 user",
6574                 password="ike password", wait_connect=False)
6575     proxy_msg(hapd, dev) # EAP-Identity/Request
6576     proxy_msg(dev, hapd) # EAP-Identity/Response
6577     proxy_msg(hapd, dev) # IKEV2 1
6578 
6579 def stop_ikev2_assoc(dev, hapd):
6580     dev.request("REMOVE_NETWORK all")
6581     dev.wait_disconnected()
6582     dev.dump_monitor()
6583     hapd.dump_monitor()
6584 
6585 def test_eap_proto_ikev2_server(dev, apdev):
6586     """EAP-IKEV2 protocol testing for the server"""
6587     check_eap_capa(dev[0], "IKEV2")
6588     params = int_eap_server_params()
6589     params['erp_domain'] = 'example.com'
6590     params['eap_server_erp'] = '1'
6591     hapd = hostapd.add_ap(apdev[0], params)
6592     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
6593     hapd.request("SET ext_eapol_frame_io 1")
6594     dev[0].request("SET ext_eapol_frame_io 1")
6595 
6596     # Successful exchange to verify proxying mechanism
6597     start_ikev2_assoc(dev[0], hapd)
6598     proxy_msg(dev[0], hapd) # IKEV2 2
6599     proxy_msg(hapd, dev[0]) # IKEV2 3
6600     proxy_msg(dev[0], hapd) # IKEV2 4
6601     proxy_msg(hapd, dev[0]) # EAP-Success
6602     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 1/4
6603     proxy_msg(dev[0], hapd) # EAPOL-Key msg 2/4
6604     proxy_msg(hapd, dev[0]) # EAPOL-Key msg 3/4
6605     proxy_msg(dev[0], hapd) # EAPOL-Key msg 4/4
6606     dev[0].wait_connected()
6607     stop_ikev2_assoc(dev[0], hapd)
6608 
6609     start_ikev2_assoc(dev[0], hapd)
6610     resp = rx_msg(dev[0])
6611     # Too short EAP-IKEV2 header
6612     hapd.note("IKEV2: Too short frame to include HDR")
6613     msg = resp[0:4] + "0005" + resp[8:12] + "0005" + "31"
6614     tx_msg(dev[0], hapd, msg)
6615     rx_msg(hapd)
6616     stop_ikev2_assoc(dev[0], hapd)
6617 
6618     start_ikev2_assoc(dev[0], hapd)
6619     resp = rx_msg(dev[0])
6620     # Too short EAP-IKEV2 header - missing Message Length field
6621     hapd.note("EAP-IKEV2: Message underflow")
6622     msg = resp[0:4] + "0006" + resp[8:12] + "0006" + "3180"
6623     tx_msg(dev[0], hapd, msg)
6624     rx_msg(hapd)
6625     stop_ikev2_assoc(dev[0], hapd)
6626 
6627     start_ikev2_assoc(dev[0], hapd)
6628     resp = rx_msg(dev[0])
6629     # Too short EAP-IKEV2 header - too small Message Length
6630     hapd.note("EAP-IKEV2: Invalid Message Length (0; 1 remaining in this msg)")
6631     msg = resp[0:4] + "000b" + resp[8:12] + "000b" + "318000000000ff"
6632     tx_msg(dev[0], hapd, msg)
6633     rx_msg(hapd)
6634     stop_ikev2_assoc(dev[0], hapd)
6635 
6636     start_ikev2_assoc(dev[0], hapd)
6637     resp = rx_msg(dev[0])
6638     # Too short EAP-IKEV2 header - too large Message Length
6639     hapd.note("EAP-IKEV2: Ignore too long message")
6640     msg = resp[0:4] + "000b" + resp[8:12] + "000b" + "31c0bbccddeeff"
6641     tx_msg(dev[0], hapd, msg)
6642     rx_msg(hapd)
6643     stop_ikev2_assoc(dev[0], hapd)
6644 
6645     start_ikev2_assoc(dev[0], hapd)
6646     resp = rx_msg(dev[0])
6647     # No Message Length in first fragment
6648     hapd.note("EAP-IKEV2: No Message Length field in a fragmented packet")
6649     msg = resp[0:4] + "0007" + resp[8:12] + "0007" + "3140ff"
6650     tx_msg(dev[0], hapd, msg)
6651     rx_msg(hapd)
6652     stop_ikev2_assoc(dev[0], hapd)
6653 
6654     start_ikev2_assoc(dev[0], hapd)
6655     resp = rx_msg(dev[0])
6656     # First fragment (valid)
6657     hapd.note("EAP-IKEV2: Received 1 bytes in first fragment, waiting for 255 bytes more")
6658     msg = resp[0:4] + "000b" + resp[8:12] + "000b" + "31c000000100ff"
6659     tx_msg(dev[0], hapd, msg)
6660     req = rx_msg(hapd)
6661     id, = struct.unpack('B', binascii.unhexlify(req)[5:6])
6662     hapd.note("EAP-IKEV2: Received 1 bytes in first fragment, waiting for 254 bytes more")
6663     payload = struct.pack('BBB', 49, 0x40, 0)
6664     msg = struct.pack('>BBHBBH', 1, 0, 4 + len(payload), 2, id, 4 + len(payload)) + payload
6665     tx_msg(dev[0], hapd, binascii.hexlify(msg).decode())
6666     req = rx_msg(hapd)
6667     id, = struct.unpack('B', binascii.unhexlify(req)[5:6])
6668     hapd.note("EAP-IKEV2: Fragment overflow")
6669     payload = struct.pack('BB', 49, 0x40) + 255*b'\x00'
6670     msg = struct.pack('>BBHBBH', 1, 0, 4 + len(payload), 2, id, 4 + len(payload)) + payload
6671     tx_msg(dev[0], hapd, binascii.hexlify(msg).decode())
6672     rx_msg(hapd)
6673     stop_ikev2_assoc(dev[0], hapd)
6674 
6675     start_ikev2_assoc(dev[0], hapd)
6676     proxy_msg(dev[0], hapd) # IKEV2 2
6677     req = proxy_msg(hapd, dev[0]) # IKEV2 3
6678     id, = struct.unpack('B', binascii.unhexlify(req)[5:6])
6679     # Missing ICV
6680     hapd.note("EAP-IKEV2: The message should have included integrity checksum")
6681     payload = struct.pack('BB', 49, 0) + b'\x00'
6682     msg = struct.pack('>BBHBBH', 1, 0, 4 + len(payload), 2, id, 4 + len(payload)) + payload
6683     tx_msg(dev[0], hapd, binascii.hexlify(msg).decode())
6684     rx_msg(hapd)
6685     stop_ikev2_assoc(dev[0], hapd)
6686 
6687     tests = [("Unsupported HDR version 0x0 (expected 0x20)",
6688               struct.pack('BB', 49, 0) + 16*b'\x00' +
6689               struct.pack('>BBBBLL', 0, 0, 0, 0, 0, 0)),
6690              ("IKEV2: Invalid length (HDR: 0 != RX: 28)",
6691               struct.pack('BB', 49, 0) + 16*b'\x00' +
6692               struct.pack('>BBBBLL', 0, 0x20, 0, 0, 0, 0)),
6693              ("IKEV2: Unexpected Exchange Type 0 in SA_INIT state",
6694               struct.pack('BB', 49, 0) + 16*b'\x00' +
6695               struct.pack('>BBBBLL', 0, 0x20, 0, 0, 0, 28)),
6696              ("IKEV2: Unexpected Flags value 0x0",
6697               struct.pack('BB', 49, 0) + 16*b'\x00' +
6698               struct.pack('>BBBBLL', 0, 0x20, 34, 0, 0, 28)),
6699              ("IKEV2: SAr1 not received",
6700               struct.pack('BB', 49, 0) + 16*b'\x00' +
6701               struct.pack('>BBBBLL', 0, 0x20, 34, 0x20, 0, 28))]
6702     for txt, payload in tests:
6703         start_ikev2_assoc(dev[0], hapd)
6704         resp = rx_msg(dev[0])
6705         id, = struct.unpack('B', binascii.unhexlify(resp)[5:6])
6706         hapd.note(txt)
6707         msg = struct.pack('>BBHBBH', 1, 0, 4 + len(payload), 2, id, 4 + len(payload)) + payload
6708         tx_msg(dev[0], hapd, binascii.hexlify(msg).decode())
6709         rx_msg(hapd)
6710         stop_ikev2_assoc(dev[0], hapd)
6711 
6712 def test_eap_proto_mschapv2(dev, apdev):
6713     """EAP-MSCHAPv2 protocol tests"""
6714     check_eap_capa(dev[0], "MSCHAPV2")
6715 
6716     def mschapv2_handler(ctx, req):
6717         logger.info("mschapv2_handler - RX " + binascii.hexlify(req).decode())
6718         if 'num' not in ctx:
6719             ctx['num'] = 0
6720         ctx['num'] = ctx['num'] + 1
6721         if 'id' not in ctx:
6722             ctx['id'] = 1
6723         ctx['id'] = (ctx['id'] + 1) % 256
6724         idx = 0
6725 
6726         idx += 1
6727         if ctx['num'] == idx:
6728             logger.info("Test: Missing payload")
6729             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
6730                                4 + 1,
6731                                EAP_TYPE_MSCHAPV2)
6732 
6733         idx += 1
6734         if ctx['num'] == idx:
6735             logger.info("Test: Unknown MSCHAPv2 op_code")
6736             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6737                                4 + 1 + 4 + 1,
6738                                EAP_TYPE_MSCHAPV2,
6739                                0, 0, 5, 0)
6740 
6741         idx += 1
6742         if ctx['num'] == idx:
6743             logger.info("Test: Invalid ms_len and unknown MSCHAPv2 op_code")
6744             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6745                                4 + 1 + 4 + 1,
6746                                EAP_TYPE_MSCHAPV2,
6747                                255, 0, 0, 0)
6748 
6749         idx += 1
6750         if ctx['num'] == idx:
6751             logger.info("Test: Success before challenge")
6752             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6753                                4 + 1 + 4 + 1,
6754                                EAP_TYPE_MSCHAPV2,
6755                                3, 0, 5, 0)
6756 
6757         idx += 1
6758         if ctx['num'] == idx:
6759             logger.info("Test: Failure before challenge - required challenge field not present")
6760             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6761                                4 + 1 + 4 + 1,
6762                                EAP_TYPE_MSCHAPV2,
6763                                4, 0, 5, 0)
6764         idx += 1
6765         if ctx['num'] == idx:
6766             logger.info("Test: Failure")
6767             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6768 
6769         idx += 1
6770         if ctx['num'] == idx:
6771             logger.info("Test: Failure before challenge - invalid failure challenge len")
6772             payload = b'C=12'
6773             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6774                                4 + 1 + 4 + len(payload),
6775                                EAP_TYPE_MSCHAPV2,
6776                                4, 0, 4 + len(payload)) + payload
6777         idx += 1
6778         if ctx['num'] == idx:
6779             logger.info("Test: Failure")
6780             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6781 
6782         idx += 1
6783         if ctx['num'] == idx:
6784             logger.info("Test: Failure before challenge - invalid failure challenge len")
6785             payload = b'C=12 V=3'
6786             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6787                                4 + 1 + 4 + len(payload),
6788                                EAP_TYPE_MSCHAPV2,
6789                                4, 0, 4 + len(payload)) + payload
6790         idx += 1
6791         if ctx['num'] == idx:
6792             logger.info("Test: Failure")
6793             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6794 
6795         idx += 1
6796         if ctx['num'] == idx:
6797             logger.info("Test: Failure before challenge - invalid failure challenge")
6798             payload = b'C=00112233445566778899aabbccddeefQ '
6799             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6800                                4 + 1 + 4 + len(payload),
6801                                EAP_TYPE_MSCHAPV2,
6802                                4, 0, 4 + len(payload)) + payload
6803         idx += 1
6804         if ctx['num'] == idx:
6805             logger.info("Test: Failure")
6806             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6807 
6808         idx += 1
6809         if ctx['num'] == idx:
6810             logger.info("Test: Failure before challenge - password expired")
6811             payload = b'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
6812             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6813                                4 + 1 + 4 + len(payload),
6814                                EAP_TYPE_MSCHAPV2,
6815                                4, 0, 4 + len(payload)) + payload
6816         idx += 1
6817         if ctx['num'] == idx:
6818             logger.info("Test: Success after password change")
6819             payload = b"S=1122334455667788990011223344556677889900"
6820             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6821                                4 + 1 + 4 + len(payload),
6822                                EAP_TYPE_MSCHAPV2,
6823                                3, 0, 4 + len(payload)) + payload
6824 
6825         idx += 1
6826         if ctx['num'] == idx:
6827             logger.info("Test: Invalid challenge length")
6828             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6829                                4 + 1 + 4 + 1,
6830                                EAP_TYPE_MSCHAPV2,
6831                                1, 0, 4 + 1, 0)
6832 
6833         idx += 1
6834         if ctx['num'] == idx:
6835             logger.info("Test: Too short challenge packet")
6836             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6837                                4 + 1 + 4 + 1,
6838                                EAP_TYPE_MSCHAPV2,
6839                                1, 0, 4 + 1, 16)
6840 
6841         idx += 1
6842         if ctx['num'] == idx:
6843             logger.info("Test: Challenge")
6844             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6845                                4 + 1 + 4 + 1 + 16 + 6,
6846                                EAP_TYPE_MSCHAPV2,
6847                                1, 0, 4 + 1 + 16 + 6, 16) + 16*b'A' + b'foobar'
6848         idx += 1
6849         if ctx['num'] == idx:
6850             logger.info("Test: Failure - password expired")
6851             payload = b'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
6852             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6853                                4 + 1 + 4 + len(payload),
6854                                EAP_TYPE_MSCHAPV2,
6855                                4, 0, 4 + len(payload)) + payload
6856         idx += 1
6857         if ctx['num'] == idx:
6858             logger.info("Test: Success after password change")
6859             if len(req) != 591:
6860                 logger.info("Unexpected Change-Password packet length: %s" % len(req))
6861                 return None
6862             data = req[9:]
6863             enc_pw = data[0:516]
6864             data = data[516:]
6865             enc_hash = data[0:16]
6866             data = data[16:]
6867             peer_challenge = data[0:16]
6868             data = data[16:]
6869             # Reserved
6870             data = data[8:]
6871             nt_response = data[0:24]
6872             data = data[24:]
6873             flags = data
6874             logger.info("enc_hash: " + binascii.hexlify(enc_hash).decode())
6875             logger.info("peer_challenge: " + binascii.hexlify(peer_challenge).decode())
6876             logger.info("nt_response: " + binascii.hexlify(nt_response).decode())
6877             logger.info("flags: " + binascii.hexlify(flags).decode())
6878 
6879             auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
6880             logger.info("auth_challenge: " + binascii.hexlify(auth_challenge).decode())
6881 
6882             auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
6883                                                       peer_challenge,
6884                                                       auth_challenge, "user")
6885             payload = b"S=" + binascii.hexlify(auth_resp).decode().upper().encode()
6886             logger.info("Success message payload: " + payload.decode())
6887             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6888                                4 + 1 + 4 + len(payload),
6889                                EAP_TYPE_MSCHAPV2,
6890                                3, 0, 4 + len(payload)) + payload
6891         idx += 1
6892         if ctx['num'] == idx:
6893             logger.info("Test: EAP-Success")
6894             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
6895 
6896         idx += 1
6897         if ctx['num'] == idx:
6898             logger.info("Test: Failure - password expired")
6899             payload = b'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
6900             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6901                                4 + 1 + 4 + len(payload),
6902                                EAP_TYPE_MSCHAPV2,
6903                                4, 0, 4 + len(payload)) + payload
6904         idx += 1
6905         if ctx['num'] == idx:
6906             logger.info("Test: Success after password change")
6907             if len(req) != 591:
6908                 logger.info("Unexpected Change-Password packet length: %s" % len(req))
6909                 return None
6910             data = req[9:]
6911             enc_pw = data[0:516]
6912             data = data[516:]
6913             enc_hash = data[0:16]
6914             data = data[16:]
6915             peer_challenge = data[0:16]
6916             data = data[16:]
6917             # Reserved
6918             data = data[8:]
6919             nt_response = data[0:24]
6920             data = data[24:]
6921             flags = data
6922             logger.info("enc_hash: " + binascii.hexlify(enc_hash).decode())
6923             logger.info("peer_challenge: " + binascii.hexlify(peer_challenge).decode())
6924             logger.info("nt_response: " + binascii.hexlify(nt_response).decode())
6925             logger.info("flags: " + binascii.hexlify(flags).decode())
6926 
6927             auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
6928             logger.info("auth_challenge: " + binascii.hexlify(auth_challenge).decode())
6929 
6930             auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
6931                                                       peer_challenge,
6932                                                       auth_challenge, "user")
6933             payload = b"S=" + binascii.hexlify(auth_resp).decode().upper().encode()
6934             logger.info("Success message payload: " + payload.decode())
6935             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6936                                4 + 1 + 4 + len(payload),
6937                                EAP_TYPE_MSCHAPV2,
6938                                3, 0, 4 + len(payload)) + payload
6939         idx += 1
6940         if ctx['num'] == idx:
6941             logger.info("Test: EAP-Success")
6942             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
6943 
6944         idx += 1
6945         if ctx['num'] == idx:
6946             logger.info("Test: Challenge")
6947             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6948                                4 + 1 + 4 + 1 + 16 + 6,
6949                                EAP_TYPE_MSCHAPV2,
6950                                1, 0, 4 + 1 + 16 + 6, 16) + 16*b'A' + b'foobar'
6951         idx += 1
6952         if ctx['num'] == idx:
6953             logger.info("Test: Failure - authentication failure")
6954             payload = b'E=691 R=1 C=00112233445566778899aabbccddeeff V=3 M=Authentication failed'
6955             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6956                                4 + 1 + 4 + len(payload),
6957                                EAP_TYPE_MSCHAPV2,
6958                                4, 0, 4 + len(payload)) + payload
6959 
6960         idx += 1
6961         if ctx['num'] == idx:
6962             logger.info("Test: Challenge")
6963             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6964                                4 + 1 + 4 + 1 + 16 + 6,
6965                                EAP_TYPE_MSCHAPV2,
6966                                1, 0, 4 + 1 + 16 + 6, 16) + 16*b'A' + b'foobar'
6967         idx += 1
6968         if ctx['num'] == idx:
6969             logger.info("Test: Failure - authentication failure")
6970             payload = b'E=691 R=1 C=00112233445566778899aabbccddeeff V=3 M=Authentication failed (2)'
6971             return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
6972                                4 + 1 + 4 + len(payload),
6973                                EAP_TYPE_MSCHAPV2,
6974                                4, 0, 4 + len(payload)) + payload
6975         idx += 1
6976         if ctx['num'] == idx:
6977             logger.info("Test: Failure")
6978             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
6979 
6980         idx += 1
6981         if ctx['num'] == idx:
6982             logger.info("Test: Challenge - invalid ms_len and workaround disabled")
6983             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
6984                                4 + 1 + 4 + 1 + 16 + 6,
6985                                EAP_TYPE_MSCHAPV2,
6986                                1, 0, 4 + 1 + 16 + 6 + 1, 16) + 16*b'A' + b'foobar'
6987 
6988         return None
6989 
6990     srv = start_radius_server(mschapv2_handler)
6991 
6992     try:
6993         hapd = start_ap(apdev[0])
6994         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
6995 
6996         for i in range(0, 16):
6997             logger.info("RUN: %d" % i)
6998             if i == 12:
6999                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7000                                eap="MSCHAPV2", identity="user",
7001                                password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
7002                                wait_connect=False)
7003             elif i == 14:
7004                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7005                                eap="MSCHAPV2", identity="user",
7006                                phase2="mschapv2_retry=0",
7007                                password="password", wait_connect=False)
7008             elif i == 15:
7009                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7010                                eap="MSCHAPV2", identity="user",
7011                                eap_workaround="0",
7012                                password="password", wait_connect=False)
7013             else:
7014                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7015                                eap="MSCHAPV2", identity="user",
7016                                password="password", wait_connect=False)
7017             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
7018             if ev is None:
7019                 raise Exception("Timeout on EAP start")
7020 
7021             if i in [8, 11, 12]:
7022                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"],
7023                                        timeout=10)
7024                 if ev is None:
7025                     raise Exception("Timeout on new password request")
7026                 id = ev.split(':')[0].split('-')[-1]
7027                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
7028                 if i in [11, 12]:
7029                     ev = dev[0].wait_event(["CTRL-EVENT-PASSWORD-CHANGED"],
7030                                        timeout=10)
7031                     if ev is None:
7032                         raise Exception("Timeout on password change")
7033                     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"],
7034                                        timeout=10)
7035                     if ev is None:
7036                         raise Exception("Timeout on EAP success")
7037                 else:
7038                     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
7039                                            timeout=10)
7040                     if ev is None:
7041                         raise Exception("Timeout on EAP failure")
7042 
7043             if i in [13]:
7044                 ev = dev[0].wait_event(["CTRL-REQ-IDENTITY"],
7045                                        timeout=10)
7046                 if ev is None:
7047                     raise Exception("Timeout on identity request")
7048                 id = ev.split(':')[0].split('-')[-1]
7049                 dev[0].request("CTRL-RSP-IDENTITY-" + id + ":user")
7050 
7051                 ev = dev[0].wait_event(["CTRL-REQ-PASSWORD"],
7052                                        timeout=10)
7053                 if ev is None:
7054                     raise Exception("Timeout on password request")
7055                 id = ev.split(':')[0].split('-')[-1]
7056                 dev[0].request("CTRL-RSP-PASSWORD-" + id + ":password")
7057 
7058                 # TODO: Does this work correctly?
7059 
7060                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
7061                                        timeout=10)
7062                 if ev is None:
7063                     raise Exception("Timeout on EAP failure")
7064 
7065             if i in [4, 5, 6, 7, 14]:
7066                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
7067                                        timeout=10)
7068                 if ev is None:
7069                     raise Exception("Timeout on EAP failure")
7070             else:
7071                 time.sleep(0.05)
7072             dev[0].request("REMOVE_NETWORK all")
7073             dev[0].wait_disconnected(timeout=1)
7074     finally:
7075         stop_radius_server(srv)
7076 
7077 def test_eap_proto_mschapv2_errors(dev, apdev):
7078     """EAP-MSCHAPv2 protocol tests (error paths)"""
7079     check_eap_capa(dev[0], "MSCHAPV2")
7080 
7081     def mschapv2_fail_password_expired(ctx):
7082         logger.info("Test: Failure before challenge - password expired")
7083         payload = b'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
7084         return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
7085                            4 + 1 + 4 + len(payload),
7086                            EAP_TYPE_MSCHAPV2,
7087                            4, 0, 4 + len(payload)) + payload
7088 
7089     def mschapv2_success_after_password_change(ctx, req=None):
7090         logger.info("Test: Success after password change")
7091         if req is None or len(req) != 591:
7092             payload = b"S=1122334455667788990011223344556677889900"
7093         else:
7094             data = req[9:]
7095             enc_pw = data[0:516]
7096             data = data[516:]
7097             enc_hash = data[0:16]
7098             data = data[16:]
7099             peer_challenge = data[0:16]
7100             data = data[16:]
7101             # Reserved
7102             data = data[8:]
7103             nt_response = data[0:24]
7104             data = data[24:]
7105             flags = data
7106             logger.info("enc_hash: " + binascii.hexlify(enc_hash).decode())
7107             logger.info("peer_challenge: " + binascii.hexlify(peer_challenge).decode())
7108             logger.info("nt_response: " + binascii.hexlify(nt_response).decode())
7109             logger.info("flags: " + binascii.hexlify(flags).decode())
7110 
7111             auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
7112             logger.info("auth_challenge: " + binascii.hexlify(auth_challenge).decode())
7113 
7114             auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
7115                                                       peer_challenge,
7116                                                       auth_challenge, "user")
7117             payload = b"S=" + binascii.hexlify(auth_resp).decode().upper().encode()
7118         return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
7119                            4 + 1 + 4 + len(payload),
7120                            EAP_TYPE_MSCHAPV2,
7121                            3, 0, 4 + len(payload)) + payload
7122 
7123     def mschapv2_handler(ctx, req):
7124         logger.info("mschapv2_handler - RX " + binascii.hexlify(req).decode())
7125         if 'num' not in ctx:
7126             ctx['num'] = 0
7127         ctx['num'] = ctx['num'] + 1
7128         if 'id' not in ctx:
7129             ctx['id'] = 1
7130         ctx['id'] = (ctx['id'] + 1) % 256
7131         idx = 0
7132 
7133         idx += 1
7134         if ctx['num'] == idx:
7135             return mschapv2_fail_password_expired(ctx)
7136         idx += 1
7137         if ctx['num'] == idx:
7138             return mschapv2_success_after_password_change(ctx, req)
7139         idx += 1
7140         if ctx['num'] == idx:
7141             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7142 
7143         idx += 1
7144         if ctx['num'] == idx:
7145             return mschapv2_fail_password_expired(ctx)
7146         idx += 1
7147         if ctx['num'] == idx:
7148             return mschapv2_success_after_password_change(ctx, req)
7149         idx += 1
7150         if ctx['num'] == idx:
7151             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7152 
7153         idx += 1
7154         if ctx['num'] == idx:
7155             return mschapv2_fail_password_expired(ctx)
7156         idx += 1
7157         if ctx['num'] == idx:
7158             return mschapv2_success_after_password_change(ctx, req)
7159         idx += 1
7160         if ctx['num'] == idx:
7161             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7162 
7163         idx += 1
7164         if ctx['num'] == idx:
7165             return mschapv2_fail_password_expired(ctx)
7166         idx += 1
7167         if ctx['num'] == idx:
7168             return mschapv2_success_after_password_change(ctx, req)
7169         idx += 1
7170         if ctx['num'] == idx:
7171             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7172 
7173         idx += 1
7174         if ctx['num'] == idx:
7175             return mschapv2_fail_password_expired(ctx)
7176         idx += 1
7177         if ctx['num'] == idx:
7178             return mschapv2_success_after_password_change(ctx, req)
7179         idx += 1
7180         if ctx['num'] == idx:
7181             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7182 
7183         idx += 1
7184         if ctx['num'] == idx:
7185             return mschapv2_fail_password_expired(ctx)
7186         idx += 1
7187         if ctx['num'] == idx:
7188             return mschapv2_success_after_password_change(ctx, req)
7189         idx += 1
7190         if ctx['num'] == idx:
7191             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7192 
7193         idx += 1
7194         if ctx['num'] == idx:
7195             return mschapv2_fail_password_expired(ctx)
7196         idx += 1
7197         if ctx['num'] == idx:
7198             return mschapv2_success_after_password_change(ctx, req)
7199         idx += 1
7200         if ctx['num'] == idx:
7201             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7202 
7203         idx += 1
7204         if ctx['num'] == idx:
7205             return mschapv2_fail_password_expired(ctx)
7206         idx += 1
7207         if ctx['num'] == idx:
7208             return mschapv2_success_after_password_change(ctx, req)
7209         idx += 1
7210         if ctx['num'] == idx:
7211             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7212 
7213         idx += 1
7214         if ctx['num'] == idx:
7215             return mschapv2_fail_password_expired(ctx)
7216         idx += 1
7217         if ctx['num'] == idx:
7218             return mschapv2_success_after_password_change(ctx, req)
7219         idx += 1
7220         if ctx['num'] == idx:
7221             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7222 
7223         return None
7224 
7225     srv = start_radius_server(mschapv2_handler)
7226 
7227     try:
7228         hapd = start_ap(apdev[0])
7229         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
7230 
7231         tests = ["os_get_random;eap_mschapv2_change_password",
7232                  "generate_nt_response;eap_mschapv2_change_password",
7233                  "get_master_key;eap_mschapv2_change_password",
7234                  "nt_password_hash;eap_mschapv2_change_password",
7235                  "old_nt_password_hash_encrypted_with_new_nt_password_hash"]
7236         for func in tests:
7237             with fail_test(dev[0], 1, func):
7238                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7239                                eap="MSCHAPV2", identity="user",
7240                                password="password", wait_connect=False)
7241                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
7242                 if ev is None:
7243                     raise Exception("Timeout on new password request")
7244                 id = ev.split(':')[0].split('-')[-1]
7245                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
7246                 time.sleep(0.1)
7247                 wait_fail_trigger(dev[0], "GET_FAIL")
7248                 dev[0].request("REMOVE_NETWORK all")
7249                 dev[0].wait_disconnected(timeout=1)
7250 
7251         tests = ["encrypt_pw_block_with_password_hash;eap_mschapv2_change_password",
7252                  "nt_password_hash;eap_mschapv2_change_password",
7253                  "nt_password_hash;eap_mschapv2_success"]
7254         for func in tests:
7255             with fail_test(dev[0], 1, func):
7256                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7257                                eap="MSCHAPV2", identity="user",
7258                                password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
7259                                wait_connect=False)
7260                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
7261                 if ev is None:
7262                     raise Exception("Timeout on new password request")
7263                 id = ev.split(':')[0].split('-')[-1]
7264                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
7265                 time.sleep(0.1)
7266                 wait_fail_trigger(dev[0], "GET_FAIL")
7267                 dev[0].request("REMOVE_NETWORK all")
7268                 dev[0].wait_disconnected(timeout=1)
7269 
7270         tests = ["eap_msg_alloc;eap_mschapv2_change_password"]
7271         for func in tests:
7272             with alloc_fail(dev[0], 1, func):
7273                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7274                                eap="MSCHAPV2", identity="user",
7275                                password="password", wait_connect=False)
7276                 ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
7277                 if ev is None:
7278                     raise Exception("Timeout on new password request")
7279                 id = ev.split(':')[0].split('-')[-1]
7280                 dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
7281                 time.sleep(0.1)
7282                 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
7283                 dev[0].request("REMOVE_NETWORK all")
7284                 dev[0].wait_disconnected(timeout=1)
7285     finally:
7286         stop_radius_server(srv)
7287 
7288 def test_eap_proto_pwd(dev, apdev):
7289     """EAP-pwd protocol tests"""
7290     check_eap_capa(dev[0], "PWD")
7291 
7292     global eap_proto_pwd_test_done, eap_proto_pwd_test_wait
7293     eap_proto_pwd_test_done = False
7294     eap_proto_pwd_test_wait = False
7295 
7296     def pwd_handler(ctx, req):
7297         logger.info("pwd_handler - RX " + binascii.hexlify(req).decode())
7298         if 'num' not in ctx:
7299             ctx['num'] = 0
7300         ctx['num'] = ctx['num'] + 1
7301         if 'id' not in ctx:
7302             ctx['id'] = 1
7303         ctx['id'] = (ctx['id'] + 1) % 256
7304         idx = 0
7305 
7306         global eap_proto_pwd_test_wait
7307         eap_proto_pwd_test_wait = False
7308 
7309         idx += 1
7310         if ctx['num'] == idx:
7311             logger.info("Test: Missing payload")
7312             # EAP-pwd: Got a frame but pos is not NULL and len is 0
7313             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
7314                                EAP_TYPE_PWD)
7315 
7316         idx += 1
7317         if ctx['num'] == idx:
7318             logger.info("Test: Missing Total-Length field")
7319             # EAP-pwd: Frame too short to contain Total-Length field
7320             payload = struct.pack("B", 0x80)
7321             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7322                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7323 
7324         idx += 1
7325         if ctx['num'] == idx:
7326             logger.info("Test: Too large Total-Length")
7327             # EAP-pwd: Incoming fragments whose total length = 65535
7328             payload = struct.pack(">BH", 0x80, 65535)
7329             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7330                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7331 
7332         idx += 1
7333         if ctx['num'] == idx:
7334             eap_proto_pwd_test_wait = True
7335             logger.info("Test: First fragment")
7336             # EAP-pwd: Incoming fragments whose total length = 10
7337             # EAP-pwd: ACKing a 0 byte fragment
7338             payload = struct.pack(">BH", 0xc0, 10)
7339             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7340                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7341         idx += 1
7342         if ctx['num'] == idx:
7343             logger.info("Test: Unexpected Total-Length value in the second fragment")
7344             # EAP-pwd: Incoming fragments whose total length = 0
7345             # EAP-pwd: Unexpected new fragment start when previous fragment is still in use
7346             payload = struct.pack(">BH", 0x80, 0)
7347             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7348                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7349 
7350         idx += 1
7351         if ctx['num'] == idx:
7352             logger.info("Test: First and only fragment")
7353             # EAP-pwd: Incoming fragments whose total length = 0
7354             # EAP-pwd: processing frame: exch 0, len 0
7355             # EAP-pwd: Ignoring message with unknown opcode 128
7356             payload = struct.pack(">BH", 0x80, 0)
7357             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7358                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7359 
7360         idx += 1
7361         if ctx['num'] == idx:
7362             logger.info("Test: First and only fragment with extra data")
7363             # EAP-pwd: Incoming fragments whose total length = 0
7364             # EAP-pwd: processing frame: exch 0, len 1
7365             # EAP-pwd: Ignoring message with unknown opcode 128
7366             payload = struct.pack(">BHB", 0x80, 0, 0)
7367             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7368                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7369 
7370         idx += 1
7371         if ctx['num'] == idx:
7372             eap_proto_pwd_test_wait = True
7373             logger.info("Test: First fragment")
7374             # EAP-pwd: Incoming fragments whose total length = 2
7375             # EAP-pwd: ACKing a 1 byte fragment
7376             payload = struct.pack(">BHB", 0xc0, 2, 1)
7377             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7378                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7379         idx += 1
7380         if ctx['num'] == idx:
7381             logger.info("Test: Extra data in the second fragment")
7382             # EAP-pwd: Buffer overflow attack detected (3 vs. 1)!
7383             payload = struct.pack(">BBB", 0x0, 2, 3)
7384             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7385                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7386 
7387         idx += 1
7388         if ctx['num'] == idx:
7389             logger.info("Test: Too short id exchange")
7390             # EAP-pwd: processing frame: exch 1, len 0
7391             # EAP-PWD: PWD-ID-Req -> FAILURE
7392             payload = struct.pack(">B", 0x01)
7393             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7394                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7395 
7396         idx += 1
7397         if ctx['num'] == idx:
7398             logger.info("Test: Unsupported rand func in id exchange")
7399             # EAP-PWD: Server EAP-pwd-ID proposal: group=0 random=0 prf=0 prep=0
7400             # EAP-PWD: PWD-ID-Req -> FAILURE
7401             payload = struct.pack(">BHBBLB", 0x01, 0, 0, 0, 0, 0)
7402             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7403                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7404 
7405         idx += 1
7406         if ctx['num'] == idx:
7407             logger.info("Test: Unsupported prf in id exchange")
7408             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=0 prep=0
7409             # EAP-PWD: PWD-ID-Req -> FAILURE
7410             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 0, 0, 0)
7411             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7412                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7413 
7414         idx += 1
7415         if ctx['num'] == idx:
7416             logger.info("Test: Unsupported password pre-processing technique in id exchange")
7417             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=255
7418             # EAP-PWD: Unsupported password pre-processing technique (Prep=255)
7419             # EAP-PWD: PWD-ID-Req -> FAILURE
7420             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 255)
7421             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7422                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7423 
7424         idx += 1
7425         if ctx['num'] == idx:
7426             eap_proto_pwd_test_wait = True
7427             logger.info("Test: Valid id exchange")
7428             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=0
7429             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7430             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7431                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7432         idx += 1
7433         if ctx['num'] == idx:
7434             logger.info("Test: Unexpected id exchange")
7435             # EAP-pwd: processing frame: exch 1, len 9
7436             # EAP-PWD: PWD-Commit-Req -> FAILURE
7437             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7438             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7439                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7440 
7441         idx += 1
7442         if ctx['num'] == idx:
7443             logger.info("Test: Unexpected commit exchange")
7444             # EAP-pwd: processing frame: exch 2, len 0
7445             # EAP-PWD: PWD-ID-Req -> FAILURE
7446             payload = struct.pack(">B", 0x02)
7447             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7448                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7449 
7450         idx += 1
7451         if ctx['num'] == idx:
7452             eap_proto_pwd_test_wait = True
7453             logger.info("Test: Valid id exchange")
7454             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=0
7455             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7456             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7457                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7458         idx += 1
7459         if ctx['num'] == idx:
7460             logger.info("Test: Unexpected Commit payload length (prep=None)")
7461             # EAP-pwd commit request, password prep is NONE
7462             # EAP-pwd: Unexpected Commit payload length 0 (expected 96)
7463             payload = struct.pack(">B", 0x02)
7464             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7465                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7466 
7467         idx += 1
7468         if ctx['num'] == idx:
7469             eap_proto_pwd_test_wait = True
7470             logger.info("Test: Valid id exchange")
7471             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=0
7472             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7473             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7474                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7475         idx += 1
7476         if ctx['num'] == idx:
7477             logger.info("Test: Commit payload with all zeros values --> Shared key at infinity")
7478             # EAP-pwd: Invalid coordinate in element
7479             payload = struct.pack(">B", 0x02) + 96*b'\0'
7480             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7481                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7482 
7483         idx += 1
7484         if ctx['num'] == idx:
7485             eap_proto_pwd_test_wait = True
7486             logger.info("Test: Valid id exchange")
7487             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=0
7488             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7489             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7490                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7491         idx += 1
7492         if ctx['num'] == idx:
7493             eap_proto_pwd_test_wait = True
7494             logger.info("Test: Commit payload with valid values")
7495             # EAP-pwd commit request, password prep is NONE
7496             element = binascii.unhexlify("8dcab2862c5396839a6bac0c689ff03d962863108e7c275bbf1d6eedf634ee832a214db99f0d0a1a6317733eecdd97f0fc4cda19f57e1bb9bb9c8dcf8c60ba6f")
7497             scalar = binascii.unhexlify("450f31e058cf2ac2636a5d6e2b3c70b1fcc301957f0716e77f13aa69f9a2e5bd")
7498             payload = struct.pack(">B", 0x02) + element + scalar
7499             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7500                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7501         idx += 1
7502         if ctx['num'] == idx:
7503             logger.info("Test: Unexpected Confirm payload length 0")
7504             # EAP-pwd: Unexpected Confirm payload length 0 (expected 32)
7505             payload = struct.pack(">B", 0x03)
7506             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7507                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7508 
7509         idx += 1
7510         if ctx['num'] == idx:
7511             eap_proto_pwd_test_wait = True
7512             logger.info("Test: Valid id exchange")
7513             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=0
7514             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7515             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7516                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7517         idx += 1
7518         if ctx['num'] == idx:
7519             eap_proto_pwd_test_wait = True
7520             logger.info("Test: Commit payload with valid values")
7521             # EAP-pwd commit request, password prep is NONE
7522             element = binascii.unhexlify("8dcab2862c5396839a6bac0c689ff03d962863108e7c275bbf1d6eedf634ee832a214db99f0d0a1a6317733eecdd97f0fc4cda19f57e1bb9bb9c8dcf8c60ba6f")
7523             scalar = binascii.unhexlify("450f31e058cf2ac2636a5d6e2b3c70b1fcc301957f0716e77f13aa69f9a2e5bd")
7524             payload = struct.pack(">B", 0x02) + element + scalar
7525             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7526                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7527         idx += 1
7528         if ctx['num'] == idx:
7529             logger.info("Test: Confirm payload with incorrect value")
7530             # EAP-PWD (peer): confirm did not verify
7531             payload = struct.pack(">B", 0x03) + 32*b'\0'
7532             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7533                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7534 
7535         idx += 1
7536         if ctx['num'] == idx:
7537             logger.info("Test: Unexpected confirm exchange")
7538             # EAP-pwd: processing frame: exch 3, len 0
7539             # EAP-PWD: PWD-ID-Req -> FAILURE
7540             payload = struct.pack(">B", 0x03)
7541             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7542                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7543 
7544         idx += 1
7545         if ctx['num'] == idx:
7546             logger.info("Test: Unsupported password pre-processing technique SASLprep in id exchange")
7547             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=2
7548             # EAP-PWD: Unsupported password pre-processing technique (Prep=2)
7549             # EAP-PWD: PWD-ID-Req -> FAILURE
7550             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 2)
7551             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7552                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7553 
7554         idx += 1
7555         if ctx['num'] == idx:
7556             eap_proto_pwd_test_wait = True
7557             logger.info("Test: Valid id exchange")
7558             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=1
7559             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 1)
7560             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7561                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7562         idx += 1
7563         if ctx['num'] == idx:
7564             logger.info("Test: Unexpected Commit payload length (prep=MS)")
7565             # EAP-pwd commit request, password prep is MS
7566             # EAP-pwd: Unexpected Commit payload length 0 (expected 96)
7567             payload = struct.pack(">B", 0x02)
7568             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7569                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7570 
7571         idx += 1
7572         if ctx['num'] == idx:
7573             eap_proto_pwd_test_wait = True
7574             logger.info("Test: Valid id exchange")
7575             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=3
7576             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 3)
7577             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7578                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7579         idx += 1
7580         if ctx['num'] == idx:
7581             logger.info("Test: Unexpected Commit payload length (prep=ssha1)")
7582             # EAP-pwd commit request, password prep is salted sha1
7583             # EAP-pwd: Invalid Salt-len
7584             payload = struct.pack(">B", 0x02)
7585             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7586                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7587 
7588         idx += 1
7589         if ctx['num'] == idx:
7590             eap_proto_pwd_test_wait = True
7591             logger.info("Test: Valid id exchange")
7592             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=3
7593             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 3)
7594             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7595                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7596         idx += 1
7597         if ctx['num'] == idx:
7598             logger.info("Test: Unexpected Commit payload length (prep=ssha1)")
7599             # EAP-pwd commit request, password prep is salted sha1
7600             # EAP-pwd: Invalid Salt-len
7601             payload = struct.pack(">BB", 0x02, 0)
7602             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7603                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7604 
7605         idx += 1
7606         if ctx['num'] == idx:
7607             eap_proto_pwd_test_wait = True
7608             logger.info("Test: Valid id exchange")
7609             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=3
7610             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 3)
7611             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7612                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7613         idx += 1
7614         if ctx['num'] == idx:
7615             logger.info("Test: Unexpected Commit payload length (prep=ssha1)")
7616             # EAP-pwd commit request, password prep is salted sha1
7617             # EAP-pwd: Unexpected Commit payload length 1 (expected 98)
7618             payload = struct.pack(">BB", 0x02, 1)
7619             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7620                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7621 
7622         idx += 1
7623         if ctx['num'] == idx:
7624             eap_proto_pwd_test_wait = True
7625             logger.info("Test: Valid id exchange")
7626             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=4
7627             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 4)
7628             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7629                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7630         idx += 1
7631         if ctx['num'] == idx:
7632             logger.info("Test: Unexpected Commit payload length (prep=ssha256)")
7633             # EAP-pwd commit request, password prep is salted sha256
7634             # EAP-pwd: Invalid Salt-len
7635             payload = struct.pack(">B", 0x02)
7636             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7637                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7638 
7639         idx += 1
7640         if ctx['num'] == idx:
7641             eap_proto_pwd_test_wait = True
7642             logger.info("Test: Valid id exchange")
7643             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=4
7644             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 4)
7645             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7646                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7647         idx += 1
7648         if ctx['num'] == idx:
7649             logger.info("Test: Unexpected Commit payload length (prep=ssha256)")
7650             # EAP-pwd commit request, password prep is salted sha256
7651             # EAP-pwd: Invalid Salt-len
7652             payload = struct.pack(">BB", 0x02, 0)
7653             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7654                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7655 
7656         idx += 1
7657         if ctx['num'] == idx:
7658             eap_proto_pwd_test_wait = True
7659             logger.info("Test: Valid id exchange")
7660             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=4
7661             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 4)
7662             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7663                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7664         idx += 1
7665         if ctx['num'] == idx:
7666             logger.info("Test: Unexpected Commit payload length (prep=ssha256)")
7667             # EAP-pwd commit request, password prep is salted sha256
7668             # EAP-pwd: Unexpected Commit payload length 1 (expected 98)
7669             payload = struct.pack(">BB", 0x02, 1)
7670             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7671                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7672 
7673         idx += 1
7674         if ctx['num'] == idx:
7675             eap_proto_pwd_test_wait = True
7676             logger.info("Test: Valid id exchange")
7677             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=5
7678             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 5)
7679             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7680                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7681         idx += 1
7682         if ctx['num'] == idx:
7683             logger.info("Test: Unexpected Commit payload length (prep=ssha512)")
7684             # EAP-pwd commit request, password prep is salted sha512
7685             # EAP-pwd: Invalid Salt-len
7686             payload = struct.pack(">B", 0x02)
7687             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7688                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7689 
7690         idx += 1
7691         if ctx['num'] == idx:
7692             eap_proto_pwd_test_wait = True
7693             logger.info("Test: Valid id exchange")
7694             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=5
7695             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 5)
7696             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7697                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7698         idx += 1
7699         if ctx['num'] == idx:
7700             logger.info("Test: Unexpected Commit payload length (prep=ssha512)")
7701             # EAP-pwd commit request, password prep is salted sha512
7702             # EAP-pwd: Invalid Salt-len
7703             payload = struct.pack(">BB", 0x02, 0)
7704             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7705                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7706 
7707         idx += 1
7708         if ctx['num'] == idx:
7709             eap_proto_pwd_test_wait = True
7710             logger.info("Test: Valid id exchange")
7711             # EAP-PWD: Server EAP-pwd-ID proposal: group=19 random=1 prf=1 prep=5
7712             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 5)
7713             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7714                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7715         idx += 1
7716         if ctx['num'] == idx:
7717             logger.info("Test: Unexpected Commit payload length (prep=ssha512)")
7718             # EAP-pwd commit request, password prep is salted sha512
7719             # EAP-pwd: Unexpected Commit payload length 1 (expected 98)
7720             payload = struct.pack(">BB", 0x02, 1)
7721             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7722                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7723 
7724         logger.info("No more test responses available - test case completed")
7725         global eap_proto_pwd_test_done
7726         eap_proto_pwd_test_done = True
7727         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7728 
7729     srv = start_radius_server(pwd_handler)
7730 
7731     try:
7732         hapd = start_ap(apdev[0])
7733         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
7734 
7735         i = 0
7736         while not eap_proto_pwd_test_done:
7737             i += 1
7738             logger.info("Running connection iteration %d" % i)
7739             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7740                            eap="PWD", identity="pwd user",
7741                            password="secret password",
7742                            wait_connect=False)
7743             ok = False
7744             for j in range(5):
7745                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS",
7746                                         "CTRL-EVENT-EAP-PROPOSED-METHOD"],
7747                                        timeout=5)
7748                 if ev is None:
7749                     raise Exception("Timeout on EAP start")
7750                 if "CTRL-EVENT-EAP-PROPOSED-METHOD" in ev:
7751                     ok = True
7752                     break
7753                 if "CTRL-EVENT-EAP-STATUS" in ev and "status='completion' parameter='failure'" in ev:
7754                     ok = True
7755                     break
7756             if not ok:
7757                 raise Exception("Expected EAP event not seen")
7758             if eap_proto_pwd_test_wait:
7759                 for k in range(20):
7760                     time.sleep(0.1)
7761                     if not eap_proto_pwd_test_wait:
7762                         break
7763                 if eap_proto_pwd_test_wait:
7764                     raise Exception("eap_proto_pwd_test_wait not cleared")
7765             dev[0].request("REMOVE_NETWORK all")
7766             dev[0].wait_disconnected(timeout=1)
7767             dev[0].dump_monitor()
7768     finally:
7769         stop_radius_server(srv)
7770 
7771 def test_eap_proto_pwd_invalid_scalar(dev, apdev):
7772     """EAP-pwd protocol tests - invalid server scalar"""
7773     check_eap_capa(dev[0], "PWD")
7774     run_eap_proto_pwd_invalid_scalar(dev, apdev, 32*b'\0')
7775     run_eap_proto_pwd_invalid_scalar(dev, apdev, 31*b'\0' + b'\x01')
7776     # Group Order
7777     val = binascii.unhexlify("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551")
7778     run_eap_proto_pwd_invalid_scalar(dev, apdev, val)
7779     # Group Order - 1
7780     val = binascii.unhexlify("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550")
7781     run_eap_proto_pwd_invalid_scalar(dev, apdev, val, valid_scalar=True)
7782 
7783 def run_eap_proto_pwd_invalid_scalar(dev, apdev, scalar, valid_scalar=False):
7784     global eap_proto_pwd_invalid_scalar_fail
7785     eap_proto_pwd_invalid_scalar_fail = False
7786 
7787     def pwd_handler(ctx, req):
7788         logger.info("pwd_handler - RX " + binascii.hexlify(req).decode())
7789         if 'num' not in ctx:
7790             ctx['num'] = 0
7791         ctx['num'] = ctx['num'] + 1
7792         if 'id' not in ctx:
7793             ctx['id'] = 1
7794         ctx['id'] = (ctx['id'] + 1) % 256
7795         idx = 0
7796 
7797         idx += 1
7798         if ctx['num'] == idx:
7799             logger.info("Test: Valid id exchange")
7800             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7801             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7802                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7803         idx += 1
7804         if ctx['num'] == idx:
7805             logger.info("Test: Commit payload with invalid scalar")
7806             payload = struct.pack(">B", 0x02) + binascii.unhexlify("67feb2b46d59e6dd3af3a429ec9c04a949337564615d3a2c19bdf6826eb6f5efa303aed86af3a072ed819d518d620adb2659f0e84c4f8b739629db8c93088cfc") + scalar
7807             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7808                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7809         idx += 1
7810         if ctx['num'] == idx:
7811             logger.info("Confirm message next - should not get here")
7812             global eap_proto_pwd_invalid_scalar_fail
7813             eap_proto_pwd_invalid_scalar_fail = True
7814             payload = struct.pack(">B", 0x03) + 32*b'\0'
7815             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7816                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7817 
7818         logger.info("No more test responses available - test case completed")
7819         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7820 
7821     srv = start_radius_server(pwd_handler)
7822 
7823     try:
7824         hapd = start_ap(apdev[0])
7825         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
7826 
7827         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7828                        eap="PWD", identity="pwd user",
7829                        password="secret password",
7830                        wait_connect=False)
7831         ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
7832         if ev is None:
7833             raise Exception("EAP failure not reported")
7834         dev[0].request("REMOVE_NETWORK all")
7835         dev[0].wait_disconnected(timeout=1)
7836         dev[0].dump_monitor()
7837     finally:
7838         stop_radius_server(srv)
7839 
7840     if valid_scalar and not eap_proto_pwd_invalid_scalar_fail:
7841         raise Exception("Peer did not accept valid EAP-pwd-Commit scalar")
7842     if not valid_scalar and eap_proto_pwd_invalid_scalar_fail:
7843         raise Exception("Peer did not stop after invalid EAP-pwd-Commit scalar")
7844 
7845 def test_eap_proto_pwd_invalid_element(dev, apdev):
7846     """EAP-pwd protocol tests - invalid server element"""
7847     check_eap_capa(dev[0], "PWD")
7848     # Invalid x,y coordinates
7849     run_eap_proto_pwd_invalid_element(dev, apdev, 64*b'\x00')
7850     run_eap_proto_pwd_invalid_element(dev, apdev, 32*b'\x00' + 32*b'\x01')
7851     run_eap_proto_pwd_invalid_element(dev, apdev, 32*b'\x01' + 32*b'\x00')
7852     run_eap_proto_pwd_invalid_element(dev, apdev, 32*b'\xff' + 32*b'\x01')
7853     run_eap_proto_pwd_invalid_element(dev, apdev, 32*b'\x01' + 32*b'\xff')
7854     run_eap_proto_pwd_invalid_element(dev, apdev, 64*b'\xff')
7855     # Not on curve
7856     run_eap_proto_pwd_invalid_element(dev, apdev, 64*b'\x01')
7857 
7858 def run_eap_proto_pwd_invalid_element(dev, apdev, element):
7859     global eap_proto_pwd_invalid_element_fail
7860     eap_proto_pwd_invalid_element_fail = False
7861 
7862     def pwd_handler(ctx, req):
7863         logger.info("pwd_handler - RX " + binascii.hexlify(req).decode())
7864         if 'num' not in ctx:
7865             ctx['num'] = 0
7866         ctx['num'] = ctx['num'] + 1
7867         if 'id' not in ctx:
7868             ctx['id'] = 1
7869         ctx['id'] = (ctx['id'] + 1) % 256
7870         idx = 0
7871 
7872         idx += 1
7873         if ctx['num'] == idx:
7874             logger.info("Test: Valid id exchange")
7875             payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
7876             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7877                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7878         idx += 1
7879         if ctx['num'] == idx:
7880             logger.info("Test: Commit payload with invalid element")
7881             payload = struct.pack(">B", 0x02) + element + 31*b'\0' + b'\x02'
7882             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7883                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7884         idx += 1
7885         if ctx['num'] == idx:
7886             logger.info("Confirm message next - should not get here")
7887             global eap_proto_pwd_invalid_element_fail
7888             eap_proto_pwd_invalid_element_fail = True
7889             payload = struct.pack(">B", 0x03) + 32*b'\0'
7890             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
7891                                4 + 1 + len(payload), EAP_TYPE_PWD) + payload
7892 
7893         logger.info("No more test responses available - test case completed")
7894         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
7895 
7896     srv = start_radius_server(pwd_handler)
7897 
7898     try:
7899         hapd = start_ap(apdev[0])
7900         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
7901 
7902         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
7903                        eap="PWD", identity="pwd user",
7904                        password="secret password",
7905                        wait_connect=False)
7906         ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
7907         if ev is None:
7908             raise Exception("EAP failure not reported")
7909         dev[0].request("REMOVE_NETWORK all")
7910         dev[0].wait_disconnected(timeout=1)
7911         dev[0].dump_monitor()
7912     finally:
7913         stop_radius_server(srv)
7914 
7915     if eap_proto_pwd_invalid_element_fail:
7916         raise Exception("Peer did not stop after invalid EAP-pwd-Commit element")
7917 
7918 def rx_msg(src):
7919     ev = src.wait_event(["EAPOL-TX"], timeout=5)
7920     if ev is None:
7921         raise Exception("No EAPOL-TX")
7922     return ev.split(' ')[2]
7923 
7924 def tx_msg(src, dst, msg):
7925     dst.request("EAPOL_RX " + src.own_addr() + " " + msg)
7926 
7927 def proxy_msg(src, dst):
7928     msg = rx_msg(src)
7929     tx_msg(src, dst, msg)
7930     return msg
7931 
7932 def start_pwd_exchange(dev, ap):
7933     check_eap_capa(dev, "PWD")
7934     params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
7935     hapd = hostapd.add_ap(ap, params)
7936     hapd.request("SET ext_eapol_frame_io 1")
7937     dev.request("SET ext_eapol_frame_io 1")
7938     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP",
7939                    eap="PWD", identity="pwd user", password="secret password",
7940                    wait_connect=False, scan_freq="2412")
7941     proxy_msg(hapd, dev) # EAP-Identity/Request
7942     proxy_msg(dev, hapd) # EAP-Identity/Response
7943     proxy_msg(hapd, dev) # EAP-pwd-ID/Request
7944     proxy_msg(dev, hapd) # EAP-pwd-ID/Response
7945     return hapd
7946 
7947 def test_eap_proto_pwd_unexpected_fragment(dev, apdev):
7948     """EAP-pwd protocol tests - unexpected more-fragment frame"""
7949     hapd = start_pwd_exchange(dev[0], apdev[0])
7950 
7951     # EAP-pwd-Commit/Request
7952     req = rx_msg(hapd)
7953     if req[18:20] != "02":
7954         raise Exception("Unexpected EAP-pwd-Commit/Request flag")
7955     msg = req[0:18] + "42" + req[20:]
7956     tx_msg(hapd, dev[0], msg)
7957 
7958 def test_eap_proto_pwd_reflection_attack(dev, apdev):
7959     """EAP-pwd protocol tests - reflection attack on the server"""
7960     hapd = start_pwd_exchange(dev[0], apdev[0])
7961 
7962     # EAP-pwd-Commit/Request
7963     req = proxy_msg(hapd, dev[0])
7964     if len(req) != 212:
7965         raise Exception("Unexpected EAP-pwd-Commit/Response length")
7966 
7967     # EAP-pwd-Commit/Response
7968     resp = rx_msg(dev[0])
7969     # Reflect same Element/Scalar back to the server
7970     msg = resp[0:20] + req[20:]
7971     tx_msg(dev[0], hapd, msg)
7972 
7973     # EAP-pwd-Commit/Response or EAP-Failure
7974     req = rx_msg(hapd)
7975     if req[8:10] != "04":
7976         # reflect EAP-pwd-Confirm/Request
7977         msg = req[0:8] + "02" + req[10:]
7978         tx_msg(dev[0], hapd, msg)
7979         req = rx_msg(hapd)
7980         if req[8:10] == "03":
7981             raise Exception("EAP-Success after reflected Element/Scalar")
7982         raise Exception("No EAP-Failure to reject invalid EAP-pwd-Commit/Response")
7983 
7984 def test_eap_proto_pwd_invalid_scalar_peer(dev, apdev):
7985     """EAP-pwd protocol tests - invalid peer scalar"""
7986     run_eap_proto_pwd_invalid_scalar_peer(dev, apdev, 32*"00")
7987     run_eap_proto_pwd_invalid_scalar_peer(dev, apdev, 31*"00" + "01")
7988     # Group Order
7989     run_eap_proto_pwd_invalid_scalar_peer(dev, apdev,
7990                                           "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551")
7991     # Group Order - 1
7992     run_eap_proto_pwd_invalid_scalar_peer(dev, apdev,
7993                                           "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550",
7994                                           valid_scalar=True)
7995 
7996 def run_eap_proto_pwd_invalid_scalar_peer(dev, apdev, scalar,
7997                                           valid_scalar=False):
7998     hapd = start_pwd_exchange(dev[0], apdev[0])
7999     proxy_msg(hapd, dev[0]) # EAP-pwd-Commit/Request
8000 
8001     # EAP-pwd-Commit/Response
8002     resp = rx_msg(dev[0])
8003     # Replace scalar with an invalid value
8004     msg = resp[0:20] + resp[20:148] + scalar
8005     tx_msg(dev[0], hapd, msg)
8006 
8007     # EAP-pwd-Commit/Response or EAP-Failure
8008     req = rx_msg(hapd)
8009     if valid_scalar and req[8:10] == "04":
8010         raise Exception("Unexpected EAP-Failure with valid scalar")
8011     if not valid_scalar and req[8:10] != "04":
8012         raise Exception("No EAP-Failure to reject invalid scalar")
8013     dev[0].request("REMOVE_NETWORK all")
8014     dev[0].wait_disconnected(timeout=1)
8015     hapd.disable()
8016 
8017 def test_eap_proto_pwd_invalid_element_peer(dev, apdev):
8018     """EAP-pwd protocol tests - invalid peer element"""
8019     # Invalid x,y coordinates
8020     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 64*'00')
8021     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 32*'00' + 32*'01')
8022     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 32*'01' + 32*'00')
8023     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 32*'ff' + 32*'01')
8024     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 32*'01' + 32*'ff')
8025     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 64*'ff')
8026     # Not on curve
8027     run_eap_proto_pwd_invalid_element_peer(dev, apdev, 64*'01')
8028 
8029 def run_eap_proto_pwd_invalid_element_peer(dev, apdev, element):
8030     hapd = start_pwd_exchange(dev[0], apdev[0])
8031     proxy_msg(hapd, dev[0]) # EAP-pwd-Commit/Request
8032 
8033     # EAP-pwd-Commit/Response
8034     resp = rx_msg(dev[0])
8035     # Replace element with an invalid value
8036     msg = resp[0:20] + element + resp[148:]
8037     tx_msg(dev[0], hapd, msg)
8038 
8039     # EAP-pwd-Commit/Response or EAP-Failure
8040     req = rx_msg(hapd)
8041     if req[8:10] != "04":
8042         raise Exception("No EAP-Failure to reject invalid element")
8043     dev[0].request("REMOVE_NETWORK all")
8044     dev[0].wait_disconnected(timeout=1)
8045     hapd.disable()
8046 
8047 def test_eap_proto_pwd_errors(dev, apdev):
8048     """EAP-pwd local error cases"""
8049     check_eap_capa(dev[0], "PWD")
8050     params = hostapd.wpa2_eap_params(ssid="eap-test")
8051     hapd = hostapd.add_ap(apdev[0], params)
8052     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8053 
8054     for i in range(1, 4):
8055         with alloc_fail(dev[0], i, "eap_pwd_init"):
8056             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8057                            eap="PWD", identity="pwd user",
8058                            password="secret password",
8059                            wait_connect=False)
8060             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
8061                                    timeout=15)
8062             if ev is None:
8063                 raise Exception("Timeout on EAP start")
8064             dev[0].request("REMOVE_NETWORK all")
8065             dev[0].wait_disconnected()
8066 
8067     with alloc_fail(dev[0], 1, "eap_pwd_get_session_id"):
8068         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8069                        eap="PWD", identity="pwd user",
8070                        fragment_size="0",
8071                        password="secret password")
8072         dev[0].request("REMOVE_NETWORK all")
8073         dev[0].wait_disconnected()
8074 
8075     funcs = ["eap_pwd_getkey", "eap_pwd_get_emsk",
8076              "=wpabuf_alloc;eap_pwd_perform_commit_exchange",
8077              "=wpabuf_alloc;eap_pwd_perform_confirm_exchange"]
8078     for func in funcs:
8079         with alloc_fail(dev[0], 1, func):
8080             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8081                            eap="PWD", identity="pwd user@domain",
8082                            password="secret password", erp="1",
8083                            wait_connect=False)
8084             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8085             dev[0].request("REMOVE_NETWORK all")
8086             dev[0].wait_disconnected()
8087 
8088     for i in range(1, 5):
8089         with alloc_fail(dev[0], i, "eap_pwd_perform_id_exchange"):
8090             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8091                            eap="PWD", identity="pwd user",
8092                            password="secret password",
8093                            wait_connect=False)
8094             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8095                                    timeout=15)
8096             if ev is None:
8097                 raise Exception("Timeout on EAP start")
8098             ok = False
8099             for j in range(10):
8100                 state = dev[0].request('GET_ALLOC_FAIL')
8101                 if state.startswith('0:'):
8102                     ok = True
8103                     break
8104                 time.sleep(0.1)
8105             if not ok:
8106                 raise Exception("No allocation failure seen")
8107             dev[0].request("REMOVE_NETWORK all")
8108             dev[0].wait_disconnected()
8109 
8110     with alloc_fail(dev[0], 1, "wpabuf_alloc;eap_pwd_perform_id_exchange"):
8111         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8112                        eap="PWD", identity="pwd user",
8113                        password="secret password",
8114                        wait_connect=False)
8115         ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8116                                timeout=15)
8117         if ev is None:
8118             raise Exception("Timeout on EAP start")
8119         dev[0].request("REMOVE_NETWORK all")
8120         dev[0].wait_disconnected()
8121 
8122     for i in range(1, 9):
8123         with alloc_fail(dev[0], i, "eap_pwd_perform_commit_exchange"):
8124             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8125                            eap="PWD", identity="pwd user",
8126                            password="secret password",
8127                            wait_connect=False)
8128             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8129                                    timeout=15)
8130             if ev is None:
8131                 raise Exception("Timeout on EAP start")
8132             ok = False
8133             for j in range(10):
8134                 state = dev[0].request('GET_ALLOC_FAIL')
8135                 if state.startswith('0:'):
8136                     ok = True
8137                     break
8138                 time.sleep(0.1)
8139             if not ok:
8140                 raise Exception("No allocation failure seen")
8141             dev[0].request("REMOVE_NETWORK all")
8142             dev[0].wait_disconnected()
8143 
8144     for i in range(1, 12):
8145         with alloc_fail(dev[0], i, "eap_pwd_perform_confirm_exchange"):
8146             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8147                            eap="PWD", identity="pwd user",
8148                            password="secret password",
8149                            wait_connect=False)
8150             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8151                                    timeout=15)
8152             if ev is None:
8153                 raise Exception("Timeout on EAP start")
8154             ok = False
8155             for j in range(10):
8156                 state = dev[0].request('GET_ALLOC_FAIL')
8157                 if state.startswith('0:'):
8158                     ok = True
8159                     break
8160                 time.sleep(0.1)
8161             if not ok:
8162                 raise Exception("No allocation failure seen")
8163             dev[0].request("REMOVE_NETWORK all")
8164             dev[0].wait_disconnected()
8165 
8166     for i in range(1, 5):
8167         with alloc_fail(dev[0], i, "eap_msg_alloc;=eap_pwd_process"):
8168             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8169                            eap="PWD", identity="pwd user",
8170                            password="secret password", fragment_size="50",
8171                            wait_connect=False)
8172             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8173                                    timeout=15)
8174             if ev is None:
8175                 raise Exception("Timeout on EAP start")
8176             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8177             dev[0].request("REMOVE_NETWORK all")
8178             dev[0].wait_disconnected()
8179 
8180     # No password configured
8181     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8182                    eap="PWD", identity="pwd user",
8183                    wait_connect=False)
8184     ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=52"],
8185                            timeout=15)
8186     if ev is None:
8187         raise Exception("EAP-pwd not started")
8188     dev[0].request("REMOVE_NETWORK all")
8189     dev[0].wait_disconnected()
8190 
8191     funcs = [(1, "hash_nt_password_hash;eap_pwd_perform_commit_exchange"),
8192              (1, "=crypto_bignum_init;eap_pwd_perform_commit_exchange"),
8193              (1, "=crypto_ec_point_init;eap_pwd_perform_commit_exchange"),
8194              (2, "=crypto_ec_point_init;eap_pwd_perform_commit_exchange"),
8195              (1, "=crypto_ec_point_mul;eap_pwd_perform_commit_exchange"),
8196              (2, "=crypto_ec_point_mul;eap_pwd_perform_commit_exchange"),
8197              (3, "=crypto_ec_point_mul;eap_pwd_perform_commit_exchange"),
8198              (1, "=crypto_ec_point_add;eap_pwd_perform_commit_exchange"),
8199              (1, "=crypto_ec_point_invert;eap_pwd_perform_commit_exchange"),
8200              (1, "=crypto_ec_point_to_bin;eap_pwd_perform_commit_exchange"),
8201              (1, "crypto_hash_finish;eap_pwd_kdf"),
8202              (1, "crypto_ec_point_from_bin;eap_pwd_get_element"),
8203              (3, "crypto_bignum_init;compute_password_element"),
8204              (4, "crypto_bignum_init;compute_password_element"),
8205              (1, "crypto_bignum_init_set;compute_password_element"),
8206              (2, "crypto_bignum_init_set;compute_password_element"),
8207              (3, "crypto_bignum_init_set;compute_password_element"),
8208              (1, "crypto_bignum_to_bin;compute_password_element"),
8209              (1, "crypto_ec_point_compute_y_sqr;compute_password_element"),
8210              (1, "crypto_bignum_rand;compute_password_element"),
8211              (1, "crypto_bignum_sub;compute_password_element")]
8212     for count, func in funcs:
8213         with fail_test(dev[0], count, func):
8214             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8215                            eap="PWD", identity="pwd-hash",
8216                            password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a",
8217                            wait_connect=False)
8218             ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
8219             if ev is None:
8220                 raise Exception("No EAP-Failure reported")
8221             dev[0].request("REMOVE_NETWORK all")
8222             dev[0].wait_disconnected()
8223 
8224     params = {"ssid": "eap-test2", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
8225               "rsn_pairwise": "CCMP", "ieee8021x": "1",
8226               "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
8227               "pwd_group": "19", "fragment_size": "40"}
8228     hapd2 = hostapd.add_ap(apdev[1], params)
8229     dev[0].scan_for_bss(hapd2.own_addr(), freq=2412)
8230 
8231     with alloc_fail(dev[0], 1, "wpabuf_alloc;=eap_pwd_process"):
8232         dev[0].connect("eap-test2", key_mgmt="WPA-EAP", scan_freq="2412",
8233                        eap="PWD", identity="pwd user",
8234                        password="secret password",
8235                        wait_connect=False)
8236         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8237         dev[0].request("REMOVE_NETWORK all")
8238         dev[0].wait_disconnected()
8239 
8240     for i in range(1, 5):
8241         with fail_test(dev[0], i,
8242                        "=crypto_ec_point_to_bin;eap_pwd_perform_confirm_exchange"):
8243             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8244                            eap="PWD", identity="pwd-hash",
8245                            password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a",
8246                            wait_connect=False)
8247             ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
8248             if ev is None:
8249                 raise Exception("No EAP-Failure reported")
8250             dev[0].request("REMOVE_NETWORK all")
8251             dev[0].wait_disconnected()
8252             dev[0].dump_monitor()
8253 
8254 def run_eap_pwd_connect(dev, hash=True, fragment=2000):
8255     if hash:
8256         dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP",
8257                     fragment_size=str(fragment),
8258                     eap="PWD", identity="pwd-hash",
8259                     password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a",
8260                     scan_freq="2412", wait_connect=False)
8261     else:
8262         dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP",
8263                     fragment_size=str(fragment),
8264                     eap="PWD", identity="pwd-hash-sha1",
8265                     password="secret password",
8266                     scan_freq="2412", wait_connect=False)
8267     ev = dev.wait_event(["CTRL-EVENT-EAP-SUCCESS", "CTRL-EVENT-EAP-FAILURE",
8268                          "CTRL-EVENT-DISCONNECTED"],
8269                         timeout=1)
8270     dev.request("REMOVE_NETWORK all")
8271     if not ev or "CTRL-EVENT-DISCONNECTED" not in ev:
8272         dev.wait_disconnected()
8273     dev.dump_monitor()
8274 
8275 def test_eap_proto_pwd_errors_server(dev, apdev):
8276     """EAP-pwd local error cases on server"""
8277     check_eap_capa(dev[0], "PWD")
8278     params = int_eap_server_params()
8279     params['erp_domain'] = 'example.com'
8280     params['eap_server_erp'] = '1'
8281     hapd = hostapd.add_ap(apdev[0], params)
8282     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8283 
8284     tests = [(1, "eap_pwd_init"),
8285              (2, "eap_pwd_init"),
8286              (3, "eap_pwd_init"),
8287              (1, "eap_pwd_build_id_req"),
8288              (1, "eap_pwd_build_commit_req"),
8289              (1, "eap_pwd_build_confirm_req"),
8290              (1, "eap_pwd_h_init;eap_pwd_build_confirm_req"),
8291              (1, "wpabuf_alloc;eap_pwd_build_confirm_req"),
8292              (1, "eap_msg_alloc;eap_pwd_build_req"),
8293              (1, "eap_pwd_process_id_resp"),
8294              (1, "get_eap_pwd_group;eap_pwd_process_id_resp"),
8295              (1, "eap_pwd_process_confirm_resp"),
8296              (1, "eap_pwd_h_init;eap_pwd_process_confirm_resp"),
8297              (1, "compute_keys;eap_pwd_process_confirm_resp"),
8298              (1, "eap_pwd_getkey"),
8299              (1, "eap_pwd_get_emsk"),
8300              (1, "eap_pwd_get_session_id")]
8301     for count, func in tests:
8302         with alloc_fail(hapd, count, func):
8303             run_eap_pwd_connect(dev[0], hash=True)
8304 
8305     tests = [(1, "eap_msg_alloc;eap_pwd_build_req"),
8306              (2, "eap_msg_alloc;eap_pwd_build_req"),
8307              (1, "wpabuf_alloc;eap_pwd_process")]
8308     for count, func in tests:
8309         with alloc_fail(hapd, count, func):
8310             run_eap_pwd_connect(dev[0], hash=True, fragment=13)
8311 
8312     tests = [(4, "eap_pwd_init")]
8313     for count, func in tests:
8314         with alloc_fail(hapd, count, func):
8315             run_eap_pwd_connect(dev[0], hash=False)
8316 
8317     tests = [(1, "eap_pwd_build_id_req"),
8318              (1, "eap_pwd_build_commit_req"),
8319              (1, "crypto_ec_point_mul;eap_pwd_build_commit_req"),
8320              (1, "crypto_ec_point_invert;eap_pwd_build_commit_req"),
8321              (1, "crypto_ec_point_to_bin;eap_pwd_build_commit_req"),
8322              (1, "crypto_ec_point_to_bin;eap_pwd_build_confirm_req"),
8323              (2, "=crypto_ec_point_to_bin;eap_pwd_build_confirm_req"),
8324              (1, "hash_nt_password_hash;eap_pwd_process_id_resp"),
8325              (1, "compute_password_element;eap_pwd_process_id_resp"),
8326              (1, "crypto_bignum_init;eap_pwd_process_commit_resp"),
8327              (1, "crypto_ec_point_mul;eap_pwd_process_commit_resp"),
8328              (2, "crypto_ec_point_mul;eap_pwd_process_commit_resp"),
8329              (1, "crypto_ec_point_add;eap_pwd_process_commit_resp"),
8330              (1, "crypto_ec_point_to_bin;eap_pwd_process_confirm_resp"),
8331              (2, "=crypto_ec_point_to_bin;eap_pwd_process_confirm_resp")]
8332     for count, func in tests:
8333         with fail_test(hapd, count, func):
8334             run_eap_pwd_connect(dev[0], hash=True)
8335 
8336 def start_pwd_assoc(dev, hapd):
8337     dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP",
8338                 eap="PWD", identity="pwd user", password="secret password",
8339                 wait_connect=False, scan_freq="2412")
8340     proxy_msg(hapd, dev) # EAP-Identity/Request
8341     proxy_msg(dev, hapd) # EAP-Identity/Response
8342     proxy_msg(hapd, dev) # EAP-pwd-Identity/Request
8343 
8344 def stop_pwd_assoc(dev, hapd):
8345     dev.request("REMOVE_NETWORK all")
8346     dev.wait_disconnected()
8347     dev.dump_monitor()
8348     hapd.dump_monitor()
8349 
8350 def test_eap_proto_pwd_server(dev, apdev):
8351     """EAP-pwd protocol testing for the server"""
8352     check_eap_capa(dev[0], "PWD")
8353     params = int_eap_server_params()
8354     hapd = hostapd.add_ap(apdev[0], params)
8355     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8356     hapd.request("SET ext_eapol_frame_io 1")
8357     dev[0].request("SET ext_eapol_frame_io 1")
8358 
8359     start_pwd_assoc(dev[0], hapd)
8360     resp = rx_msg(dev[0])
8361     # Replace exch field with unexpected value
8362     # --> EAP-pwd: Unexpected opcode=4 in state=0
8363     msg = resp[0:18] + "04" + resp[20:]
8364     tx_msg(dev[0], hapd, msg)
8365 
8366     # Too short EAP-pwd header (no flags/exch field)
8367     # --> EAP-pwd: Invalid frame
8368     msg = resp[0:4] + "0005" + resp[8:12] + "0005" + "34"
8369     tx_msg(dev[0], hapd, msg)
8370 
8371     # Too short EAP-pwd header (L=1 but only one octet of total length field)
8372     # --> EAP-pwd: Frame too short to contain Total-Length field
8373     msg = resp[0:4] + "0007" + resp[8:12] + "0007" + "34" + "81ff"
8374     tx_msg(dev[0], hapd, msg)
8375     # server continues exchange, so start from scratch for the next step
8376     rx_msg(hapd)
8377     stop_pwd_assoc(dev[0], hapd)
8378 
8379     start_pwd_assoc(dev[0], hapd)
8380     resp = rx_msg(dev[0])
8381     # Too large total length
8382     msg = resp[0:4] + "0008" + resp[8:12] + "0008" + "34" + "c1ffff"
8383     tx_msg(dev[0], hapd, msg)
8384     # server continues exchange, so start from scratch for the next step
8385     rx_msg(hapd)
8386     stop_pwd_assoc(dev[0], hapd)
8387 
8388     start_pwd_assoc(dev[0], hapd)
8389     resp = rx_msg(dev[0])
8390     # First fragment
8391     msg = resp[0:4] + "0009" + resp[8:12] + "0009" + "34" + "c100ff" + "aa"
8392     tx_msg(dev[0], hapd, msg)
8393     # Ack
8394     req = rx_msg(hapd)
8395     # Unexpected first fragment
8396     # --> EAP-pwd: Unexpected new fragment start when previous fragment is still in use
8397     msg = resp[0:4] + "0009" + resp[8:10] + req[10:12] + "0009" + "34" + "c100ee" + "bb"
8398     tx_msg(dev[0], hapd, msg)
8399     # server continues exchange, so start from scratch for the next step
8400     rx_msg(hapd)
8401     stop_pwd_assoc(dev[0], hapd)
8402 
8403     start_pwd_assoc(dev[0], hapd)
8404     resp = rx_msg(dev[0])
8405     # Too much data in first fragment
8406     # --> EAP-pwd: Buffer overflow attack detected! (0+2 > 1)
8407     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "34" + "c10001" + "aabb"
8408     tx_msg(dev[0], hapd, msg)
8409     # EAP-Failure
8410     rx_msg(hapd)
8411     stop_pwd_assoc(dev[0], hapd)
8412 
8413     start_pwd_assoc(dev[0], hapd)
8414     resp = rx_msg(dev[0])
8415     # Change parameters
8416     # --> EAP-pwd: peer changed parameters
8417     msg = resp[0:20] + "ff" + resp[22:]
8418     tx_msg(dev[0], hapd, msg)
8419     # EAP-Failure
8420     rx_msg(hapd)
8421     stop_pwd_assoc(dev[0], hapd)
8422 
8423     start_pwd_assoc(dev[0], hapd)
8424     resp = rx_msg(dev[0])
8425     # Too short ID response
8426     # --> EAP-pwd: Invalid ID response
8427     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "34" + "01ffeeddcc"
8428     tx_msg(dev[0], hapd, msg)
8429     # server continues exchange, so start from scratch for the next step
8430     rx_msg(hapd)
8431     stop_pwd_assoc(dev[0], hapd)
8432 
8433     start_pwd_assoc(dev[0], hapd)
8434     # EAP-pwd-Identity/Response
8435     resp = rx_msg(dev[0])
8436     tx_msg(dev[0], hapd, resp)
8437     # EAP-pwd-Commit/Request
8438     req = rx_msg(hapd)
8439     # Unexpected EAP-pwd-Identity/Response
8440     # --> EAP-pwd: Unexpected opcode=1 in state=1
8441     msg = resp[0:10] + req[10:12] + resp[12:]
8442     tx_msg(dev[0], hapd, msg)
8443     # server continues exchange, so start from scratch for the next step
8444     rx_msg(hapd)
8445     stop_pwd_assoc(dev[0], hapd)
8446 
8447     start_pwd_assoc(dev[0], hapd)
8448     proxy_msg(dev[0], hapd) # EAP-pwd-Identity/Response
8449     proxy_msg(hapd, dev[0]) # EAP-pwd-Commit/Request
8450     # EAP-pwd-Commit/Response
8451     resp = rx_msg(dev[0])
8452     # Too short Commit response
8453     # --> EAP-pwd: Unexpected Commit payload length 4 (expected 96)
8454     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "34" + "02ffeeddcc"
8455     tx_msg(dev[0], hapd, msg)
8456     # EAP-Failure
8457     rx_msg(hapd)
8458     stop_pwd_assoc(dev[0], hapd)
8459 
8460     start_pwd_assoc(dev[0], hapd)
8461     proxy_msg(dev[0], hapd) # EAP-pwd-Identity/Response
8462     proxy_msg(hapd, dev[0]) # EAP-pwd-Commit/Request
8463     proxy_msg(dev[0], hapd) # EAP-pwd-Commit/Response
8464     proxy_msg(hapd, dev[0]) # EAP-pwd-Confirm/Request
8465     # EAP-pwd-Confirm/Response
8466     resp = rx_msg(dev[0])
8467     # Too short Confirm response
8468     # --> EAP-pwd: Unexpected Confirm payload length 4 (expected 32)
8469     msg = resp[0:4] + "000a" + resp[8:12] + "000a" + "34" + "03ffeeddcc"
8470     tx_msg(dev[0], hapd, msg)
8471     # EAP-Failure
8472     rx_msg(hapd)
8473     stop_pwd_assoc(dev[0], hapd)
8474 
8475     start_pwd_assoc(dev[0], hapd)
8476     resp = rx_msg(dev[0])
8477     # Set M=1
8478     # --> EAP-pwd: No buffer for reassembly
8479     msg = resp[0:18] + "41" + resp[20:]
8480     tx_msg(dev[0], hapd, msg)
8481     # EAP-Failure
8482     rx_msg(hapd)
8483     stop_pwd_assoc(dev[0], hapd)
8484 
8485 def test_eap_proto_erp(dev, apdev):
8486     """ERP protocol tests"""
8487     check_erp_capa(dev[0])
8488 
8489     global eap_proto_erp_test_done
8490     eap_proto_erp_test_done = False
8491 
8492     def erp_handler(ctx, req):
8493         logger.info("erp_handler - RX " + binascii.hexlify(req).decode())
8494         if 'num' not in ctx:
8495             ctx['num'] = 0
8496         ctx['num'] += 1
8497         if 'id' not in ctx:
8498             ctx['id'] = 1
8499         ctx['id'] = (ctx['id'] + 1) % 256
8500         idx = 0
8501 
8502         idx += 1
8503         if ctx['num'] == idx:
8504             logger.info("Test: Missing type")
8505             return struct.pack(">BBH", EAP_CODE_INITIATE, ctx['id'], 4)
8506 
8507         idx += 1
8508         if ctx['num'] == idx:
8509             logger.info("Test: Unexpected type")
8510             return struct.pack(">BBHB", EAP_CODE_INITIATE, ctx['id'], 4 + 1,
8511                                255)
8512 
8513         idx += 1
8514         if ctx['num'] == idx:
8515             logger.info("Test: Missing Reserved field")
8516             return struct.pack(">BBHB", EAP_CODE_INITIATE, ctx['id'], 4 + 1,
8517                                EAP_ERP_TYPE_REAUTH_START)
8518 
8519         idx += 1
8520         if ctx['num'] == idx:
8521             logger.info("Test: Zero-length TVs/TLVs")
8522             payload = b""
8523             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8524                                4 + 1 + 1 + len(payload),
8525                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8526 
8527         idx += 1
8528         if ctx['num'] == idx:
8529             logger.info("Test: Too short TLV")
8530             payload = struct.pack("B", 191)
8531             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8532                                4 + 1 + 1 + len(payload),
8533                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8534 
8535         idx += 1
8536         if ctx['num'] == idx:
8537             logger.info("Test: Truncated TLV")
8538             payload = struct.pack("BB", 191, 1)
8539             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8540                                4 + 1 + 1 + len(payload),
8541                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8542 
8543         idx += 1
8544         if ctx['num'] == idx:
8545             logger.info("Test: Ignored unknown TLV and unknown TV/TLV terminating parsing")
8546             payload = struct.pack("BBB", 191, 0, 192)
8547             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8548                                4 + 1 + 1 + len(payload),
8549                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8550 
8551         idx += 1
8552         if ctx['num'] == idx:
8553             logger.info("Test: More than one keyName-NAI")
8554             payload = struct.pack("BBBB", EAP_ERP_TLV_KEYNAME_NAI, 0,
8555                                   EAP_ERP_TLV_KEYNAME_NAI, 0)
8556             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8557                                4 + 1 + 1 + len(payload),
8558                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8559 
8560         idx += 1
8561         if ctx['num'] == idx:
8562             logger.info("Test: Too short TLV keyName-NAI")
8563             payload = struct.pack("B", EAP_ERP_TLV_KEYNAME_NAI)
8564             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8565                                4 + 1 + 1 + len(payload),
8566                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8567 
8568         idx += 1
8569         if ctx['num'] == idx:
8570             logger.info("Test: Truncated TLV keyName-NAI")
8571             payload = struct.pack("BB", EAP_ERP_TLV_KEYNAME_NAI, 1)
8572             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8573                                4 + 1 + 1 + len(payload),
8574                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8575 
8576         idx += 1
8577         if ctx['num'] == idx:
8578             logger.info("Test: Valid rRK lifetime TV followed by too short rMSK lifetime TV")
8579             payload = struct.pack(">BLBH", EAP_ERP_TV_RRK_LIFETIME, 0,
8580                                   EAP_ERP_TV_RMSK_LIFETIME, 0)
8581             return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
8582                                4 + 1 + 1 + len(payload),
8583                                EAP_ERP_TYPE_REAUTH_START, 0) + payload
8584 
8585         idx += 1
8586         if ctx['num'] == idx:
8587             logger.info("Test: Missing type (Finish)")
8588             return struct.pack(">BBH", EAP_CODE_FINISH, ctx['id'], 4)
8589 
8590         idx += 1
8591         if ctx['num'] == idx:
8592             logger.info("Test: Unexpected type (Finish)")
8593             return struct.pack(">BBHB", EAP_CODE_FINISH, ctx['id'], 4 + 1,
8594                                255)
8595 
8596         idx += 1
8597         if ctx['num'] == idx:
8598             logger.info("Test: Missing fields (Finish)")
8599             return struct.pack(">BBHB", EAP_CODE_FINISH, ctx['id'], 4 + 1,
8600                                EAP_ERP_TYPE_REAUTH)
8601 
8602         idx += 1
8603         if ctx['num'] == idx:
8604             logger.info("Test: Unexpected SEQ (Finish)")
8605             return struct.pack(">BBHBBHB", EAP_CODE_FINISH, ctx['id'],
8606                                4 + 1 + 4,
8607                                EAP_ERP_TYPE_REAUTH, 0, 0xffff, 0)
8608 
8609         logger.info("No more test responses available - test case completed")
8610         global eap_proto_erp_test_done
8611         eap_proto_erp_test_done = True
8612         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
8613 
8614     srv = start_radius_server(erp_handler)
8615 
8616     try:
8617         hapd = start_ap(apdev[0])
8618         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8619 
8620         i = 0
8621         while not eap_proto_erp_test_done:
8622             i += 1
8623             logger.info("Running connection iteration %d" % i)
8624             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8625                            eap="PAX", identity="pax.user@example.com",
8626                            password_hex="0123456789abcdef0123456789abcdef",
8627                            wait_connect=False)
8628             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
8629             if ev is None:
8630                 raise Exception("Timeout on EAP start")
8631             time.sleep(0.1)
8632             dev[0].request("REMOVE_NETWORK all")
8633             dev[0].wait_disconnected(timeout=1)
8634             dev[0].dump_monitor()
8635     finally:
8636         stop_radius_server(srv)
8637 
8638 def test_eap_proto_fast_errors(dev, apdev):
8639     """EAP-FAST local error cases"""
8640     check_eap_capa(dev[0], "FAST")
8641     params = hostapd.wpa2_eap_params(ssid="eap-test")
8642     hapd = hostapd.add_ap(apdev[0], params)
8643     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8644 
8645     for i in range(1, 5):
8646         with alloc_fail(dev[0], i, "eap_fast_init"):
8647             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8648                            eap="FAST", anonymous_identity="FAST",
8649                            identity="user", password="password",
8650                            ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
8651                            phase1="fast_provisioning=2",
8652                            pac_file="blob://fast_pac_auth",
8653                            wait_connect=False)
8654             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
8655                                    timeout=5)
8656             if ev is None:
8657                 raise Exception("Timeout on EAP start")
8658             dev[0].request("REMOVE_NETWORK all")
8659             dev[0].wait_disconnected()
8660 
8661     tests = [(1, "wpabuf_alloc;eap_fast_tlv_eap_payload"),
8662              (1, "eap_fast_derive_key;eap_fast_derive_key_auth"),
8663              (1, "eap_msg_alloc;eap_peer_tls_phase2_nak"),
8664              (1, "wpabuf_alloc;eap_fast_tlv_result"),
8665              (1, "wpabuf_alloc;eap_fast_tlv_pac_ack"),
8666              (1, "=eap_peer_tls_derive_session_id;eap_fast_process_crypto_binding"),
8667              (1, "eap_peer_tls_decrypt;eap_fast_decrypt"),
8668              (1, "eap_fast_getKey"),
8669              (1, "eap_fast_get_session_id"),
8670              (1, "eap_fast_get_emsk")]
8671     for count, func in tests:
8672         dev[0].request("SET blob fast_pac_auth_errors ")
8673         with alloc_fail(dev[0], count, func):
8674             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8675                            eap="FAST", anonymous_identity="FAST",
8676                            identity="user@example.com", password="password",
8677                            ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
8678                            phase1="fast_provisioning=2",
8679                            pac_file="blob://fast_pac_auth_errors",
8680                            erp="1",
8681                            wait_connect=False)
8682             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8683                                    timeout=15)
8684             if ev is None:
8685                 raise Exception("Timeout on EAP start")
8686             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8687             dev[0].request("REMOVE_NETWORK all")
8688             dev[0].wait_disconnected()
8689 
8690     tests = [(1, "eap_fast_derive_key;eap_fast_derive_key_provisioning"),
8691              (1, "eap_mschapv2_getKey;eap_fast_get_phase2_key"),
8692              (1, "=eap_fast_use_pac_opaque"),
8693              (1, "eap_fast_copy_buf"),
8694              (1, "=eap_fast_add_pac"),
8695              (1, "=eap_fast_init_pac_data"),
8696              (1, "=eap_fast_write_pac"),
8697              (2, "=eap_fast_write_pac")]
8698     for count, func in tests:
8699         dev[0].request("SET blob fast_pac_errors ")
8700         with alloc_fail(dev[0], count, func):
8701             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8702                            eap="FAST", anonymous_identity="FAST",
8703                            identity="user", password="password",
8704                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8705                            phase1="fast_provisioning=1",
8706                            pac_file="blob://fast_pac_errors",
8707                            erp="1",
8708                            wait_connect=False)
8709             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8710                                    timeout=15)
8711             if ev is None:
8712                 raise Exception("Timeout on EAP start")
8713             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8714             dev[0].request("REMOVE_NETWORK all")
8715             dev[0].wait_disconnected()
8716 
8717     tests = [(1, "eap_fast_get_cmk;eap_fast_process_crypto_binding"),
8718              (1, "eap_fast_derive_eap_msk;eap_fast_process_crypto_binding"),
8719              (1, "eap_fast_derive_eap_emsk;eap_fast_process_crypto_binding")]
8720     for count, func in tests:
8721         dev[0].request("SET blob fast_pac_auth_errors ")
8722         with fail_test(dev[0], count, func):
8723             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8724                            eap="FAST", anonymous_identity="FAST",
8725                            identity="user", password="password",
8726                            ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
8727                            phase1="fast_provisioning=2",
8728                            pac_file="blob://fast_pac_auth_errors",
8729                            erp="1",
8730                            wait_connect=False)
8731             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8732                                    timeout=15)
8733             if ev is None:
8734                 raise Exception("Timeout on EAP start")
8735             wait_fail_trigger(dev[0], "GET_FAIL")
8736             dev[0].request("REMOVE_NETWORK all")
8737             dev[0].wait_disconnected()
8738 
8739     dev[0].request("SET blob fast_pac_errors ")
8740     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8741                    eap="FAST", anonymous_identity="FAST",
8742                    identity="user", password="password",
8743                    ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
8744                    phase1="fast_provisioning=1",
8745                    pac_file="blob://fast_pac_errors",
8746                    wait_connect=False)
8747     ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
8748     if ev is None:
8749         raise Exception("Timeout on EAP start")
8750     # EAP-FAST: Only EAP-MSCHAPv2 is allowed during unauthenticated
8751     # provisioning; reject phase2 type 6
8752     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
8753     if ev is None:
8754         raise Exception("Timeout on EAP failure")
8755     dev[0].request("REMOVE_NETWORK all")
8756     dev[0].wait_disconnected()
8757 
8758     logger.info("Wrong password in Phase 2")
8759     dev[0].request("SET blob fast_pac_errors ")
8760     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8761                    eap="FAST", anonymous_identity="FAST",
8762                    identity="user", password="wrong password",
8763                    ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8764                    phase1="fast_provisioning=1",
8765                    pac_file="blob://fast_pac_errors",
8766                    wait_connect=False)
8767     ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
8768     if ev is None:
8769         raise Exception("Timeout on EAP start")
8770     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
8771     if ev is None:
8772         raise Exception("Timeout on EAP failure")
8773     dev[0].request("REMOVE_NETWORK all")
8774     dev[0].wait_disconnected()
8775 
8776     tests = ["FOOBAR\n",
8777              "wpa_supplicant EAP-FAST PAC file - version 1\nFOOBAR\n",
8778              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\n",
8779              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nSTART\n",
8780              "wpa_supplicant EAP-FAST PAC file - version 1\nEND\n",
8781              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Type=12345\nEND\n"
8782              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=12\nEND\n",
8783              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=1\nEND\n",
8784              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=1q\nEND\n",
8785              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Opaque=1\nEND\n",
8786              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nA-ID=1\nEND\n",
8787              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nI-ID=1\nEND\n",
8788              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nA-ID-Info=1\nEND\n"]
8789     for pac in tests:
8790         blob = binascii.hexlify(pac.encode()).decode()
8791         dev[0].request("SET blob fast_pac_errors " + blob)
8792         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8793                        eap="FAST", anonymous_identity="FAST",
8794                        identity="user", password="password",
8795                        ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
8796                        phase1="fast_provisioning=2",
8797                        pac_file="blob://fast_pac_errors",
8798                        wait_connect=False)
8799         ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
8800                                timeout=5)
8801         if ev is None:
8802             raise Exception("Timeout on EAP start")
8803         dev[0].request("REMOVE_NETWORK all")
8804         dev[0].wait_disconnected()
8805 
8806     tests = ["wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nEND\n",
8807              "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nEND\nSTART\nEND\nSTART\nEND\n"]
8808     for pac in tests:
8809         blob = binascii.hexlify(pac.encode()).decode()
8810         dev[0].request("SET blob fast_pac_errors " + blob)
8811         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8812                        eap="FAST", anonymous_identity="FAST",
8813                        identity="user", password="password",
8814                        ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
8815                        phase1="fast_provisioning=2",
8816                        pac_file="blob://fast_pac_errors")
8817         dev[0].request("REMOVE_NETWORK all")
8818         dev[0].wait_disconnected()
8819 
8820     dev[0].request("SET blob fast_pac_errors ")
8821 
8822 def test_eap_proto_peap_errors_server(dev, apdev):
8823     """EAP-PEAP local error cases on server"""
8824     params = int_eap_server_params()
8825     hapd = hostapd.add_ap(apdev[0], params)
8826     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8827 
8828     tests = [(1, "get_asymetric_start_key;eap_mschapv2_getKey"),
8829              (1, "generate_authenticator_response_pwhash;eap_mschapv2_process_response"),
8830              (1, "hash_nt_password_hash;eap_mschapv2_process_response"),
8831              (1, "get_master_key;eap_mschapv2_process_response")]
8832     for count, func in tests:
8833         with fail_test(hapd, count, func):
8834             dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
8835                            scan_freq="2412",
8836                            eap="PEAP", anonymous_identity="peap",
8837                            identity="user", password="password",
8838                            phase1="peapver=0 crypto_binding=2",
8839                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8840                            erp="1", wait_connect=False)
8841             ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
8842             if ev is None:
8843                 raise Exception("EAP-Failure not reported")
8844             dev[0].request("REMOVE_NETWORK all")
8845             dev[0].wait_disconnected()
8846 
8847 def test_eap_proto_peap_errors(dev, apdev):
8848     """EAP-PEAP local error cases"""
8849     check_eap_capa(dev[0], "PEAP")
8850     check_eap_capa(dev[0], "MSCHAPV2")
8851     params = hostapd.wpa2_eap_params(ssid="eap-test")
8852     hapd = hostapd.add_ap(apdev[0], params)
8853     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8854 
8855     for i in range(1, 5):
8856         with alloc_fail(dev[0], i, "eap_peap_init"):
8857             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8858                            eap="PEAP", anonymous_identity="peap",
8859                            identity="user", password="password",
8860                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8861                            wait_connect=False)
8862             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
8863                                    timeout=5)
8864             if ev is None:
8865                 raise Exception("Timeout on EAP start")
8866             dev[0].request("REMOVE_NETWORK all")
8867             dev[0].wait_disconnected()
8868 
8869     tests = [(1, "eap_mschapv2_getKey;eap_peap_get_isk;eap_peap_derive_cmk"),
8870              (1, "eap_msg_alloc;eap_tlv_build_result"),
8871              (1, "eap_mschapv2_init;eap_peap_phase2_request"),
8872              (1, "eap_peer_tls_decrypt;eap_peap_decrypt"),
8873              (1, "wpabuf_alloc;=eap_peap_decrypt"),
8874              (1, "eap_peer_tls_encrypt;eap_peap_decrypt"),
8875              (1, "eap_peer_tls_process_helper;eap_peap_process"),
8876              (1, "eap_peer_tls_derive_key;eap_peap_process"),
8877              (1, "eap_peer_tls_derive_session_id;eap_peap_process"),
8878              (1, "eap_peap_getKey"),
8879              (1, "eap_peap_get_session_id")]
8880     for count, func in tests:
8881         with alloc_fail(dev[0], count, func):
8882             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8883                            eap="PEAP", anonymous_identity="peap",
8884                            identity="user", password="password",
8885                            phase1="peapver=0 crypto_binding=2",
8886                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8887                            erp="1", wait_connect=False)
8888             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8889                                    timeout=15)
8890             if ev is None:
8891                 raise Exception("Timeout on EAP start")
8892             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8893             dev[0].request("REMOVE_NETWORK all")
8894             dev[0].wait_disconnected()
8895 
8896     tests = [(1, "peap_prfplus;eap_peap_derive_cmk"),
8897              (1, "eap_tlv_add_cryptobinding;eap_tlv_build_result"),
8898              (1, "peap_prfplus;eap_peap_getKey"),
8899              (1, "get_asymetric_start_key;eap_mschapv2_getKey")]
8900     for count, func in tests:
8901         with fail_test(dev[0], count, func):
8902             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8903                            eap="PEAP", anonymous_identity="peap",
8904                            identity="user", password="password",
8905                            phase1="peapver=0 crypto_binding=2",
8906                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8907                            erp="1", wait_connect=False)
8908             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
8909                                    timeout=15)
8910             if ev is None:
8911                 raise Exception("Timeout on EAP start")
8912             wait_fail_trigger(dev[0], "GET_FAIL")
8913             dev[0].request("REMOVE_NETWORK all")
8914             dev[0].wait_disconnected()
8915 
8916     with alloc_fail(dev[0], 1,
8917                     "eap_peer_tls_phase2_nak;eap_peap_phase2_request"):
8918         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8919                        eap="PEAP", anonymous_identity="peap",
8920                        identity="cert user", password="password",
8921                        ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
8922                        wait_connect=False)
8923         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
8924         dev[0].request("REMOVE_NETWORK all")
8925         dev[0].wait_disconnected()
8926 
8927 def test_eap_proto_ttls_errors(dev, apdev):
8928     """EAP-TTLS local error cases"""
8929     check_eap_capa(dev[0], "TTLS")
8930     check_eap_capa(dev[0], "MSCHAPV2")
8931     params = hostapd.wpa2_eap_params(ssid="eap-test")
8932     hapd = hostapd.add_ap(apdev[0], params)
8933     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
8934 
8935     for i in range(1, 5):
8936         with alloc_fail(dev[0], i, "eap_ttls_init"):
8937             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
8938                            eap="TTLS", anonymous_identity="ttls",
8939                            identity="user", password="password",
8940                            ca_cert="auth_serv/ca.pem",
8941                            phase2="autheap=MSCHAPV2",
8942                            wait_connect=False)
8943             ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
8944                                    timeout=5)
8945             if ev is None:
8946                 raise Exception("Timeout on EAP start")
8947             dev[0].request("REMOVE_NETWORK all")
8948             dev[0].wait_disconnected()
8949 
8950     tests = [(1, "eap_peer_tls_derive_key;eap_ttls_v0_derive_key",
8951               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8952              (1, "eap_peer_tls_derive_session_id;eap_ttls_v0_derive_key",
8953               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8954              (1, "wpabuf_alloc;eap_ttls_phase2_request_mschapv2",
8955               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8956              (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_mschapv2",
8957               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8958              (1, "eap_peer_tls_encrypt;eap_ttls_encrypt_response;eap_ttls_implicit_identity_request",
8959               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8960              (1, "eap_peer_tls_decrypt;eap_ttls_decrypt",
8961               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8962              (1, "eap_ttls_getKey",
8963               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8964              (1, "eap_ttls_get_session_id",
8965               "DOMAIN\\mschapv2 user", "auth=MSCHAPV2"),
8966              (1, "eap_ttls_get_emsk",
8967               "mschapv2 user@domain", "auth=MSCHAPV2"),
8968              (1, "wpabuf_alloc;eap_ttls_phase2_request_mschap",
8969               "mschap user", "auth=MSCHAP"),
8970              (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_mschap",
8971               "mschap user", "auth=MSCHAP"),
8972              (1, "wpabuf_alloc;eap_ttls_phase2_request_chap",
8973               "chap user", "auth=CHAP"),
8974              (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_chap",
8975               "chap user", "auth=CHAP"),
8976              (1, "wpabuf_alloc;eap_ttls_phase2_request_pap",
8977               "pap user", "auth=PAP"),
8978              (1, "wpabuf_alloc;eap_ttls_avp_encapsulate",
8979               "user", "autheap=MSCHAPV2"),
8980              (1, "eap_mschapv2_init;eap_ttls_phase2_request_eap_method",
8981               "user", "autheap=MSCHAPV2"),
8982              (1, "eap_sm_buildIdentity;eap_ttls_phase2_request_eap",
8983               "user", "autheap=MSCHAPV2"),
8984              (1, "eap_ttls_avp_encapsulate;eap_ttls_phase2_request_eap",
8985               "user", "autheap=MSCHAPV2"),
8986              (1, "eap_ttls_parse_attr_eap",
8987               "user", "autheap=MSCHAPV2"),
8988              (1, "eap_peer_tls_encrypt;eap_ttls_encrypt_response;eap_ttls_process_decrypted",
8989               "user", "autheap=MSCHAPV2"),
8990              (1, "eap_ttls_fake_identity_request",
8991               "user", "autheap=MSCHAPV2"),
8992              (1, "eap_msg_alloc;eap_tls_process_output",
8993               "user", "autheap=MSCHAPV2"),
8994              (1, "eap_msg_alloc;eap_peer_tls_build_ack",
8995               "user", "autheap=MSCHAPV2"),
8996              (1, "eap_peer_tls_phase2_nak;eap_ttls_phase2_request_eap_method",
8997               "cert user", "autheap=MSCHAPV2")]
8998     tls = dev[0].request("GET tls_library")
8999     if tls.startswith("internal"):
9000         tests += [(1, "tlsv1_client_decrypt;eap_peer_tls_decrypt",
9001                    "user", "autheap=MSCHAPV2")]
9002     else:
9003         tests += [(1, "tls_connection_decrypt;eap_peer_tls_decrypt",
9004                    "user", "autheap=MSCHAPV2")]
9005     for count, func, identity, phase2 in tests:
9006         with alloc_fail(dev[0], count, func):
9007             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9008                            eap="TTLS", anonymous_identity="ttls",
9009                            identity=identity, password="password",
9010                            ca_cert="auth_serv/ca.pem", phase2=phase2,
9011                            erp="1", wait_connect=False)
9012             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
9013                                    timeout=15)
9014             if ev is None:
9015                 raise Exception("Timeout on EAP start")
9016             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
9017                               note="Allocation failure not triggered for: %d:%s" % (count, func))
9018             dev[0].request("REMOVE_NETWORK all")
9019             dev[0].wait_disconnected()
9020 
9021     tests = [(1, "os_get_random;eap_ttls_phase2_request_mschapv2"),
9022              (1, "mschapv2_derive_response;eap_ttls_phase2_request_mschapv2")]
9023     for count, func in tests:
9024         with fail_test(dev[0], count, func):
9025             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9026                            eap="TTLS", anonymous_identity="ttls",
9027                            identity="DOMAIN\\mschapv2 user",
9028                            password="password",
9029                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
9030                            erp="1", wait_connect=False)
9031             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
9032                                    timeout=15)
9033             if ev is None:
9034                 raise Exception("Timeout on EAP start")
9035             wait_fail_trigger(dev[0], "GET_FAIL",
9036                               note="Test failure not triggered for: %d:%s" % (count, func))
9037             dev[0].request("REMOVE_NETWORK all")
9038             dev[0].wait_disconnected()
9039 
9040     tests = [(1, "nt_challenge_response;eap_ttls_phase2_request_mschap")]
9041     for count, func in tests:
9042         with fail_test(dev[0], count, func):
9043             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9044                            eap="TTLS", anonymous_identity="ttls",
9045                            identity="mschap user", password="password",
9046                            ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
9047                            erp="1", wait_connect=False)
9048             ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
9049                                    timeout=15)
9050             if ev is None:
9051                 raise Exception("Timeout on EAP start")
9052             wait_fail_trigger(dev[0], "GET_FAIL",
9053                               note="Test failure not triggered for: %d:%s" % (count, func))
9054             dev[0].request("REMOVE_NETWORK all")
9055             dev[0].wait_disconnected()
9056 
9057 def test_eap_proto_expanded(dev, apdev):
9058     """EAP protocol tests with expanded header"""
9059     global eap_proto_expanded_test_done
9060     eap_proto_expanded_test_done = False
9061 
9062     def expanded_handler(ctx, req):
9063         logger.info("expanded_handler - RX " + binascii.hexlify(req).decode())
9064         if 'num' not in ctx:
9065             ctx['num'] = 0
9066         ctx['num'] += 1
9067         if 'id' not in ctx:
9068             ctx['id'] = 1
9069         ctx['id'] = (ctx['id'] + 1) % 256
9070         idx = 0
9071 
9072         idx += 1
9073         if ctx['num'] == idx:
9074             logger.info("Test: MD5 challenge in expanded header")
9075             return struct.pack(">BBHB3BLBBB", EAP_CODE_REQUEST, ctx['id'],
9076                                4 + 1 + 3 + 4 + 3,
9077                                EAP_TYPE_EXPANDED, 0, 0, 0, EAP_TYPE_MD5,
9078                                1, 0xaa, ord('n'))
9079         idx += 1
9080         if ctx['num'] == idx:
9081             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9082 
9083         idx += 1
9084         if ctx['num'] == idx:
9085             logger.info("Test: Invalid expanded EAP length")
9086             return struct.pack(">BBHB3BH", EAP_CODE_REQUEST, ctx['id'],
9087                                4 + 1 + 3 + 2,
9088                                EAP_TYPE_EXPANDED, 0, 0, 0, EAP_TYPE_MD5)
9089         idx += 1
9090         if ctx['num'] == idx:
9091             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9092 
9093         idx += 1
9094         if ctx['num'] == idx:
9095             logger.info("Test: Invalid expanded frame type")
9096             return struct.pack(">BBHB3BL", EAP_CODE_REQUEST, ctx['id'],
9097                                4 + 1 + 3 + 4,
9098                                EAP_TYPE_EXPANDED, 0, 0, 1, EAP_TYPE_MD5)
9099         idx += 1
9100         if ctx['num'] == idx:
9101             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9102 
9103         idx += 1
9104         if ctx['num'] == idx:
9105             logger.info("Test: MSCHAPv2 Challenge")
9106             return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
9107                                4 + 1 + 4 + 1 + 16 + 6,
9108                                EAP_TYPE_MSCHAPV2,
9109                                1, 0, 4 + 1 + 16 + 6, 16) + 16*b'A' + b'foobar'
9110         idx += 1
9111         if ctx['num'] == idx:
9112             logger.info("Test: Invalid expanded frame type")
9113             return struct.pack(">BBHB3BL", EAP_CODE_REQUEST, ctx['id'],
9114                                4 + 1 + 3 + 4,
9115                                EAP_TYPE_EXPANDED, 0, 0, 1, EAP_TYPE_MSCHAPV2)
9116 
9117         logger.info("No more test responses available - test case completed")
9118         global eap_proto_expanded_test_done
9119         eap_proto_expanded_test_done = True
9120         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9121 
9122     srv = start_radius_server(expanded_handler)
9123 
9124     try:
9125         hapd = start_ap(apdev[0])
9126         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9127 
9128         i = 0
9129         while not eap_proto_expanded_test_done:
9130             i += 1
9131             logger.info("Running connection iteration %d" % i)
9132             if i == 4:
9133                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9134                                eap="MSCHAPV2", identity="user",
9135                                password="password",
9136                                wait_connect=False)
9137             else:
9138                 dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9139                                eap="MD5", identity="user", password="password",
9140                                wait_connect=False)
9141             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
9142             if ev is None:
9143                 raise Exception("Timeout on EAP start")
9144             if i in [1]:
9145                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
9146                 if ev is None:
9147                     raise Exception("Timeout on EAP method start")
9148                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9149                 if ev is None:
9150                     raise Exception("Timeout on EAP failure")
9151             elif i in [2, 3]:
9152                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
9153                                        timeout=5)
9154                 if ev is None:
9155                     raise Exception("Timeout on EAP proposed method")
9156                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9157                 if ev is None:
9158                     raise Exception("Timeout on EAP failure")
9159             else:
9160                 time.sleep(0.1)
9161             dev[0].request("REMOVE_NETWORK all")
9162             dev[0].wait_disconnected(timeout=1)
9163             dev[0].dump_monitor()
9164     finally:
9165         stop_radius_server(srv)
9166 
9167 def test_eap_proto_tls(dev, apdev):
9168     """EAP-TLS protocol tests"""
9169     check_eap_capa(dev[0], "TLS")
9170     global eap_proto_tls_test_done, eap_proto_tls_test_wait
9171     eap_proto_tls_test_done = False
9172     eap_proto_tls_test_wait = False
9173 
9174     def tls_handler(ctx, req):
9175         logger.info("tls_handler - RX " + binascii.hexlify(req).decode())
9176         if 'num' not in ctx:
9177             ctx['num'] = 0
9178         ctx['num'] += 1
9179         if 'id' not in ctx:
9180             ctx['id'] = 1
9181         ctx['id'] = (ctx['id'] + 1) % 256
9182         idx = 0
9183 
9184         global eap_proto_tls_test_wait
9185 
9186         idx += 1
9187         if ctx['num'] == idx:
9188             logger.info("Test: Too much payload in TLS/Start: TLS Message Length (0 bytes) smaller than this fragment (1 bytes)")
9189             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
9190                                4 + 1 + 1 + 4 + 1,
9191                                EAP_TYPE_TLS, 0xa0, 0, 1)
9192 
9193         idx += 1
9194         if ctx['num'] == idx:
9195             logger.info("Test: Fragmented TLS/Start")
9196             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
9197                                4 + 1 + 1 + 4 + 1,
9198                                EAP_TYPE_TLS, 0xe0, 2, 1)
9199         idx += 1
9200         if ctx['num'] == idx:
9201             logger.info("Test: Too long fragment of TLS/Start: Invalid reassembly state: tls_in_left=2 tls_in_len=0 in_len=0")
9202             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
9203                                4 + 1 + 1 + 2,
9204                                EAP_TYPE_TLS, 0x00, 2, 3)
9205         idx += 1
9206         if ctx['num'] == idx:
9207             logger.info("Test: EAP-Failure")
9208             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9209 
9210         idx += 1
9211         if ctx['num'] == idx:
9212             logger.info("Test: TLS/Start")
9213             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9214                                4 + 1 + 1,
9215                                EAP_TYPE_TLS, 0x20)
9216         idx += 1
9217         if ctx['num'] == idx:
9218             logger.info("Test: Fragmented TLS message")
9219             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
9220                                4 + 1 + 1 + 4 + 1,
9221                                EAP_TYPE_TLS, 0xc0, 2, 1)
9222         idx += 1
9223         if ctx['num'] == idx:
9224             logger.info("Test: Invalid TLS message: no Flags octet included + workaround")
9225             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
9226                                4 + 1,
9227                                EAP_TYPE_TLS)
9228         idx += 1
9229         if ctx['num'] == idx:
9230             logger.info("Test: Too long fragment of TLS message: more data than TLS message length indicated")
9231             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
9232                                4 + 1 + 1 + 2,
9233                                EAP_TYPE_TLS, 0x00, 2, 3)
9234         idx += 1
9235         if ctx['num'] == idx:
9236             logger.info("Test: EAP-Failure")
9237             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9238 
9239         idx += 1
9240         if ctx['num'] == idx:
9241             logger.info("Test: Fragmented TLS/Start and truncated Message Length field")
9242             return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
9243                                4 + 1 + 1 + 3,
9244                                EAP_TYPE_TLS, 0xe0, 1, 2, 3)
9245 
9246         idx += 1
9247         if ctx['num'] == idx:
9248             logger.info("Test: TLS/Start")
9249             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9250                                4 + 1 + 1,
9251                                EAP_TYPE_TLS, 0x20)
9252         idx += 1
9253         if ctx['num'] == idx:
9254             logger.info("Test: Fragmented TLS message")
9255             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
9256                                4 + 1 + 1 + 4 + 1,
9257                                EAP_TYPE_TLS, 0xc0, 2, 1)
9258         idx += 1
9259         if ctx['num'] == idx:
9260             logger.info("Test: Invalid TLS message: no Flags octet included + workaround disabled")
9261             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
9262                                4 + 1,
9263                                EAP_TYPE_TLS)
9264 
9265         idx += 1
9266         if ctx['num'] == idx:
9267             logger.info("Test: TLS/Start")
9268             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9269                                4 + 1 + 1,
9270                                EAP_TYPE_TLS, 0x20)
9271         idx += 1
9272         if ctx['num'] == idx:
9273             logger.info("Test: Fragmented TLS message (long; first)")
9274             payload = 1450*b'A'
9275             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
9276                                4 + 1 + 1 + 4 + len(payload),
9277                                EAP_TYPE_TLS, 0xc0, 65536) + payload
9278         # "Too long TLS fragment (size over 64 kB)" on the last one
9279         for i in range(44):
9280             idx += 1
9281             if ctx['num'] == idx:
9282                 logger.info("Test: Fragmented TLS message (long; cont %d)" % i)
9283                 eap_proto_tls_test_wait = True
9284                 payload = 1470*b'A'
9285                 return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9286                                    4 + 1 + 1 + len(payload),
9287                                    EAP_TYPE_TLS, 0x40) + payload
9288         eap_proto_tls_test_wait = False
9289         idx += 1
9290         if ctx['num'] == idx:
9291             logger.info("Test: EAP-Failure")
9292             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9293 
9294         idx += 1
9295         if ctx['num'] == idx:
9296             logger.info("Test: TLS/Start")
9297             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9298                                4 + 1 + 1,
9299                                EAP_TYPE_TLS, 0x20)
9300         idx += 1
9301         if ctx['num'] == idx:
9302             logger.info("Test: Non-ACK to more-fragment message")
9303             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
9304                                4 + 1 + 1 + 1,
9305                                EAP_TYPE_TLS, 0x00, 255)
9306         idx += 1
9307         if ctx['num'] == idx:
9308             logger.info("Test: EAP-Failure")
9309             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9310 
9311         logger.info("No more test responses available - test case completed")
9312         global eap_proto_tls_test_done
9313         eap_proto_tls_test_done = True
9314         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9315 
9316     srv = start_radius_server(tls_handler)
9317 
9318     try:
9319         hapd = start_ap(apdev[0])
9320         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9321 
9322         i = 0
9323         while not eap_proto_tls_test_done:
9324             i += 1
9325             logger.info("Running connection iteration %d" % i)
9326             workaround = "0" if i == 6 else "1"
9327             fragment_size = "100" if i == 8 else "1400"
9328             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9329                            eap="TLS", identity="tls user",
9330                            ca_cert="auth_serv/ca.pem",
9331                            client_cert="auth_serv/user.pem",
9332                            private_key="auth_serv/user.key",
9333                            eap_workaround=workaround,
9334                            fragment_size=fragment_size,
9335                            wait_connect=False)
9336             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
9337             if ev is None:
9338                 raise Exception("Timeout on EAP start")
9339             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD",
9340                                     "CTRL-EVENT-EAP-STATUS"], timeout=5)
9341             if ev is None:
9342                 raise Exception("Timeout on EAP method start")
9343             time.sleep(0.1)
9344             start = os.times()[4]
9345             while eap_proto_tls_test_wait:
9346                 now = os.times()[4]
9347                 if now - start > 10:
9348                     break
9349                 time.sleep(0.1)
9350             dev[0].request("REMOVE_NETWORK all")
9351             dev[0].wait_disconnected(timeout=1)
9352             dev[0].dump_monitor()
9353     finally:
9354         stop_radius_server(srv)
9355 
9356 def test_eap_proto_tnc(dev, apdev):
9357     """EAP-TNC protocol tests"""
9358     check_eap_capa(dev[0], "TNC")
9359     global eap_proto_tnc_test_done
9360     eap_proto_tnc_test_done = False
9361 
9362     def tnc_handler(ctx, req):
9363         logger.info("tnc_handler - RX " + binascii.hexlify(req).decode())
9364         if 'num' not in ctx:
9365             ctx['num'] = 0
9366         ctx['num'] += 1
9367         if 'id' not in ctx:
9368             ctx['id'] = 1
9369         ctx['id'] = (ctx['id'] + 1) % 256
9370         idx = 0
9371 
9372         idx += 1
9373         if ctx['num'] == idx:
9374             logger.info("Test: TNC start with unsupported version")
9375             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9376                                4 + 1 + 1,
9377                                EAP_TYPE_TNC, 0x20)
9378 
9379         idx += 1
9380         if ctx['num'] == idx:
9381             logger.info("Test: TNC without Flags field")
9382             return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
9383                                4 + 1,
9384                                EAP_TYPE_TNC)
9385 
9386         idx += 1
9387         if ctx['num'] == idx:
9388             logger.info("Test: Message underflow due to missing Message Length")
9389             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9390                                4 + 1 + 1,
9391                                EAP_TYPE_TNC, 0xa1)
9392 
9393         idx += 1
9394         if ctx['num'] == idx:
9395             logger.info("Test: Invalid Message Length")
9396             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
9397                                4 + 1 + 1 + 4 + 1,
9398                                EAP_TYPE_TNC, 0xa1, 0, 0)
9399 
9400         idx += 1
9401         if ctx['num'] == idx:
9402             logger.info("Test: Invalid Message Length")
9403             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
9404                                4 + 1 + 1 + 4,
9405                                EAP_TYPE_TNC, 0xe1, 75001)
9406 
9407         idx += 1
9408         if ctx['num'] == idx:
9409             logger.info("Test: Start with Message Length")
9410             return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
9411                                4 + 1 + 1 + 4,
9412                                EAP_TYPE_TNC, 0xa1, 1)
9413         idx += 1
9414         if ctx['num'] == idx:
9415             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9416 
9417         idx += 1
9418         if ctx['num'] == idx:
9419             logger.info("Test: Server used start flag again")
9420             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9421                                4 + 1 + 1,
9422                                EAP_TYPE_TNC, 0x21)
9423         idx += 1
9424         if ctx['num'] == idx:
9425             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9426                                4 + 1 + 1,
9427                                EAP_TYPE_TNC, 0x21)
9428 
9429         idx += 1
9430         if ctx['num'] == idx:
9431             logger.info("Test: Fragmentation and unexpected payload in ack")
9432             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9433                                4 + 1 + 1,
9434                                EAP_TYPE_TNC, 0x21)
9435         idx += 1
9436         if ctx['num'] == idx:
9437             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9438                                4 + 1 + 1,
9439                                EAP_TYPE_TNC, 0x01)
9440         idx += 1
9441         if ctx['num'] == idx:
9442             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
9443                                4 + 1 + 1 + 1,
9444                                EAP_TYPE_TNC, 0x01, 0)
9445 
9446         idx += 1
9447         if ctx['num'] == idx:
9448             logger.info("Test: Server fragmenting and fragment overflow")
9449             return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
9450                                4 + 1 + 1 + 4 + 1,
9451                                EAP_TYPE_TNC, 0xe1, 2, 1)
9452         idx += 1
9453         if ctx['num'] == idx:
9454             return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
9455                                4 + 1 + 1 + 2,
9456                                EAP_TYPE_TNC, 0x01, 2, 3)
9457 
9458         idx += 1
9459         if ctx['num'] == idx:
9460             logger.info("Test: Server fragmenting and no message length in a fragment")
9461             return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
9462                                4 + 1 + 1 + 1,
9463                                EAP_TYPE_TNC, 0x61, 2)
9464 
9465         idx += 1
9466         if ctx['num'] == idx:
9467             logger.info("Test: TNC start followed by invalid TNCCS-Batch")
9468             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9469                                4 + 1 + 1,
9470                                EAP_TYPE_TNC, 0x21)
9471         idx += 1
9472         if ctx['num'] == idx:
9473             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9474             resp = b"FOO"
9475             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9476                                4 + 1 + 1 + len(resp),
9477                                EAP_TYPE_TNC, 0x01) + resp
9478 
9479         idx += 1
9480         if ctx['num'] == idx:
9481             logger.info("Test: TNC start followed by invalid TNCCS-Batch (2)")
9482             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9483                                4 + 1 + 1,
9484                                EAP_TYPE_TNC, 0x21)
9485         idx += 1
9486         if ctx['num'] == idx:
9487             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9488             resp = b"</TNCCS-Batch><TNCCS-Batch>"
9489             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9490                                4 + 1 + 1 + len(resp),
9491                                EAP_TYPE_TNC, 0x01) + resp
9492 
9493         idx += 1
9494         if ctx['num'] == idx:
9495             logger.info("Test: TNCCS-Batch missing BatchId attribute")
9496             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9497                                4 + 1 + 1,
9498                                EAP_TYPE_TNC, 0x21)
9499         idx += 1
9500         if ctx['num'] == idx:
9501             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9502             resp = b"<TNCCS-Batch    foo=3></TNCCS-Batch>"
9503             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9504                                4 + 1 + 1 + len(resp),
9505                                EAP_TYPE_TNC, 0x01) + resp
9506 
9507         idx += 1
9508         if ctx['num'] == idx:
9509             logger.info("Test: Unexpected IF-TNCCS BatchId")
9510             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9511                                4 + 1 + 1,
9512                                EAP_TYPE_TNC, 0x21)
9513         idx += 1
9514         if ctx['num'] == idx:
9515             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9516             resp = b"<TNCCS-Batch    BatchId=123456789></TNCCS-Batch>"
9517             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9518                                4 + 1 + 1 + len(resp),
9519                                EAP_TYPE_TNC, 0x01) + resp
9520 
9521         idx += 1
9522         if ctx['num'] == idx:
9523             logger.info("Test: Missing IMC-IMV-Message and TNCC-TNCS-Message end tags")
9524             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9525                                4 + 1 + 1,
9526                                EAP_TYPE_TNC, 0x21)
9527         idx += 1
9528         if ctx['num'] == idx:
9529             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9530             resp = b"<TNCCS-Batch BatchId=2><IMC-IMV-Message><TNCC-TNCS-Message></TNCCS-Batch>"
9531             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9532                                4 + 1 + 1 + len(resp),
9533                                EAP_TYPE_TNC, 0x01) + resp
9534         idx += 1
9535         if ctx['num'] == idx:
9536             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9537 
9538         idx += 1
9539         if ctx['num'] == idx:
9540             logger.info("Test: Missing IMC-IMV-Message and TNCC-TNCS-Message Type")
9541             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9542                                4 + 1 + 1,
9543                                EAP_TYPE_TNC, 0x21)
9544         idx += 1
9545         if ctx['num'] == idx:
9546             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9547             resp = b"<TNCCS-Batch BatchId=2><IMC-IMV-Message></IMC-IMV-Message><TNCC-TNCS-Message></TNCC-TNCS-Message></TNCCS-Batch>"
9548             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9549                                4 + 1 + 1 + len(resp),
9550                                EAP_TYPE_TNC, 0x01) + resp
9551         idx += 1
9552         if ctx['num'] == idx:
9553             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9554 
9555         idx += 1
9556         if ctx['num'] == idx:
9557             logger.info("Test: Missing TNCC-TNCS-Message XML end tag")
9558             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9559                                4 + 1 + 1,
9560                                EAP_TYPE_TNC, 0x21)
9561         idx += 1
9562         if ctx['num'] == idx:
9563             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9564             resp = b"<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML></TNCC-TNCS-Message></TNCCS-Batch>"
9565             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9566                                4 + 1 + 1 + len(resp),
9567                                EAP_TYPE_TNC, 0x01) + resp
9568         idx += 1
9569         if ctx['num'] == idx:
9570             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9571 
9572         idx += 1
9573         if ctx['num'] == idx:
9574             logger.info("Test: Missing TNCC-TNCS-Message Base64 start tag")
9575             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9576                                4 + 1 + 1,
9577                                EAP_TYPE_TNC, 0x21)
9578         idx += 1
9579         if ctx['num'] == idx:
9580             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9581             resp = b"<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type></TNCC-TNCS-Message></TNCCS-Batch>"
9582             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9583                                4 + 1 + 1 + len(resp),
9584                                EAP_TYPE_TNC, 0x01) + resp
9585         idx += 1
9586         if ctx['num'] == idx:
9587             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9588 
9589         idx += 1
9590         if ctx['num'] == idx:
9591             logger.info("Test: Missing TNCC-TNCS-Message Base64 end tag")
9592             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9593                                4 + 1 + 1,
9594                                EAP_TYPE_TNC, 0x21)
9595         idx += 1
9596         if ctx['num'] == idx:
9597             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9598             resp = b"<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><Base64>abc</TNCC-TNCS-Message></TNCCS-Batch>"
9599             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9600                                4 + 1 + 1 + len(resp),
9601                                EAP_TYPE_TNC, 0x01) + resp
9602         idx += 1
9603         if ctx['num'] == idx:
9604             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9605 
9606         idx += 1
9607         if ctx['num'] == idx:
9608             logger.info("Test: TNCC-TNCS-Message Base64 message")
9609             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9610                                4 + 1 + 1,
9611                                EAP_TYPE_TNC, 0x21)
9612         idx += 1
9613         if ctx['num'] == idx:
9614             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9615             resp = b"<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><Base64>aGVsbG8=</Base64></TNCC-TNCS-Message></TNCCS-Batch>"
9616             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9617                                4 + 1 + 1 + len(resp),
9618                                EAP_TYPE_TNC, 0x01) + resp
9619         idx += 1
9620         if ctx['num'] == idx:
9621             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9622 
9623         idx += 1
9624         if ctx['num'] == idx:
9625             logger.info("Test: Invalid TNCC-TNCS-Message XML message")
9626             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9627                                4 + 1 + 1,
9628                                EAP_TYPE_TNC, 0x21)
9629         idx += 1
9630         if ctx['num'] == idx:
9631             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9632             resp = b"<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML>hello</XML></TNCC-TNCS-Message></TNCCS-Batch>"
9633             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9634                                4 + 1 + 1 + len(resp),
9635                                EAP_TYPE_TNC, 0x01) + resp
9636         idx += 1
9637         if ctx['num'] == idx:
9638             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9639 
9640         idx += 1
9641         if ctx['num'] == idx:
9642             logger.info("Test: Missing TNCCS-Recommendation type")
9643             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9644                                4 + 1 + 1,
9645                                EAP_TYPE_TNC, 0x21)
9646         idx += 1
9647         if ctx['num'] == idx:
9648             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9649             resp = b'<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation foo=1></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
9650             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9651                                4 + 1 + 1 + len(resp),
9652                                EAP_TYPE_TNC, 0x01) + resp
9653         idx += 1
9654         if ctx['num'] == idx:
9655             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9656 
9657         idx += 1
9658         if ctx['num'] == idx:
9659             logger.info("Test: TNCCS-Recommendation type=none")
9660             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9661                                4 + 1 + 1,
9662                                EAP_TYPE_TNC, 0x21)
9663         idx += 1
9664         if ctx['num'] == idx:
9665             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9666             resp = b'<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation type="none"></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
9667             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9668                                4 + 1 + 1 + len(resp),
9669                                EAP_TYPE_TNC, 0x01) + resp
9670         idx += 1
9671         if ctx['num'] == idx:
9672             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9673 
9674         idx += 1
9675         if ctx['num'] == idx:
9676             logger.info("Test: TNCCS-Recommendation type=isolate")
9677             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9678                                4 + 1 + 1,
9679                                EAP_TYPE_TNC, 0x21)
9680         idx += 1
9681         if ctx['num'] == idx:
9682             logger.info("Received TNCCS-Batch: " + binascii.hexlify(req[6:]).decode())
9683             resp = b'<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation type="isolate"></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
9684             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
9685                                4 + 1 + 1 + len(resp),
9686                                EAP_TYPE_TNC, 0x01) + resp
9687         idx += 1
9688         if ctx['num'] == idx:
9689             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9690 
9691         logger.info("No more test responses available - test case completed")
9692         global eap_proto_tnc_test_done
9693         eap_proto_tnc_test_done = True
9694         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9695 
9696     srv = start_radius_server(tnc_handler)
9697 
9698     try:
9699         hapd = start_ap(apdev[0])
9700         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9701 
9702         i = 0
9703         while not eap_proto_tnc_test_done:
9704             i += 1
9705             logger.info("Running connection iteration %d" % i)
9706             frag = 1400
9707             if i == 8:
9708                 frag = 150
9709             dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9710                            eap="TNC", identity="tnc", fragment_size=str(frag),
9711                            wait_connect=False)
9712             ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
9713             if ev is None:
9714                 raise Exception("Timeout on EAP start")
9715             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD",
9716                                     "CTRL-EVENT-EAP-STATUS"], timeout=5)
9717             if ev is None:
9718                 raise Exception("Timeout on EAP method start")
9719             time.sleep(0.1)
9720             dev[0].request("REMOVE_NETWORK all")
9721             dev[0].wait_disconnected(timeout=1)
9722             dev[0].dump_monitor()
9723     finally:
9724         stop_radius_server(srv)
9725 
9726 def test_eap_canned_success_after_identity(dev, apdev):
9727     """EAP protocol tests for canned EAP-Success after identity"""
9728     check_eap_capa(dev[0], "MD5")
9729     def eap_canned_success_handler(ctx, req):
9730         logger.info("eap_canned_success_handler - RX " + binascii.hexlify(req).decode())
9731         if 'num' not in ctx:
9732             ctx['num'] = 0
9733         ctx['num'] = ctx['num'] + 1
9734         if 'id' not in ctx:
9735             ctx['id'] = 1
9736         ctx['id'] = (ctx['id'] + 1) % 256
9737         idx = 0
9738 
9739         idx += 1
9740         if ctx['num'] == idx:
9741             logger.info("Test: EAP-Success")
9742             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
9743 
9744         idx += 1
9745         if ctx['num'] == idx:
9746             logger.info("Test: EAP-Success")
9747             return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
9748 
9749         return None
9750 
9751     srv = start_radius_server(eap_canned_success_handler)
9752 
9753     try:
9754         hapd = start_ap(apdev[0])
9755         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9756 
9757         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9758                        phase1="allow_canned_success=1",
9759                        eap="MD5", identity="user", password="password",
9760                        wait_connect=False)
9761         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
9762         if ev is None:
9763             raise Exception("Timeout on EAP success")
9764         dev[0].request("REMOVE_NETWORK all")
9765         dev[0].wait_disconnected()
9766 
9767         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
9768                        eap="MD5", identity="user", password="password",
9769                        wait_connect=False)
9770         ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
9771         if ev is None:
9772             raise Exception("Timeout on EAP start")
9773         ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=0.1)
9774         if ev is not None:
9775             raise Exception("Unexpected EAP success")
9776         dev[0].request("REMOVE_NETWORK all")
9777         dev[0].wait_disconnected()
9778     finally:
9779         stop_radius_server(srv)
9780 
9781 def test_eap_proto_wsc(dev, apdev):
9782     """EAP-WSC protocol tests"""
9783     global eap_proto_wsc_test_done, eap_proto_wsc_wait_failure
9784     eap_proto_wsc_test_done = False
9785 
9786     def wsc_handler(ctx, req):
9787         logger.info("wsc_handler - RX " + binascii.hexlify(req).decode())
9788         if 'num' not in ctx:
9789             ctx['num'] = 0
9790         ctx['num'] += 1
9791         if 'id' not in ctx:
9792             ctx['id'] = 1
9793         ctx['id'] = (ctx['id'] + 1) % 256
9794         idx = 0
9795 
9796         global eap_proto_wsc_wait_failure
9797         eap_proto_wsc_wait_failure = False
9798 
9799         idx += 1
9800         if ctx['num'] == idx:
9801             logger.info("Test: Missing Flags field")
9802             return struct.pack(">BBHB3BLB", EAP_CODE_REQUEST, ctx['id'],
9803                                4 + 1 + 3 + 4 + 1,
9804                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9805                                1)
9806 
9807         idx += 1
9808         if ctx['num'] == idx:
9809             logger.info("Test: Message underflow (missing Message Length field)")
9810             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9811                                4 + 1 + 3 + 4 + 2,
9812                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9813                                1, 0x02)
9814 
9815         idx += 1
9816         if ctx['num'] == idx:
9817             logger.info("Test: Invalid Message Length (> 50000)")
9818             return struct.pack(">BBHB3BLBBH", EAP_CODE_REQUEST, ctx['id'],
9819                                4 + 1 + 3 + 4 + 4,
9820                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9821                                1, 0x02, 65535)
9822 
9823         idx += 1
9824         if ctx['num'] == idx:
9825             logger.info("Test: Invalid Message Length (< current payload)")
9826             return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
9827                                4 + 1 + 3 + 4 + 5,
9828                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9829                                1, 0x02, 0, 0xff)
9830 
9831         idx += 1
9832         if ctx['num'] == idx:
9833             logger.info("Test: Unexpected Op-Code 5 in WAIT_START state")
9834             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9835                                4 + 1 + 3 + 4 + 2,
9836                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9837                                5, 0x00)
9838 
9839         idx += 1
9840         if ctx['num'] == idx:
9841             logger.info("Test: Valid WSC Start to start the sequence")
9842             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9843                                4 + 1 + 3 + 4 + 2,
9844                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9845                                1, 0x00)
9846         idx += 1
9847         if ctx['num'] == idx:
9848             logger.info("Test: No Message Length field in a fragmented packet")
9849             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9850                                4 + 1 + 3 + 4 + 2,
9851                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9852                                4, 0x01)
9853 
9854         idx += 1
9855         if ctx['num'] == idx:
9856             logger.info("Test: Valid WSC Start to start the sequence")
9857             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9858                                4 + 1 + 3 + 4 + 2,
9859                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9860                                1, 0x00)
9861         idx += 1
9862         if ctx['num'] == idx:
9863             logger.info("Test: Valid first fragmented packet")
9864             return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
9865                                4 + 1 + 3 + 4 + 5,
9866                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9867                                4, 0x03, 10, 1)
9868         idx += 1
9869         if ctx['num'] == idx:
9870             logger.info("Test: Unexpected Op-Code 5 in fragment (expected 4)")
9871             return struct.pack(">BBHB3BLBBB", EAP_CODE_REQUEST, ctx['id'],
9872                                4 + 1 + 3 + 4 + 3,
9873                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9874                                5, 0x01, 2)
9875 
9876         idx += 1
9877         if ctx['num'] == idx:
9878             logger.info("Test: Valid WSC Start to start the sequence")
9879             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9880                                4 + 1 + 3 + 4 + 2,
9881                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9882                                1, 0x00)
9883         idx += 1
9884         if ctx['num'] == idx:
9885             logger.info("Test: Valid first fragmented packet")
9886             return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
9887                                4 + 1 + 3 + 4 + 5,
9888                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9889                                4, 0x03, 2, 1)
9890         idx += 1
9891         if ctx['num'] == idx:
9892             logger.info("Test: Fragment overflow")
9893             return struct.pack(">BBHB3BLBBBB", EAP_CODE_REQUEST, ctx['id'],
9894                                4 + 1 + 3 + 4 + 4,
9895                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9896                                4, 0x01, 2, 3)
9897 
9898         idx += 1
9899         if ctx['num'] == idx:
9900             logger.info("Test: Valid WSC Start to start the sequence")
9901             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9902                                4 + 1 + 3 + 4 + 2,
9903                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9904                                1, 0x00)
9905         idx += 1
9906         if ctx['num'] == idx:
9907             logger.info("Test: Unexpected Op-Code 5 in WAIT_FRAG_ACK state")
9908             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9909                                4 + 1 + 3 + 4 + 2,
9910                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9911                                5, 0x00)
9912 
9913         idx += 1
9914         if ctx['num'] == idx:
9915             logger.info("Test: Valid WSC Start")
9916             return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
9917                                4 + 1 + 3 + 4 + 2,
9918                                EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
9919                                1, 0x00)
9920         idx += 1
9921         if ctx['num'] == idx:
9922             logger.info("No more test responses available - test case completed")
9923             global eap_proto_wsc_test_done
9924             eap_proto_wsc_test_done = True
9925             eap_proto_wsc_wait_failure = True
9926             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9927 
9928         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
9929 
9930     srv = start_radius_server(wsc_handler)
9931 
9932     try:
9933         hapd = start_ap(apdev[0])
9934         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9935 
9936         i = 0
9937         while not eap_proto_wsc_test_done:
9938             i += 1
9939             logger.info("Running connection iteration %d" % i)
9940             fragment_size = 1398 if i != 9 else 50
9941             dev[0].connect("eap-test", key_mgmt="WPA-EAP", eap="WSC",
9942                            fragment_size=str(fragment_size),
9943                            identity="WFA-SimpleConfig-Enrollee-1-0",
9944                            phase1="pin=12345670",
9945                            scan_freq="2412", wait_connect=False)
9946             ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
9947             if ev is None:
9948                 raise Exception("Timeout on EAP method start")
9949             if eap_proto_wsc_wait_failure:
9950                 ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9951                 if ev is None:
9952                     raise Exception("Timeout on EAP failure")
9953             else:
9954                 time.sleep(0.1)
9955             dev[0].request("REMOVE_NETWORK all")
9956             dev[0].wait_disconnected(timeout=1)
9957             dev[0].dump_monitor()
9958     finally:
9959         stop_radius_server(srv)
9960 
9961 def test_eap_canned_success_before_method(dev, apdev):
9962     """EAP protocol tests for canned EAP-Success before any method"""
9963     params = int_eap_server_params()
9964     hapd = hostapd.add_ap(apdev[0], params)
9965     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9966     bssid = apdev[0]['bssid']
9967     hapd.request("SET ext_eapol_frame_io 1")
9968 
9969     dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9970                    phase1="allow_canned_success=1",
9971                    eap="MD5", identity="user", password="password",
9972                    wait_connect=False)
9973 
9974     ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
9975     if ev is None:
9976         raise Exception("Timeout on EAPOL-TX from hostapd")
9977 
9978     res = dev[0].request("EAPOL_RX " + bssid + " 0200000403020004")
9979     if "OK" not in res:
9980         raise Exception("EAPOL_RX to wpa_supplicant failed")
9981 
9982     ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
9983     if ev is None:
9984         raise Exception("Timeout on EAP success")
9985     dev[0].request("REMOVE_NETWORK all")
9986     dev[0].wait_disconnected()
9987 
9988 def test_eap_canned_failure_before_method(dev, apdev):
9989     """EAP protocol tests for canned EAP-Failure before any method"""
9990     params = int_eap_server_params()
9991     hapd = hostapd.add_ap(apdev[0], params)
9992     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
9993     bssid = apdev[0]['bssid']
9994     hapd.request("SET ext_eapol_frame_io 1")
9995     dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9996                    phase1="allow_canned_success=1",
9997                    eap="MD5", identity="user", password="password",
9998                    wait_connect=False)
9999 
10000     ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
10001     if ev is None:
10002         raise Exception("Timeout on EAPOL-TX from hostapd")
10003 
10004     res = dev[0].request("EAPOL_RX " + bssid + " 0200000404020004")
10005     if "OK" not in res:
10006         raise Exception("EAPOL_RX to wpa_supplicant failed")
10007 
10008     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
10009     if ev is None:
10010         raise Exception("Timeout on EAP failure")
10011     dev[0].request("REMOVE_NETWORK all")
10012     dev[0].wait_disconnected()
10013 
10014 def test_eap_nak_oom(dev, apdev):
10015     """EAP-Nak OOM"""
10016     check_eap_capa(dev[0], "MD5")
10017     params = hostapd.wpa2_eap_params(ssid="eap-test")
10018     hapd = hostapd.add_ap(apdev[0], params)
10019     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
10020     with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sm_buildNak"):
10021         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
10022                        eap="MD5", identity="sake user", password="password",
10023                        wait_connect=False)
10024         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
10025         dev[0].request("REMOVE_NETWORK all")
10026         dev[0].wait_disconnected()
10027 
10028 def test_eap_nak_expanded(dev, apdev):
10029     """EAP-Nak with expanded method"""
10030     check_eap_capa(dev[0], "MD5")
10031     check_eap_capa(dev[0], "VENDOR-TEST")
10032     params = hostapd.wpa2_eap_params(ssid="eap-test")
10033     hapd = hostapd.add_ap(apdev[0], params)
10034     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
10035     dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
10036                    eap="VENDOR-TEST WSC",
10037                    identity="sake user", password="password",
10038                    wait_connect=False)
10039     ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=10)
10040     if ev is None or "NAK" not in ev:
10041         raise Exception("No NAK event seen")
10042 
10043     ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
10044     if ev is None:
10045         raise Exception("No EAP-Failure seen")
10046 
10047     dev[0].request("REMOVE_NETWORK all")
10048     dev[0].wait_disconnected()
10049 
10050 EAP_TLV_RESULT_TLV = 3
10051 EAP_TLV_NAK_TLV = 4
10052 EAP_TLV_ERROR_CODE_TLV = 5
10053 EAP_TLV_CONNECTION_BINDING_TLV = 6
10054 EAP_TLV_VENDOR_SPECIFIC_TLV = 7
10055 EAP_TLV_URI_TLV = 8
10056 EAP_TLV_EAP_PAYLOAD_TLV = 9
10057 EAP_TLV_INTERMEDIATE_RESULT_TLV = 10
10058 EAP_TLV_PAC_TLV = 11
10059 EAP_TLV_CRYPTO_BINDING_TLV = 12
10060 EAP_TLV_CALLING_STATION_ID_TLV = 13
10061 EAP_TLV_CALLED_STATION_ID_TLV = 14
10062 EAP_TLV_NAS_PORT_TYPE_TLV = 15
10063 EAP_TLV_SERVER_IDENTIFIER_TLV = 16
10064 EAP_TLV_IDENTITY_TYPE_TLV = 17
10065 EAP_TLV_SERVER_TRUSTED_ROOT_TLV = 18
10066 EAP_TLV_REQUEST_ACTION_TLV = 19
10067 EAP_TLV_PKCS7_TLV = 20
10068 
10069 EAP_TLV_RESULT_SUCCESS = 1
10070 EAP_TLV_RESULT_FAILURE = 2
10071 
10072 EAP_TLV_TYPE_MANDATORY = 0x8000
10073 EAP_TLV_TYPE_MASK = 0x3fff
10074 
10075 PAC_TYPE_PAC_KEY = 1
10076 PAC_TYPE_PAC_OPAQUE = 2
10077 PAC_TYPE_CRED_LIFETIME = 3
10078 PAC_TYPE_A_ID = 4
10079 PAC_TYPE_I_ID = 5
10080 PAC_TYPE_A_ID_INFO = 7
10081 PAC_TYPE_PAC_ACKNOWLEDGEMENT = 8
10082 PAC_TYPE_PAC_INFO = 9
10083 PAC_TYPE_PAC_TYPE = 10
10084 
10085 def eap_fast_start(ctx):
10086     logger.info("Send EAP-FAST/Start")
10087     return struct.pack(">BBHBBHH", EAP_CODE_REQUEST, ctx['id'],
10088                        4 + 1 + 1 + 4 + 16,
10089                        EAP_TYPE_FAST, 0x21, 4, 16) + 16*b'A'
10090 
10091 def test_eap_fast_proto(dev, apdev):
10092     """EAP-FAST Phase protocol testing"""
10093     check_eap_capa(dev[0], "FAST")
10094     global eap_fast_proto_ctx
10095     eap_fast_proto_ctx = None
10096 
10097     def eap_handler(ctx, req):
10098         logger.info("eap_handler - RX " + binascii.hexlify(req).decode())
10099         if 'num' not in ctx:
10100             ctx['num'] = 0
10101         ctx['num'] = ctx['num'] + 1
10102         if 'id' not in ctx:
10103             ctx['id'] = 1
10104         ctx['id'] = (ctx['id'] + 1) % 256
10105         idx = 0
10106 
10107         global eap_fast_proto_ctx
10108         eap_fast_proto_ctx = ctx
10109         ctx['test_done'] = False
10110 
10111         idx += 1
10112         if ctx['num'] == idx:
10113             return eap_fast_start(ctx)
10114         idx += 1
10115         if ctx['num'] == idx:
10116             logger.info("EAP-FAST: TLS processing failed")
10117             data = b'ABCDEFGHIK'
10118             return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
10119                                4 + 1 + 1 + len(data),
10120                                EAP_TYPE_FAST, 0x01) + data
10121         idx += 1
10122         if ctx['num'] == idx:
10123             ctx['test_done'] = True
10124             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
10125 
10126         logger.info("Past last test case")
10127         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
10128 
10129     srv = start_radius_server(eap_handler)
10130     try:
10131         hapd = start_ap(apdev[0])
10132         dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
10133         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
10134                        eap="FAST", anonymous_identity="FAST",
10135                        identity="user", password="password",
10136                        ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
10137                        phase1="fast_provisioning=1",
10138                        pac_file="blob://fast_pac_proto",
10139                        wait_connect=False)
10140         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
10141         if ev is None:
10142             raise Exception("Could not start EAP-FAST")
10143         ok = False
10144         for i in range(100):
10145             if eap_fast_proto_ctx:
10146                 if eap_fast_proto_ctx['test_done']:
10147                     ok = True
10148                     break
10149             time.sleep(0.05)
10150         dev[0].request("REMOVE_NETWORK all")
10151         dev[0].wait_disconnected()
10152     finally:
10153         stop_radius_server(srv)
10154 
10155 def run_eap_fast_phase2(dev, test_payload, test_failure=True):
10156     global eap_fast_proto_ctx
10157     eap_fast_proto_ctx = None
10158 
10159     def ssl_info_callback(conn, where, ret):
10160         logger.debug("SSL: info where=%d ret=%d" % (where, ret))
10161 
10162     def log_conn_state(conn):
10163         try:
10164             state = conn.state_string()
10165         except AttributeError:
10166             state = conn.get_state_string()
10167         if state:
10168             logger.info("State: " + str(state))
10169 
10170     def process_clienthello(ctx, payload):
10171         logger.info("Process ClientHello")
10172         ctx['sslctx'] = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
10173         ctx['sslctx'].set_info_callback(ssl_info_callback)
10174         ctx['sslctx'].load_tmp_dh("auth_serv/dh.conf")
10175         if OpenSSL.SSL.OPENSSL_VERSION_NUMBER >= 0x10100000:
10176             ctx['sslctx'].set_cipher_list("ADH-AES128-SHA:@SECLEVEL=0")
10177         else:
10178             ctx['sslctx'].set_cipher_list("ADH-AES128-SHA")
10179         ctx['conn'] = OpenSSL.SSL.Connection(ctx['sslctx'], None)
10180         ctx['conn'].set_accept_state()
10181         log_conn_state(ctx['conn'])
10182         ctx['conn'].bio_write(payload)
10183         try:
10184             ctx['conn'].do_handshake()
10185         except OpenSSL.SSL.WantReadError:
10186             pass
10187         log_conn_state(ctx['conn'])
10188         data = ctx['conn'].bio_read(4096)
10189         log_conn_state(ctx['conn'])
10190         return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
10191                            4 + 1 + 1 + len(data),
10192                            EAP_TYPE_FAST, 0x01) + data
10193 
10194     def process_clientkeyexchange(ctx, payload, appl_data):
10195         logger.info("Process ClientKeyExchange")
10196         log_conn_state(ctx['conn'])
10197         ctx['conn'].bio_write(payload)
10198         try:
10199             ctx['conn'].do_handshake()
10200         except OpenSSL.SSL.WantReadError:
10201             pass
10202         ctx['conn'].send(appl_data)
10203         log_conn_state(ctx['conn'])
10204         data = ctx['conn'].bio_read(4096)
10205         log_conn_state(ctx['conn'])
10206         return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
10207                            4 + 1 + 1 + len(data),
10208                            EAP_TYPE_FAST, 0x01) + data
10209 
10210     def eap_handler(ctx, req):
10211         logger.info("eap_handler - RX " + binascii.hexlify(req).decode())
10212         if 'num' not in ctx:
10213             ctx['num'] = 0
10214         ctx['num'] = ctx['num'] + 1
10215         if 'id' not in ctx:
10216             ctx['id'] = 1
10217         ctx['id'] = (ctx['id'] + 1) % 256
10218         idx = 0
10219 
10220         global eap_fast_proto_ctx
10221         eap_fast_proto_ctx = ctx
10222         ctx['test_done'] = False
10223         logger.debug("ctx['num']=%d" % ctx['num'])
10224 
10225         idx += 1
10226         if ctx['num'] == idx:
10227             return eap_fast_start(ctx)
10228         idx += 1
10229         if ctx['num'] == idx:
10230             return process_clienthello(ctx, req[6:])
10231         idx += 1
10232         if ctx['num'] == idx:
10233             if not test_failure:
10234                 ctx['test_done'] = True
10235             return process_clientkeyexchange(ctx, req[6:], test_payload)
10236         idx += 1
10237         if ctx['num'] == idx:
10238             ctx['test_done'] = True
10239             return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
10240 
10241         logger.info("Past last test case")
10242         return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
10243 
10244     srv = start_radius_server(eap_handler)
10245     try:
10246         dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
10247                        eap="FAST", anonymous_identity="FAST",
10248                        identity="user", password="password",
10249                        ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
10250                        phase1="fast_provisioning=1",
10251                        pac_file="blob://fast_pac_proto",
10252                        wait_connect=False)
10253         ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
10254         if ev is None:
10255             raise Exception("Could not start EAP-FAST")
10256         dev[0].dump_monitor()
10257         ok = False
10258         for i in range(100):
10259             if eap_fast_proto_ctx:
10260                 if eap_fast_proto_ctx['test_done']:
10261                     ok = True
10262                     break
10263             time.sleep(0.05)
10264         time.sleep(0.1)
10265         dev[0].request("REMOVE_NETWORK all")
10266         dev[0].wait_disconnected()
10267         if not ok:
10268             raise Exception("EAP-FAST TLS exchange did not complete")
10269         for i in range(3):
10270             dev[i].dump_monitor()
10271     finally:
10272         stop_radius_server(srv)
10273 
10274 def test_eap_fast_proto_phase2(dev, apdev):
10275     """EAP-FAST Phase 2 protocol testing"""
10276     if not openssl_imported:
10277         raise HwsimSkip("OpenSSL python method not available")
10278     check_eap_capa(dev[0], "FAST")
10279     hapd = start_ap(apdev[0])
10280     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
10281 
10282     tests = [("Too short Phase 2 TLV frame (len=3)",
10283               "ABC",
10284               False),
10285              ("EAP-FAST: TLV overflow",
10286               struct.pack(">HHB", 0, 2, 0xff),
10287               False),
10288              ("EAP-FAST: Unknown TLV (optional and mandatory)",
10289               struct.pack(">HHB", 0, 1, 0xff) +
10290               struct.pack(">HHB", EAP_TLV_TYPE_MANDATORY, 1, 0xff),
10291               True),
10292              ("EAP-FAST: More than one EAP-Payload TLV in the message",
10293               struct.pack(">HHBHHB",
10294                           EAP_TLV_EAP_PAYLOAD_TLV, 1, 0xff,
10295                           EAP_TLV_EAP_PAYLOAD_TLV, 1, 0xff),
10296               True),
10297              ("EAP-FAST: Unknown Result 255 and More than one Result TLV in the message",
10298               struct.pack(">HHHHHH",
10299                           EAP_TLV_RESULT_TLV, 2, 0xff,
10300                           EAP_TLV_RESULT_TLV, 2, 0xff),
10301               True),
10302              ("EAP-FAST: Too short Result TLV",
10303               struct.pack(">HHB", EAP_TLV_RESULT_TLV, 1, 0xff),
10304               True),
10305              ("EAP-FAST: Unknown Intermediate Result 255 and More than one Intermediate-Result TLV in the message",
10306               struct.pack(">HHHHHH",
10307                           EAP_TLV_INTERMEDIATE_RESULT_TLV, 2, 0xff,
10308                           EAP_TLV_INTERMEDIATE_RESULT_TLV, 2, 0xff),
10309               True),
10310              ("EAP-FAST: Too short Intermediate-Result TLV",
10311               struct.pack(">HHB", EAP_TLV_INTERMEDIATE_RESULT_TLV, 1, 0xff),
10312               True),
10313              ("EAP-FAST: More than one Crypto-Binding TLV in the message",
10314               struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*b'A' +
10315               struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*b'A',
10316               True),
10317              ("EAP-FAST: Too short Crypto-Binding TLV",
10318               struct.pack(">HHB", EAP_TLV_CRYPTO_BINDING_TLV, 1, 0xff),
10319               True),
10320              ("EAP-FAST: More than one Request-Action TLV in the message",
10321               struct.pack(">HHBBHHBB",
10322                           EAP_TLV_REQUEST_ACTION_TLV, 2, 0xff, 0xff,
10323                           EAP_TLV_REQUEST_ACTION_TLV, 2, 0xff, 0xff),
10324               True),
10325              ("EAP-FAST: Too short Request-Action TLV",
10326               struct.pack(">HHB", EAP_TLV_REQUEST_ACTION_TLV, 1, 0xff),
10327               True),
10328              ("EAP-FAST: More than one PAC TLV in the message",
10329               struct.pack(">HHBHHB",
10330                           EAP_TLV_PAC_TLV, 1, 0xff,
10331                           EAP_TLV_PAC_TLV, 1, 0xff),
10332               True),
10333              ("EAP-FAST: Too short EAP Payload TLV (Len=3)",
10334               struct.pack(">HH3B",
10335                           EAP_TLV_EAP_PAYLOAD_TLV, 3, 0, 0, 0),
10336               False),
10337              ("EAP-FAST: Too short Phase 2 request (Len=0)",
10338               struct.pack(">HHBBH",
10339                           EAP_TLV_EAP_PAYLOAD_TLV, 4,
10340                           EAP_CODE_REQUEST, 0, 0),
10341               False),
10342              ("EAP-FAST: EAP packet overflow in EAP Payload TLV",
10343               struct.pack(">HHBBH",
10344                           EAP_TLV_EAP_PAYLOAD_TLV, 4,
10345                           EAP_CODE_REQUEST, 0, 4 + 1),
10346               False),
10347              ("EAP-FAST: Unexpected code=0 in Phase 2 EAP header",
10348               struct.pack(">HHBBH",
10349                           EAP_TLV_EAP_PAYLOAD_TLV, 4,
10350                           0, 0, 0),
10351               False),
10352              ("EAP-FAST: PAC TLV without Result TLV acknowledging success",
10353               struct.pack(">HHB", EAP_TLV_PAC_TLV, 1, 0xff),
10354               True),
10355              ("EAP-FAST: PAC TLV does not include all the required fields",
10356               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10357                           EAP_TLV_RESULT_SUCCESS) +
10358               struct.pack(">HHB", EAP_TLV_PAC_TLV, 1, 0xff),
10359               True),
10360              ("EAP-FAST: Invalid PAC-Key length 0, Ignored unknown PAC type 0, and PAC TLV overrun (type=0 len=2 left=1)",
10361               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10362                           EAP_TLV_RESULT_SUCCESS) +
10363               struct.pack(">HHHHHHHHB", EAP_TLV_PAC_TLV, 4 + 4 + 5,
10364                           PAC_TYPE_PAC_KEY, 0, 0, 0, 0, 2, 0),
10365               True),
10366              ("EAP-FAST: PAC-Info does not include all the required fields",
10367               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10368                           EAP_TLV_RESULT_SUCCESS) +
10369               struct.pack(">HHHHHHHH", EAP_TLV_PAC_TLV, 4 + 4 + 4 + 32,
10370                           PAC_TYPE_PAC_OPAQUE, 0,
10371                           PAC_TYPE_PAC_INFO, 0,
10372                           PAC_TYPE_PAC_KEY, 32) + 32*b'A',
10373               True),
10374              ("EAP-FAST: Invalid CRED_LIFETIME length, Ignored unknown PAC-Info type 0, and Invalid PAC-Type length 1",
10375               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10376                           EAP_TLV_RESULT_SUCCESS) +
10377               struct.pack(">HHHHHHHHHHHHBHH", EAP_TLV_PAC_TLV, 4 + 4 + 13 + 4 + 32,
10378                           PAC_TYPE_PAC_OPAQUE, 0,
10379                           PAC_TYPE_PAC_INFO, 13, PAC_TYPE_CRED_LIFETIME, 0,
10380                           0, 0, PAC_TYPE_PAC_TYPE, 1, 0,
10381                           PAC_TYPE_PAC_KEY, 32) + 32*b'A',
10382               True),
10383              ("EAP-FAST: Unsupported PAC-Type 0",
10384               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10385                           EAP_TLV_RESULT_SUCCESS) +
10386               struct.pack(">HHHHHHHHHHH", EAP_TLV_PAC_TLV, 4 + 4 + 6 + 4 + 32,
10387                           PAC_TYPE_PAC_OPAQUE, 0,
10388                           PAC_TYPE_PAC_INFO, 6, PAC_TYPE_PAC_TYPE, 2, 0,
10389                           PAC_TYPE_PAC_KEY, 32) + 32*b'A',
10390               True),
10391              ("EAP-FAST: PAC-Info overrun (type=0 len=2 left=1)",
10392               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10393                           EAP_TLV_RESULT_SUCCESS) +
10394               struct.pack(">HHHHHHHHBHH", EAP_TLV_PAC_TLV, 4 + 4 + 5 + 4 + 32,
10395                           PAC_TYPE_PAC_OPAQUE, 0,
10396                           PAC_TYPE_PAC_INFO, 5, 0, 2, 1,
10397                           PAC_TYPE_PAC_KEY, 32) + 32*b'A',
10398               True),
10399              ("EAP-FAST: Valid PAC",
10400               struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
10401                           EAP_TLV_RESULT_SUCCESS) +
10402               struct.pack(">HHHHHHHHBHHBHH", EAP_TLV_PAC_TLV,
10403                           4 + 4 + 10 + 4 + 32,
10404                           PAC_TYPE_PAC_OPAQUE, 0,
10405                           PAC_TYPE_PAC_INFO, 10, PAC_TYPE_A_ID, 1, 0x41,
10406                           PAC_TYPE_A_ID_INFO, 1, 0x42,
10407                           PAC_TYPE_PAC_KEY, 32) + 32*b'A',
10408               True),
10409              ("EAP-FAST: Invalid version/subtype in Crypto-Binding TLV",
10410               struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*b'A',
10411               True)]
10412     for title, payload, failure in tests:
10413         logger.info("Phase 2 test: " + title)
10414         run_eap_fast_phase2(dev, payload, failure)
10415 
10416 def test_eap_fast_tlv_nak_oom(dev, apdev):
10417     """EAP-FAST Phase 2 TLV NAK OOM"""
10418     if not openssl_imported:
10419         raise HwsimSkip("OpenSSL python method not available")
10420     check_eap_capa(dev[0], "FAST")
10421     hapd = start_ap(apdev[0])
10422     dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
10423 
10424     with alloc_fail(dev[0], 1, "eap_fast_tlv_nak"):
10425         run_eap_fast_phase2(dev, struct.pack(">HHB", EAP_TLV_TYPE_MANDATORY,
10426                                              1, 0xff), False)
10427