1
2
3
4
5
6
7
8
9
10
11 """
12 MAIN CLASS FOR TLS LITE (START HERE!).
13 """
14
15 import socket
16 from .utils.compat import formatExceptionTrace
17 from .tlsrecordlayer import TLSRecordLayer
18 from .session import Session
19 from .constants import *
20 from .utils.cryptomath import getRandomBytes
21 from .errors import *
22 from .messages import *
23 from .mathtls import *
24 from .handshakesettings import HandshakeSettings
25 from .utils.tackwrapper import *
26
27
29 """
30 This class wraps a socket and provides TLS handshaking and data
31 transfer.
32
33 To use this class, create a new instance, passing a connected
34 socket into the constructor. Then call some handshake function.
35 If the handshake completes without raising an exception, then a TLS
36 connection has been negotiated. You can transfer data over this
37 connection as if it were a socket.
38
39 This class provides both synchronous and asynchronous versions of
40 its key functions. The synchronous versions should be used when
41 writing single-or multi-threaded code using blocking sockets. The
42 asynchronous versions should be used when performing asynchronous,
43 event-based I/O with non-blocking sockets.
44
45 Asynchronous I/O is a complicated subject; typically, you should
46 not use the asynchronous functions directly, but should use some
47 framework like asyncore or Twisted which TLS Lite integrates with
48 (see
49 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}).
50 """
51
53 """Create a new TLSConnection instance.
54
55 @param sock: The socket data will be transmitted on. The
56 socket should already be connected. It may be in blocking or
57 non-blocking mode.
58
59 @type sock: L{socket.socket}
60 """
61 TLSRecordLayer.__init__(self, sock)
62
63
64
65
66
70 """Perform an anonymous handshake in the role of client.
71
72 This function performs an SSL or TLS handshake using an
73 anonymous Diffie Hellman ciphersuite.
74
75 Like any handshake function, this can be called on a closed
76 TLS connection, or on a TLS connection that is already open.
77 If called on an open connection it performs a re-handshake.
78
79 If the function completes without raising an exception, the
80 TLS connection will be open and available for data transfer.
81
82 If an exception is raised, the connection will have been
83 automatically closed (if it was ever open).
84
85 @type session: L{tlslite.Session.Session}
86 @param session: A TLS session to attempt to resume. If the
87 resumption does not succeed, a full handshake will be
88 performed.
89
90 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
91 @param settings: Various settings which can be used to control
92 the ciphersuites, certificate types, and SSL/TLS versions
93 offered by the client.
94
95 @type checker: L{tlslite.Checker.Checker}
96 @param checker: A Checker instance. This instance will be
97 invoked to examine the other party's authentication
98 credentials, if the handshake completes succesfully.
99
100 @type serverName: string
101 @param serverName: The ServerNameIndication TLS Extension.
102
103 @type async: bool
104 @param async: If False, this function will block until the
105 handshake is completed. If True, this function will return a
106 generator. Successive invocations of the generator will
107 return 0 if it is waiting to read from the socket, 1 if it is
108 waiting to write to the socket, or will raise StopIteration if
109 the handshake operation is completed.
110
111 @rtype: None or an iterable
112 @return: If 'async' is True, a generator object will be
113 returned.
114
115 @raise socket.error: If a socket error occurs.
116 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
117 without a preceding alert.
118 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
119 @raise tlslite.errors.TLSAuthenticationError: If the checker
120 doesn't like the other party's authentication credentials.
121 """
122 handshaker = self._handshakeClientAsync(anonParams=(True),
123 session=session,
124 settings=settings,
125 checker=checker,
126 serverName=serverName)
127 if async:
128 return handshaker
129 for result in handshaker:
130 pass
131
132 - def handshakeClientSRP(self, username, password, session=None,
133 settings=None, checker=None,
134 reqTack=True, serverName="",
135 async=False):
136 """Perform an SRP handshake in the role of client.
137
138 This function performs a TLS/SRP handshake. SRP mutually
139 authenticates both parties to each other using only a
140 username and password. This function may also perform a
141 combined SRP and server-certificate handshake, if the server
142 chooses to authenticate itself with a certificate chain in
143 addition to doing SRP.
144
145 If the function completes without raising an exception, the
146 TLS connection will be open and available for data transfer.
147
148 If an exception is raised, the connection will have been
149 automatically closed (if it was ever open).
150
151 @type username: str
152 @param username: The SRP username.
153
154 @type password: str
155 @param password: The SRP password.
156
157 @type session: L{tlslite.session.Session}
158 @param session: A TLS session to attempt to resume. This
159 session must be an SRP session performed with the same username
160 and password as were passed in. If the resumption does not
161 succeed, a full SRP handshake will be performed.
162
163 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
164 @param settings: Various settings which can be used to control
165 the ciphersuites, certificate types, and SSL/TLS versions
166 offered by the client.
167
168 @type checker: L{tlslite.checker.Checker}
169 @param checker: A Checker instance. This instance will be
170 invoked to examine the other party's authentication
171 credentials, if the handshake completes succesfully.
172
173 @type reqTack: bool
174 @param reqTack: Whether or not to send a "tack" TLS Extension,
175 requesting the server return a TackExtension if it has one.
176
177 @type serverName: string
178 @param serverName: The ServerNameIndication TLS Extension.
179
180 @type async: bool
181 @param async: If False, this function will block until the
182 handshake is completed. If True, this function will return a
183 generator. Successive invocations of the generator will
184 return 0 if it is waiting to read from the socket, 1 if it is
185 waiting to write to the socket, or will raise StopIteration if
186 the handshake operation is completed.
187
188 @rtype: None or an iterable
189 @return: If 'async' is True, a generator object will be
190 returned.
191
192 @raise socket.error: If a socket error occurs.
193 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
194 without a preceding alert.
195 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
196 @raise tlslite.errors.TLSAuthenticationError: If the checker
197 doesn't like the other party's authentication credentials.
198 """
199 handshaker = self._handshakeClientAsync(srpParams=(username, password),
200 session=session, settings=settings, checker=checker,
201 reqTack=reqTack, serverName=serverName)
202
203
204
205
206
207
208
209 if async:
210 return handshaker
211 for result in handshaker:
212 pass
213
214 - def handshakeClientCert(self, certChain=None, privateKey=None,
215 session=None, settings=None, checker=None,
216 nextProtos=None, reqTack=True, serverName="",
217 async=False):
218 """Perform a certificate-based handshake in the role of client.
219
220 This function performs an SSL or TLS handshake. The server
221 will authenticate itself using an X.509 certificate
222 chain. If the handshake succeeds, the server's certificate
223 chain will be stored in the session's serverCertChain attribute.
224 Unless a checker object is passed in, this function does no
225 validation or checking of the server's certificate chain.
226
227 If the server requests client authentication, the
228 client will send the passed-in certificate chain, and use the
229 passed-in private key to authenticate itself. If no
230 certificate chain and private key were passed in, the client
231 will attempt to proceed without client authentication. The
232 server may or may not allow this.
233
234 If the function completes without raising an exception, the
235 TLS connection will be open and available for data transfer.
236
237 If an exception is raised, the connection will have been
238 automatically closed (if it was ever open).
239
240 @type certChain: L{tlslite.x509certchain.X509CertChain}
241 @param certChain: The certificate chain to be used if the
242 server requests client authentication.
243
244 @type privateKey: L{tlslite.utils.rsakey.RSAKey}
245 @param privateKey: The private key to be used if the server
246 requests client authentication.
247
248 @type session: L{tlslite.session.Session}
249 @param session: A TLS session to attempt to resume. If the
250 resumption does not succeed, a full handshake will be
251 performed.
252
253 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
254 @param settings: Various settings which can be used to control
255 the ciphersuites, certificate types, and SSL/TLS versions
256 offered by the client.
257
258 @type checker: L{tlslite.checker.Checker}
259 @param checker: A Checker instance. This instance will be
260 invoked to examine the other party's authentication
261 credentials, if the handshake completes succesfully.
262
263 @type nextProtos: list of strings.
264 @param nextProtos: A list of upper layer protocols ordered by
265 preference, to use in the Next-Protocol Negotiation Extension.
266
267 @type reqTack: bool
268 @param reqTack: Whether or not to send a "tack" TLS Extension,
269 requesting the server return a TackExtension if it has one.
270
271 @type serverName: string
272 @param serverName: The ServerNameIndication TLS Extension.
273
274 @type async: bool
275 @param async: If False, this function will block until the
276 handshake is completed. If True, this function will return a
277 generator. Successive invocations of the generator will
278 return 0 if it is waiting to read from the socket, 1 if it is
279 waiting to write to the socket, or will raise StopIteration if
280 the handshake operation is completed.
281
282 @rtype: None or an iterable
283 @return: If 'async' is True, a generator object will be
284 returned.
285
286 @raise socket.error: If a socket error occurs.
287 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
288 without a preceding alert.
289 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
290 @raise tlslite.errors.TLSAuthenticationError: If the checker
291 doesn't like the other party's authentication credentials.
292 """
293 handshaker = self._handshakeClientAsync(certParams=(certChain,
294 privateKey), session=session, settings=settings,
295 checker=checker, serverName=serverName,
296 nextProtos=nextProtos, reqTack=reqTack)
297
298
299
300
301
302
303
304 if async:
305 return handshaker
306 for result in handshaker:
307 pass
308
309
310 - def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
311 session=None, settings=None, checker=None,
312 nextProtos=None, serverName="", reqTack=True):
324
325
328
329 self._handshakeStart(client=True)
330
331
332 srpUsername = None
333 password = None
334 clientCertChain = None
335 privateKey = None
336
337
338 if srpParams:
339 assert(not certParams)
340 assert(not anonParams)
341 srpUsername, password = srpParams
342 if certParams:
343 assert(not srpParams)
344 assert(not anonParams)
345 clientCertChain, privateKey = certParams
346 if anonParams:
347 assert(not srpParams)
348 assert(not certParams)
349
350
351 if srpUsername and not password:
352 raise ValueError("Caller passed a username but no password")
353 if password and not srpUsername:
354 raise ValueError("Caller passed a password but no username")
355 if clientCertChain and not privateKey:
356 raise ValueError("Caller passed a certChain but no privateKey")
357 if privateKey and not clientCertChain:
358 raise ValueError("Caller passed a privateKey but no certChain")
359 if reqTack:
360 if not tackpyLoaded:
361 reqTack = False
362 if not settings or not settings.useExperimentalTackExtension:
363 reqTack = False
364 if nextProtos is not None:
365 if len(nextProtos) == 0:
366 raise ValueError("Caller passed no nextProtos")
367
368
369
370 if not settings:
371 settings = HandshakeSettings()
372 settings = settings._filter()
373
374 if clientCertChain:
375 if not isinstance(clientCertChain, X509CertChain):
376 raise ValueError("Unrecognized certificate type")
377 if "x509" not in settings.certificateTypes:
378 raise ValueError("Client certificate doesn't match "\
379 "Handshake Settings")
380
381 if session:
382
383
384 if not session.valid():
385 session = None
386 elif session.resumable:
387 if session.srpUsername != srpUsername:
388 raise ValueError("Session username doesn't match")
389 if session.serverName != serverName:
390 raise ValueError("Session servername doesn't match")
391
392
393 if srpUsername and self.fault == Fault.badUsername:
394 srpUsername += "GARBAGE"
395 if password and self.fault == Fault.badPassword:
396 password += "GARBAGE"
397
398
399
400
401 self.version = settings.maxVersion
402
403
404
405
406
407 for result in self._clientSendClientHello(settings, session,
408 srpUsername, srpParams, certParams,
409 anonParams, serverName, nextProtos,
410 reqTack):
411 if result in (0,1): yield result
412 else: break
413 clientHello = result
414
415
416 for result in self._clientGetServerHello(settings, clientHello):
417 if result in (0,1): yield result
418 else: break
419 serverHello = result
420 cipherSuite = serverHello.cipher_suite
421
422
423
424 nextProto = self._clientSelectNextProto(nextProtos, serverHello)
425
426
427 for result in self._clientResume(session, serverHello,
428 clientHello.random,
429 settings.cipherImplementations,
430 nextProto):
431 if result in (0,1): yield result
432 else: break
433 if result == "resumed_and_finished":
434 self._handshakeDone(resumed=True)
435 return
436
437
438
439
440 if cipherSuite in CipherSuite.srpAllSuites:
441 for result in self._clientSRPKeyExchange(\
442 settings, cipherSuite, serverHello.certificate_type,
443 srpUsername, password,
444 clientHello.random, serverHello.random,
445 serverHello.tackExt):
446 if result in (0,1): yield result
447 else: break
448 (premasterSecret, serverCertChain, tackExt) = result
449
450
451
452 elif cipherSuite in CipherSuite.anonSuites:
453 for result in self._clientAnonKeyExchange(settings, cipherSuite,
454 clientHello.random, serverHello.random):
455 if result in (0,1): yield result
456 else: break
457 (premasterSecret, serverCertChain, tackExt) = result
458
459
460
461
462
463
464
465 else:
466 for result in self._clientRSAKeyExchange(settings, cipherSuite,
467 clientCertChain, privateKey,
468 serverHello.certificate_type,
469 clientHello.random, serverHello.random,
470 serverHello.tackExt):
471 if result in (0,1): yield result
472 else: break
473 (premasterSecret, serverCertChain, clientCertChain,
474 tackExt) = result
475
476
477
478 for result in self._clientFinished(premasterSecret,
479 clientHello.random,
480 serverHello.random,
481 cipherSuite, settings.cipherImplementations,
482 nextProto):
483 if result in (0,1): yield result
484 else: break
485 masterSecret = result
486
487
488 self.session = Session()
489 self.session.create(masterSecret, serverHello.session_id, cipherSuite,
490 srpUsername, clientCertChain, serverCertChain,
491 tackExt, serverHello.tackExt!=None, serverName)
492 self._handshakeDone(resumed=False)
493
494
495 - def _clientSendClientHello(self, settings, session, srpUsername,
496 srpParams, certParams, anonParams,
497 serverName, nextProtos, reqTack):
498
499 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
500 if srpParams:
501 cipherSuites += CipherSuite.getSrpAllSuites(settings)
502 elif certParams:
503 cipherSuites += CipherSuite.getCertSuites(settings)
504 elif anonParams:
505 cipherSuites += CipherSuite.getAnonSuites(settings)
506 else:
507 assert(False)
508
509
510 certificateTypes = settings._getCertificateTypes()
511
512
513 if session and session.sessionID:
514
515
516 if session.cipherSuite not in cipherSuites:
517 raise ValueError("Session's cipher suite not consistent "\
518 "with parameters")
519 else:
520 clientHello = ClientHello()
521 clientHello.create(settings.maxVersion, getRandomBytes(32),
522 session.sessionID, cipherSuites,
523 certificateTypes,
524 session.srpUsername,
525 reqTack, nextProtos is not None,
526 session.serverName)
527
528
529 else:
530 clientHello = ClientHello()
531 clientHello.create(settings.maxVersion, getRandomBytes(32),
532 bytearray(0), cipherSuites,
533 certificateTypes,
534 srpUsername,
535 reqTack, nextProtos is not None,
536 serverName)
537 for result in self._sendMsg(clientHello):
538 yield result
539 yield clientHello
540
541
543 for result in self._getMsg(ContentType.handshake,
544 HandshakeType.server_hello):
545 if result in (0,1): yield result
546 else: break
547 serverHello = result
548
549
550
551 self.version = serverHello.server_version
552
553
554 self._versionCheck = True
555
556
557 if serverHello.server_version < settings.minVersion:
558 for result in self._sendError(\
559 AlertDescription.protocol_version,
560 "Too old version: %s" % str(serverHello.server_version)):
561 yield result
562 if serverHello.server_version > settings.maxVersion:
563 for result in self._sendError(\
564 AlertDescription.protocol_version,
565 "Too new version: %s" % str(serverHello.server_version)):
566 yield result
567 if serverHello.cipher_suite not in clientHello.cipher_suites:
568 for result in self._sendError(\
569 AlertDescription.illegal_parameter,
570 "Server responded with incorrect ciphersuite"):
571 yield result
572 if serverHello.certificate_type not in clientHello.certificate_types:
573 for result in self._sendError(\
574 AlertDescription.illegal_parameter,
575 "Server responded with incorrect certificate type"):
576 yield result
577 if serverHello.compression_method != 0:
578 for result in self._sendError(\
579 AlertDescription.illegal_parameter,
580 "Server responded with incorrect compression method"):
581 yield result
582 if serverHello.tackExt:
583 if not clientHello.tack:
584 for result in self._sendError(\
585 AlertDescription.illegal_parameter,
586 "Server responded with unrequested Tack Extension"):
587 yield result
588 if serverHello.next_protos and not clientHello.supports_npn:
589 for result in self._sendError(\
590 AlertDescription.illegal_parameter,
591 "Server responded with unrequested NPN Extension"):
592 yield result
593 if not serverHello.tackExt.verifySignatures():
594 for result in self._sendError(\
595 AlertDescription.decrypt_error,
596 "TackExtension contains an invalid signature"):
597 yield result
598 yield serverHello
599
601
602
603
604
605
606
607
608 if nextProtos is not None and serverHello.next_protos is not None:
609 for p in nextProtos:
610 if bytearray(p) in serverHello.next_protos:
611 return bytearray(p)
612 else:
613
614
615
616 return bytearray(nextProtos[0])
617 return None
618
619 - def _clientResume(self, session, serverHello, clientRandom,
620 cipherImplementations, nextProto):
646
647 - def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType,
648 srpUsername, password,
649 clientRandom, serverRandom, tackExt):
650
651
652 if cipherSuite in CipherSuite.srpCertSuites:
653
654 for result in self._getMsg(ContentType.handshake,
655 HandshakeType.certificate, certificateType):
656 if result in (0,1): yield result
657 else: break
658 serverCertificate = result
659 else:
660 serverCertificate = None
661
662 for result in self._getMsg(ContentType.handshake,
663 HandshakeType.server_key_exchange, cipherSuite):
664 if result in (0,1): yield result
665 else: break
666 serverKeyExchange = result
667
668 for result in self._getMsg(ContentType.handshake,
669 HandshakeType.server_hello_done):
670 if result in (0,1): yield result
671 else: break
672 serverHelloDone = result
673
674
675
676 N = serverKeyExchange.srp_N
677 g = serverKeyExchange.srp_g
678 s = serverKeyExchange.srp_s
679 B = serverKeyExchange.srp_B
680
681 if (g,N) not in goodGroupParameters:
682 for result in self._sendError(\
683 AlertDescription.insufficient_security,
684 "Unknown group parameters"):
685 yield result
686 if numBits(N) < settings.minKeySize:
687 for result in self._sendError(\
688 AlertDescription.insufficient_security,
689 "N value is too small: %d" % numBits(N)):
690 yield result
691 if numBits(N) > settings.maxKeySize:
692 for result in self._sendError(\
693 AlertDescription.insufficient_security,
694 "N value is too large: %d" % numBits(N)):
695 yield result
696 if B % N == 0:
697 for result in self._sendError(\
698 AlertDescription.illegal_parameter,
699 "Suspicious B value"):
700 yield result
701
702
703
704 serverCertChain = None
705 if cipherSuite in CipherSuite.srpCertSuites:
706
707 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
708
709
710 sigBytes = serverKeyExchange.signature
711 if len(sigBytes) == 0:
712 for result in self._sendError(\
713 AlertDescription.illegal_parameter,
714 "Server sent an SRP ServerKeyExchange "\
715 "message without a signature"):
716 yield result
717
718
719
720
721 for result in self._clientGetKeyFromChain(serverCertificate,
722 settings, tackExt):
723 if result in (0,1): yield result
724 else: break
725 publicKey, serverCertChain, tackExt = result
726
727
728 if not publicKey.verify(sigBytes, hashBytes):
729 for result in self._sendError(\
730 AlertDescription.decrypt_error,
731 "Signature failed to verify"):
732 yield result
733
734
735 a = bytesToNumber(getRandomBytes(32))
736 A = powMod(g, a, N)
737
738
739 x = makeX(s, bytearray(srpUsername, "utf-8"),
740 bytearray(password, "utf-8"))
741 v = powMod(g, x, N)
742
743
744 u = makeU(N, A, B)
745
746
747 k = makeK(N, g)
748 S = powMod((B - (k*v)) % N, a+(u*x), N)
749
750 if self.fault == Fault.badA:
751 A = N
752 S = 0
753
754 premasterSecret = numberToByteArray(S)
755
756
757 for result in self._sendMsg(\
758 ClientKeyExchange(cipherSuite).createSRP(A)):
759 yield result
760 yield (premasterSecret, serverCertChain, tackExt)
761
762
763 - def _clientRSAKeyExchange(self, settings, cipherSuite,
764 clientCertChain, privateKey,
765 certificateType,
766 clientRandom, serverRandom,
767 tackExt):
768
769
770 for result in self._getMsg(ContentType.handshake,
771 HandshakeType.certificate, certificateType):
772 if result in (0,1): yield result
773 else: break
774 serverCertificate = result
775
776
777 for result in self._getMsg(ContentType.handshake,
778 (HandshakeType.server_hello_done,
779 HandshakeType.certificate_request)):
780 if result in (0,1): yield result
781 else: break
782 msg = result
783 certificateRequest = None
784 if isinstance(msg, CertificateRequest):
785 certificateRequest = msg
786
787 for result in self._getMsg(ContentType.handshake,
788 HandshakeType.server_hello_done):
789 if result in (0,1): yield result
790 else: break
791 serverHelloDone = result
792 elif isinstance(msg, ServerHelloDone):
793 serverHelloDone = msg
794
795
796
797
798 for result in self._clientGetKeyFromChain(serverCertificate,
799 settings, tackExt):
800 if result in (0,1): yield result
801 else: break
802 publicKey, serverCertChain, tackExt = result
803
804
805 premasterSecret = getRandomBytes(48)
806 premasterSecret[0] = settings.maxVersion[0]
807 premasterSecret[1] = settings.maxVersion[1]
808
809 if self.fault == Fault.badPremasterPadding:
810 premasterSecret[0] = 5
811 if self.fault == Fault.shortPremasterSecret:
812 premasterSecret = premasterSecret[:-1]
813
814
815 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
816
817
818
819 if certificateRequest:
820 clientCertificate = Certificate(certificateType)
821
822 if clientCertChain:
823
824
825 wrongType = False
826 if certificateType == CertificateType.x509:
827 if not isinstance(clientCertChain, X509CertChain):
828 wrongType = True
829 if wrongType:
830 for result in self._sendError(\
831 AlertDescription.handshake_failure,
832 "Client certificate is of wrong type"):
833 yield result
834
835 clientCertificate.create(clientCertChain)
836 for result in self._sendMsg(clientCertificate):
837 yield result
838 else:
839
840
841
842 privateKey = None
843 clientCertChain = None
844
845
846 clientKeyExchange = ClientKeyExchange(cipherSuite,
847 self.version)
848 clientKeyExchange.createRSA(encryptedPreMasterSecret)
849 for result in self._sendMsg(clientKeyExchange):
850 yield result
851
852
853
854 if certificateRequest and privateKey:
855 if self.version == (3,0):
856 masterSecret = calcMasterSecret(self.version,
857 premasterSecret,
858 clientRandom,
859 serverRandom)
860 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
861 elif self.version in ((3,1), (3,2)):
862 verifyBytes = self._handshake_md5.digest() + \
863 self._handshake_sha.digest()
864 elif self.version == (3,3):
865 verifyBytes = self._handshake_sha256.digest()
866 if self.fault == Fault.badVerifyMessage:
867 verifyBytes[0] = ((verifyBytes[0]+1) % 256)
868 signedBytes = privateKey.sign(verifyBytes)
869 certificateVerify = CertificateVerify()
870 certificateVerify.create(signedBytes)
871 for result in self._sendMsg(certificateVerify):
872 yield result
873 yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
874
877 for result in self._getMsg(ContentType.handshake,
878 HandshakeType.server_key_exchange, cipherSuite):
879 if result in (0,1): yield result
880 else: break
881 serverKeyExchange = result
882
883 for result in self._getMsg(ContentType.handshake,
884 HandshakeType.server_hello_done):
885 if result in (0,1): yield result
886 else: break
887 serverHelloDone = result
888
889
890 dh_p = serverKeyExchange.dh_p
891 dh_g = serverKeyExchange.dh_g
892 dh_Xc = bytesToNumber(getRandomBytes(32))
893 dh_Ys = serverKeyExchange.dh_Ys
894 dh_Yc = powMod(dh_g, dh_Xc, dh_p)
895
896
897 for result in self._sendMsg(\
898 ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
899 yield result
900
901
902 S = powMod(dh_Ys, dh_Xc, dh_p)
903 premasterSecret = numberToByteArray(S)
904
905 yield (premasterSecret, None, None)
906
907 - def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
908 cipherSuite, cipherImplementations, nextProto):
909
910 masterSecret = calcMasterSecret(self.version, premasterSecret,
911 clientRandom, serverRandom)
912 self._calcPendingStates(cipherSuite, masterSecret,
913 clientRandom, serverRandom,
914 cipherImplementations)
915
916
917 for result in self._sendFinished(masterSecret, nextProto):
918 yield result
919 for result in self._getFinished(masterSecret, nextProto=nextProto):
920 yield result
921 yield masterSecret
922
959
960
961
962
963
964
965
966 - def handshakeServer(self, verifierDB=None,
967 certChain=None, privateKey=None, reqCert=False,
968 sessionCache=None, settings=None, checker=None,
969 reqCAs = None,
970 tacks=None, activationFlags=0,
971 nextProtos=None, anon=False):
972 """Perform a handshake in the role of server.
973
974 This function performs an SSL or TLS handshake. Depending on
975 the arguments and the behavior of the client, this function can
976 perform an SRP, or certificate-based handshake. It
977 can also perform a combined SRP and server-certificate
978 handshake.
979
980 Like any handshake function, this can be called on a closed
981 TLS connection, or on a TLS connection that is already open.
982 If called on an open connection it performs a re-handshake.
983 This function does not send a Hello Request message before
984 performing the handshake, so if re-handshaking is required,
985 the server must signal the client to begin the re-handshake
986 through some other means.
987
988 If the function completes without raising an exception, the
989 TLS connection will be open and available for data transfer.
990
991 If an exception is raised, the connection will have been
992 automatically closed (if it was ever open).
993
994 @type verifierDB: L{tlslite.verifierdb.VerifierDB}
995 @param verifierDB: A database of SRP password verifiers
996 associated with usernames. If the client performs an SRP
997 handshake, the session's srpUsername attribute will be set.
998
999 @type certChain: L{tlslite.x509certchain.X509CertChain}
1000 @param certChain: The certificate chain to be used if the
1001 client requests server certificate authentication.
1002
1003 @type privateKey: L{tlslite.utils.rsakey.RSAKey}
1004 @param privateKey: The private key to be used if the client
1005 requests server certificate authentication.
1006
1007 @type reqCert: bool
1008 @param reqCert: Whether to request client certificate
1009 authentication. This only applies if the client chooses server
1010 certificate authentication; if the client chooses SRP
1011 authentication, this will be ignored. If the client
1012 performs a client certificate authentication, the sessions's
1013 clientCertChain attribute will be set.
1014
1015 @type sessionCache: L{tlslite.sessioncache.SessionCache}
1016 @param sessionCache: An in-memory cache of resumable sessions.
1017 The client can resume sessions from this cache. Alternatively,
1018 if the client performs a full handshake, a new session will be
1019 added to the cache.
1020
1021 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
1022 @param settings: Various settings which can be used to control
1023 the ciphersuites and SSL/TLS version chosen by the server.
1024
1025 @type checker: L{tlslite.checker.Checker}
1026 @param checker: A Checker instance. This instance will be
1027 invoked to examine the other party's authentication
1028 credentials, if the handshake completes succesfully.
1029
1030 @type reqCAs: list of L{bytearray} of unsigned bytes
1031 @param reqCAs: A collection of DER-encoded DistinguishedNames that
1032 will be sent along with a certificate request. This does not affect
1033 verification.
1034
1035 @type nextProtos: list of strings.
1036 @param nextProtos: A list of upper layer protocols to expose to the
1037 clients through the Next-Protocol Negotiation Extension,
1038 if they support it.
1039
1040 @raise socket.error: If a socket error occurs.
1041 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1042 without a preceding alert.
1043 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1044 @raise tlslite.errors.TLSAuthenticationError: If the checker
1045 doesn't like the other party's authentication credentials.
1046 """
1047 for result in self.handshakeServerAsync(verifierDB,
1048 certChain, privateKey, reqCert, sessionCache, settings,
1049 checker, reqCAs,
1050 tacks=tacks, activationFlags=activationFlags,
1051 nextProtos=nextProtos, anon=anon):
1052 pass
1053
1054
1055 - def handshakeServerAsync(self, verifierDB=None,
1056 certChain=None, privateKey=None, reqCert=False,
1057 sessionCache=None, settings=None, checker=None,
1058 reqCAs=None,
1059 tacks=None, activationFlags=0,
1060 nextProtos=None, anon=False
1061 ):
1062 """Start a server handshake operation on the TLS connection.
1063
1064 This function returns a generator which behaves similarly to
1065 handshakeServer(). Successive invocations of the generator
1066 will return 0 if it is waiting to read from the socket, 1 if it is
1067 waiting to write to the socket, or it will raise StopIteration
1068 if the handshake operation is complete.
1069
1070 @rtype: iterable
1071 @return: A generator; see above for details.
1072 """
1073 handshaker = self._handshakeServerAsyncHelper(\
1074 verifierDB=verifierDB, certChain=certChain,
1075 privateKey=privateKey, reqCert=reqCert,
1076 sessionCache=sessionCache, settings=settings,
1077 reqCAs=reqCAs,
1078 tacks=tacks, activationFlags=activationFlags,
1079 nextProtos=nextProtos, anon=anon)
1080 for result in self._handshakeWrapperAsync(handshaker, checker):
1081 yield result
1082
1083
1084 - def _handshakeServerAsyncHelper(self, verifierDB,
1085 certChain, privateKey, reqCert, sessionCache,
1086 settings, reqCAs,
1087 tacks, activationFlags,
1088 nextProtos, anon):
1089
1090 self._handshakeStart(client=False)
1091
1092 if (not verifierDB) and (not certChain) and not anon:
1093 raise ValueError("Caller passed no authentication credentials")
1094 if certChain and not privateKey:
1095 raise ValueError("Caller passed a certChain but no privateKey")
1096 if privateKey and not certChain:
1097 raise ValueError("Caller passed a privateKey but no certChain")
1098 if reqCAs and not reqCert:
1099 raise ValueError("Caller passed reqCAs but not reqCert")
1100 if certChain and not isinstance(certChain, X509CertChain):
1101 raise ValueError("Unrecognized certificate type")
1102 if activationFlags and not tacks:
1103 raise ValueError("Nonzero activationFlags requires tacks")
1104 if tacks:
1105 if not tackpyLoaded:
1106 raise ValueError("tackpy is not loaded")
1107 if not settings or not settings.useExperimentalTackExtension:
1108 raise ValueError("useExperimentalTackExtension not enabled")
1109
1110 if not settings:
1111 settings = HandshakeSettings()
1112 settings = settings._filter()
1113
1114
1115
1116
1117
1118 for result in self._serverGetClientHello(settings, certChain,\
1119 verifierDB, sessionCache,
1120 anon):
1121 if result in (0,1): yield result
1122 elif result == None:
1123 self._handshakeDone(resumed=True)
1124 return
1125 else: break
1126 (clientHello, cipherSuite) = result
1127
1128
1129
1130
1131 if sessionCache:
1132 sessionID = getRandomBytes(32)
1133 else:
1134 sessionID = bytearray(0)
1135
1136 if not clientHello.supports_npn:
1137 nextProtos = None
1138
1139
1140 if not cipherSuite in CipherSuite.certAllSuites:
1141 tacks = None
1142
1143
1144 if clientHello.tack:
1145 tackExt = TackExtension.create(tacks, activationFlags)
1146 else:
1147 tackExt = None
1148 serverHello = ServerHello()
1149 serverHello.create(self.version, getRandomBytes(32), sessionID, \
1150 cipherSuite, CertificateType.x509, tackExt,
1151 nextProtos)
1152
1153
1154 clientCertChain = None
1155 if cipherSuite in CipherSuite.srpAllSuites:
1156 for result in self._serverSRPKeyExchange(clientHello, serverHello,
1157 verifierDB, cipherSuite,
1158 privateKey, certChain):
1159 if result in (0,1): yield result
1160 else: break
1161 premasterSecret = result
1162
1163
1164 elif cipherSuite in CipherSuite.certSuites:
1165 for result in self._serverCertKeyExchange(clientHello, serverHello,
1166 certChain, privateKey,
1167 reqCert, reqCAs, cipherSuite,
1168 settings):
1169 if result in (0,1): yield result
1170 else: break
1171 (premasterSecret, clientCertChain) = result
1172
1173
1174 elif cipherSuite in CipherSuite.anonSuites:
1175 for result in self._serverAnonKeyExchange(clientHello, serverHello,
1176 cipherSuite, settings):
1177 if result in (0,1): yield result
1178 else: break
1179 premasterSecret = result
1180
1181 else:
1182 assert(False)
1183
1184
1185 for result in self._serverFinished(premasterSecret,
1186 clientHello.random, serverHello.random,
1187 cipherSuite, settings.cipherImplementations,
1188 nextProtos):
1189 if result in (0,1): yield result
1190 else: break
1191 masterSecret = result
1192
1193
1194 self.session = Session()
1195 if cipherSuite in CipherSuite.certAllSuites:
1196 serverCertChain = certChain
1197 else:
1198 serverCertChain = None
1199 srpUsername = None
1200 serverName = None
1201 if clientHello.srp_username:
1202 srpUsername = clientHello.srp_username.decode("utf-8")
1203 if clientHello.server_name:
1204 serverName = clientHello.server_name.decode("utf-8")
1205 self.session.create(masterSecret, serverHello.session_id, cipherSuite,
1206 srpUsername, clientCertChain, serverCertChain,
1207 tackExt, serverHello.tackExt!=None, serverName)
1208
1209
1210 if sessionCache and sessionID:
1211 sessionCache[sessionID] = self.session
1212
1213 self._handshakeDone(resumed=False)
1214
1215
1218
1219 cipherSuites = []
1220 if verifierDB:
1221 if certChain:
1222 cipherSuites += \
1223 CipherSuite.getSrpCertSuites(settings)
1224 cipherSuites += CipherSuite.getSrpSuites(settings)
1225 elif certChain:
1226 cipherSuites += CipherSuite.getCertSuites(settings)
1227 elif anon:
1228 cipherSuites += CipherSuite.getAnonSuites(settings)
1229 else:
1230 assert(False)
1231
1232
1233
1234
1235 self.version = settings.maxVersion
1236
1237
1238 for result in self._getMsg(ContentType.handshake,
1239 HandshakeType.client_hello):
1240 if result in (0,1): yield result
1241 else: break
1242 clientHello = result
1243
1244
1245 if clientHello.client_version < settings.minVersion:
1246 self.version = settings.minVersion
1247 for result in self._sendError(\
1248 AlertDescription.protocol_version,
1249 "Too old version: %s" % str(clientHello.client_version)):
1250 yield result
1251
1252
1253 elif clientHello.client_version > settings.maxVersion:
1254 self.version = settings.maxVersion
1255
1256 else:
1257
1258 self.version = clientHello.client_version
1259
1260
1261 if clientHello.session_id and sessionCache:
1262 session = None
1263
1264
1265 if sessionCache and not session:
1266 try:
1267 session = sessionCache[clientHello.session_id]
1268 if not session.resumable:
1269 raise AssertionError()
1270
1271 if session.cipherSuite not in cipherSuites:
1272 for result in self._sendError(\
1273 AlertDescription.handshake_failure):
1274 yield result
1275 if session.cipherSuite not in clientHello.cipher_suites:
1276 for result in self._sendError(\
1277 AlertDescription.handshake_failure):
1278 yield result
1279 if clientHello.srp_username:
1280 if not session.srpUsername or \
1281 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"):
1282 for result in self._sendError(\
1283 AlertDescription.handshake_failure):
1284 yield result
1285 if clientHello.server_name:
1286 if not session.serverName or \
1287 clientHello.server_name != bytearray(session.serverName, "utf-8"):
1288 for result in self._sendError(\
1289 AlertDescription.handshake_failure):
1290 yield result
1291 except KeyError:
1292 pass
1293
1294
1295 if session:
1296
1297 serverHello = ServerHello()
1298 serverHello.create(self.version, getRandomBytes(32),
1299 session.sessionID, session.cipherSuite,
1300 CertificateType.x509, None, None)
1301 for result in self._sendMsg(serverHello):
1302 yield result
1303
1304
1305 self._versionCheck = True
1306
1307
1308 self._calcPendingStates(session.cipherSuite,
1309 session.masterSecret,
1310 clientHello.random,
1311 serverHello.random,
1312 settings.cipherImplementations)
1313
1314
1315 for result in self._sendFinished(session.masterSecret):
1316 yield result
1317 for result in self._getFinished(session.masterSecret):
1318 yield result
1319
1320
1321 self.session = session
1322
1323 yield None
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333 for cipherSuite in cipherSuites:
1334 if cipherSuite in clientHello.cipher_suites:
1335 break
1336 else:
1337 for result in self._sendError(\
1338 AlertDescription.handshake_failure,
1339 "No mutual ciphersuite"):
1340 yield result
1341 if cipherSuite in CipherSuite.srpAllSuites and \
1342 not clientHello.srp_username:
1343 for result in self._sendError(\
1344 AlertDescription.unknown_psk_identity,
1345 "Client sent a hello, but without the SRP username"):
1346 yield result
1347
1348
1349 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \
1350 not in clientHello.certificate_types:
1351 for result in self._sendError(\
1352 AlertDescription.handshake_failure,
1353 "the client doesn't support my certificate type"):
1354 yield result
1355
1356
1357
1358
1359 yield (clientHello, cipherSuite)
1360
1361 - def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB,
1362 cipherSuite, privateKey, serverCertChain):
1363
1364 srpUsername = clientHello.srp_username.decode("utf-8")
1365 self.allegedSrpUsername = srpUsername
1366
1367 try:
1368 entry = verifierDB[srpUsername]
1369 except KeyError:
1370 for result in self._sendError(\
1371 AlertDescription.unknown_psk_identity):
1372 yield result
1373 (N, g, s, v) = entry
1374
1375
1376 b = bytesToNumber(getRandomBytes(32))
1377 k = makeK(N, g)
1378 B = (powMod(g, b, N) + (k*v)) % N
1379
1380
1381 serverKeyExchange = ServerKeyExchange(cipherSuite)
1382 serverKeyExchange.createSRP(N, g, s, B)
1383 if cipherSuite in CipherSuite.srpCertSuites:
1384 hashBytes = serverKeyExchange.hash(clientHello.random,
1385 serverHello.random)
1386 serverKeyExchange.signature = privateKey.sign(hashBytes)
1387
1388
1389
1390 msgs = []
1391 msgs.append(serverHello)
1392 if cipherSuite in CipherSuite.srpCertSuites:
1393 certificateMsg = Certificate(CertificateType.x509)
1394 certificateMsg.create(serverCertChain)
1395 msgs.append(certificateMsg)
1396 msgs.append(serverKeyExchange)
1397 msgs.append(ServerHelloDone())
1398 for result in self._sendMsgs(msgs):
1399 yield result
1400
1401
1402 self._versionCheck = True
1403
1404
1405 for result in self._getMsg(ContentType.handshake,
1406 HandshakeType.client_key_exchange,
1407 cipherSuite):
1408 if result in (0,1): yield result
1409 else: break
1410 clientKeyExchange = result
1411 A = clientKeyExchange.srp_A
1412 if A % N == 0:
1413 for result in self._sendError(AlertDescription.illegal_parameter,
1414 "Suspicious A value"):
1415 yield result
1416 assert(False)
1417
1418
1419 u = makeU(N, A, B)
1420
1421
1422 S = powMod((A * powMod(v,u,N)) % N, b, N)
1423 premasterSecret = numberToByteArray(S)
1424
1425 yield premasterSecret
1426
1427
1428 - def _serverCertKeyExchange(self, clientHello, serverHello,
1429 serverCertChain, privateKey,
1430 reqCert, reqCAs, cipherSuite,
1431 settings):
1432
1433
1434 msgs = []
1435
1436
1437 clientCertChain = None
1438
1439 msgs.append(serverHello)
1440 msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
1441 if reqCert and reqCAs:
1442 msgs.append(CertificateRequest().create(\
1443 [ClientCertificateType.rsa_sign], reqCAs))
1444 elif reqCert:
1445 msgs.append(CertificateRequest(self.version))
1446 msgs.append(ServerHelloDone())
1447 for result in self._sendMsgs(msgs):
1448 yield result
1449
1450
1451 self._versionCheck = True
1452
1453
1454 if reqCert:
1455 if self.version == (3,0):
1456 for result in self._getMsg((ContentType.handshake,
1457 ContentType.alert),
1458 HandshakeType.certificate,
1459 CertificateType.x509):
1460 if result in (0,1): yield result
1461 else: break
1462 msg = result
1463
1464 if isinstance(msg, Alert):
1465
1466 alert = msg
1467 if alert.description != \
1468 AlertDescription.no_certificate:
1469 self._shutdown(False)
1470 raise TLSRemoteAlert(alert)
1471 elif isinstance(msg, Certificate):
1472 clientCertificate = msg
1473 if clientCertificate.certChain and \
1474 clientCertificate.certChain.getNumCerts()!=0:
1475 clientCertChain = clientCertificate.certChain
1476 else:
1477 raise AssertionError()
1478 elif self.version in ((3,1), (3,2), (3,3)):
1479 for result in self._getMsg(ContentType.handshake,
1480 HandshakeType.certificate,
1481 CertificateType.x509):
1482 if result in (0,1): yield result
1483 else: break
1484 clientCertificate = result
1485 if clientCertificate.certChain and \
1486 clientCertificate.certChain.getNumCerts()!=0:
1487 clientCertChain = clientCertificate.certChain
1488 else:
1489 raise AssertionError()
1490
1491
1492 for result in self._getMsg(ContentType.handshake,
1493 HandshakeType.client_key_exchange,
1494 cipherSuite):
1495 if result in (0,1): yield result
1496 else: break
1497 clientKeyExchange = result
1498
1499
1500 premasterSecret = privateKey.decrypt(\
1501 clientKeyExchange.encryptedPreMasterSecret)
1502
1503
1504
1505 randomPreMasterSecret = getRandomBytes(48)
1506 versionCheck = (premasterSecret[0], premasterSecret[1])
1507 if not premasterSecret:
1508 premasterSecret = randomPreMasterSecret
1509 elif len(premasterSecret)!=48:
1510 premasterSecret = randomPreMasterSecret
1511 elif versionCheck != clientHello.client_version:
1512 if versionCheck != self.version:
1513 premasterSecret = randomPreMasterSecret
1514
1515
1516 if clientCertChain:
1517 if self.version == (3,0):
1518 masterSecret = calcMasterSecret(self.version, premasterSecret,
1519 clientHello.random, serverHello.random)
1520 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
1521 elif self.version in ((3,1), (3,2)):
1522 verifyBytes = self._handshake_md5.digest() + \
1523 self._handshake_sha.digest()
1524 elif self.version == (3,3):
1525 verifyBytes = self._handshake_sha256.digest()
1526 for result in self._getMsg(ContentType.handshake,
1527 HandshakeType.certificate_verify):
1528 if result in (0,1): yield result
1529 else: break
1530 certificateVerify = result
1531 publicKey = clientCertChain.getEndEntityPublicKey()
1532 if len(publicKey) < settings.minKeySize:
1533 for result in self._sendError(\
1534 AlertDescription.handshake_failure,
1535 "Client's public key too small: %d" % len(publicKey)):
1536 yield result
1537
1538 if len(publicKey) > settings.maxKeySize:
1539 for result in self._sendError(\
1540 AlertDescription.handshake_failure,
1541 "Client's public key too large: %d" % len(publicKey)):
1542 yield result
1543
1544 if not publicKey.verify(certificateVerify.signature, verifyBytes):
1545 for result in self._sendError(\
1546 AlertDescription.decrypt_error,
1547 "Signature failed to verify"):
1548 yield result
1549 yield (premasterSecret, clientCertChain)
1550
1551
1554
1555 dh_p = getRandomSafePrime(32, False)
1556 dh_g = getRandomNumber(2, dh_p)
1557 dh_Xs = bytesToNumber(getRandomBytes(32))
1558 dh_Ys = powMod(dh_g, dh_Xs, dh_p)
1559
1560
1561 serverKeyExchange = ServerKeyExchange(cipherSuite)
1562 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
1563
1564
1565
1566 msgs = []
1567 msgs.append(serverHello)
1568 msgs.append(serverKeyExchange)
1569 msgs.append(ServerHelloDone())
1570 for result in self._sendMsgs(msgs):
1571 yield result
1572
1573
1574 self._versionCheck = True
1575
1576
1577 for result in self._getMsg(ContentType.handshake,
1578 HandshakeType.client_key_exchange,
1579 cipherSuite):
1580 if result in (0,1):
1581 yield result
1582 else:
1583 break
1584 clientKeyExchange = result
1585 dh_Yc = clientKeyExchange.dh_Yc
1586
1587 if dh_Yc % dh_p == 0:
1588 for result in self._sendError(AlertDescription.illegal_parameter,
1589 "Suspicious dh_Yc value"):
1590 yield result
1591 assert(False)
1592
1593
1594 S = powMod(dh_Yc,dh_Xs,dh_p)
1595 premasterSecret = numberToByteArray(S)
1596
1597 yield premasterSecret
1598
1599
1600 - def _serverFinished(self, premasterSecret, clientRandom, serverRandom,
1601 cipherSuite, cipherImplementations, nextProtos):
1602 masterSecret = calcMasterSecret(self.version, premasterSecret,
1603 clientRandom, serverRandom)
1604
1605
1606 self._calcPendingStates(cipherSuite, masterSecret,
1607 clientRandom, serverRandom,
1608 cipherImplementations)
1609
1610
1611 for result in self._getFinished(masterSecret,
1612 expect_next_protocol=nextProtos is not None):
1613 yield result
1614
1615 for result in self._sendFinished(masterSecret):
1616 yield result
1617
1618 yield masterSecret
1619
1620
1621
1622
1623
1624
1625
1648
1649 - def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None):
1695
1697 if self.version == (3,0):
1698 if (self._client and send) or (not self._client and not send):
1699 senderStr = b"\x43\x4C\x4E\x54"
1700 else:
1701 senderStr = b"\x53\x52\x56\x52"
1702
1703 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr)
1704 return verifyData
1705
1706 elif self.version in ((3,1), (3,2)):
1707 if (self._client and send) or (not self._client and not send):
1708 label = b"client finished"
1709 else:
1710 label = b"server finished"
1711
1712 handshakeHashes = self._handshake_md5.digest() + \
1713 self._handshake_sha.digest()
1714 verifyData = PRF(masterSecret, label, handshakeHashes, 12)
1715 return verifyData
1716 elif self.version == (3,3):
1717 if (self._client and send) or (not self._client and not send):
1718 label = b"client finished"
1719 else:
1720 label = b"server finished"
1721
1722 handshakeHashes = self._handshake_sha256.digest()
1723 verifyData = PRF_1_2(masterSecret, label, handshakeHashes, 12)
1724 return verifyData
1725 else:
1726 raise AssertionError()
1727
1728
1755