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