1
2
3
4
5
6
7
8
9
10
11 """Classes representing TLS messages."""
12
13 from .utils.compat import *
14 from .utils.cryptomath import *
15 from .errors import *
16 from .utils.codec import *
17 from .constants import *
18 from .x509 import X509
19 from .x509certchain import X509CertChain
20 from .utils.tackwrapper import *
21 from .extensions import *
25 """Generic interface to SSLv2 and SSLv3 (and later) record headers."""
26
28 """Define instance variables."""
29 self.type = 0
30 self.version = (0, 0)
31 self.length = 0
32 self.ssl2 = ssl2
33
36 """SSLv3 (and later) TLS record header."""
37
41
43 """Set object values for writing (serialisation)."""
44 self.type = type
45 self.version = version
46 self.length = length
47 return self
48
50 """Serialise object to bytearray."""
51 writer = Writer()
52 writer.add(self.type, 1)
53 writer.add(self.version[0], 1)
54 writer.add(self.version[1], 1)
55 writer.add(self.length, 2)
56 return writer.bytes
57
59 """Deserialise object from Parser."""
60 self.type = parser.get(1)
61 self.version = (parser.get(1), parser.get(1))
62 self.length = parser.get(2)
63 self.ssl2 = False
64 return self
65
66 @property
68 matching = [x[0] for x in ContentType.__dict__.items()
69 if x[1] == self.type]
70 if len(matching) == 0:
71 return "unknown(" + str(self.type) + ")"
72 else:
73 return str(matching[0])
74
76 return "SSLv3 record,version({0[0]}.{0[1]}),"\
77 "content type({1}),length({2})".format(self.version,
78 self.typeName,
79 self.length)
80
82 return "RecordHeader3(type={0}, version=({1[0]}.{1[1]}), length={2})".\
83 format(self.type, self.version, self.length)
84
87 """
88 SSLv2 record header.
89
90 @type padding: int
91 @ivar padding: number of bytes added at end of message to make it multiple
92 of block cipher size
93 @type securityEscape: boolean
94 @ivar securityEscape: whether the record contains a security escape message
95 """
96
98 """Define a SSLv2 style class."""
99 super(RecordHeader2, self).__init__(ssl2=True)
100 self.padding = 0
101 self.securityEscape = False
102
104 """Deserialise object from Parser."""
105 firstByte = parser.get(1)
106 secondByte = parser.get(1)
107 if firstByte & 0x80:
108 self.length = ((firstByte & 0x7f) << 8) | secondByte
109 else:
110 self.length = ((firstByte & 0x3f) << 8) | secondByte
111 self.securityEscape = firstByte & 0x40 != 0
112 self.padding = parser.get(1)
113
114 self.type = ContentType.handshake
115 self.version = (2, 0)
116 return self
117
119 """Set object's values."""
120 self.length = length
121 self.padding = padding
122 self.securityEscape = securityEscape
123 return self
124
126 """Serialise object to bytearray."""
127 writer = Writer()
128
129 shortHeader = not (self.padding or self.securityEscape)
130
131 if ((shortHeader and self.length >= 0x8000) or
132 (not shortHeader and self.length >= 0x4000)):
133 raise ValueError("length too large")
134
135 firstByte = 0
136 if shortHeader:
137 firstByte |= 0x80
138 if self.securityEscape:
139 firstByte |= 0x40
140 firstByte |= self.length >> 8
141 secondByte = self.length & 0xff
142
143 writer.add(firstByte, 1)
144 writer.add(secondByte, 1)
145 if not shortHeader:
146 writer.add(self.padding, 1)
147
148 return writer.bytes
149
152 """Generic TLS message."""
153
155 """
156 Initialize object with specified contentType and data.
157
158 @type contentType: int
159 @param contentType: TLS record layer content type of associated data
160 @type data: bytearray
161 @param data: data
162 """
163 self.contentType = contentType
164 self.data = data
165
167 """Return serialised object data."""
168 return self.data
169
173 self.contentType = ContentType.alert
174 self.level = 0
175 self.description = 0
176
178 self.level = level
179 self.description = description
180 return self
181
188
190 w = Writer()
191 w.add(self.level, 1)
192 w.add(self.description, 1)
193 return w.bytes
194
195 @staticmethod
197 """if text is None or empty, format number as 'unknown(number)'"""
198 if not text:
199 text = "unknown({0})".format(number)
200 return text
201
202 @property
206
207 @property
211
215
217 return "Alert(level={0}, description={1})".format(self.level,
218 self.description)
219
225
226 - def postWrite(self, w):
227 headerWriter = Writer()
228 headerWriter.add(self.handshakeType, 1)
229 headerWriter.add(len(w.bytes), 3)
230 return headerWriter.bytes + w.bytes
231
234 """Class for sharing code between L{ClientHello} and L{ServerHello}"""
235
240
241 - def getExtension(self, extType):
242 """
243 Return extension of given type if present, None otherwise.
244
245 @rtype: L{tlslite.extensions.TLSExtension}
246 @raise TLSInternalError: when there are multiple extensions of the
247 same type
248 """
249 if self.extensions is None:
250 return None
251
252 exts = [ext for ext in self.extensions if ext.extType == extType]
253 if len(exts) > 1:
254 raise TLSInternalError(
255 "Multiple extensions of the same type present")
256 elif len(exts) == 1:
257 return exts[0]
258 else:
259 return None
260
262 """
263 Add extension to internal list of extensions.
264
265 @type ext: TLSExtension
266 @param ext: extension object to add to list
267 """
268 if self.extensions is None:
269 self.extensions = []
270
271 self.extensions.append(ext)
272
274 """Add en empty extension of given type, if not already present"""
275 ext = self.getExtension(extType)
276 if ext is None:
277 ext = TLSExtension(extType=extType).create(bytearray(0))
278 self.addExtension(ext)
279
281 """Remove extension of given type"""
282 if self.extensions is not None:
283 self.extensions[:] = (i for i in self.extensions
284 if i.extType != extType)
285
286
288 """
289 Remove or add an empty extension of given type.
290
291 @type extType: int
292 @param extType: numeric id of extension to add or remove
293 @type add: boolean
294 @param add: whether to add (True) or remove (False) the extension
295 """
296 if add:
297 self._addExt(extType)
298 else:
299 self._removeExt(extType)
300
303 """
304 Class for handling the ClientHello SSLv2/SSLv3/TLS message.
305
306 @type certificate_types: list
307 @ivar certificate_types: list of supported certificate types (deprecated)
308
309 @type srp_username: bytearray
310 @ivar srp_username: name of the user in SRP extension (deprecated)
311
312 @type supports_npn: boolean
313 @ivar supports_npn: NPN extension presence (deprecated)
314
315 @type tack: boolean
316 @ivar tack: TACK extension presence (deprecated)
317
318 @type server_name: bytearray
319 @ivar server_name: first host_name (type 0) present in SNI extension
320 (deprecated)
321
322 @type extensions: list of L{TLSExtension}
323 @ivar extensions: list of TLS extensions parsed from wire or to send, see
324 L{TLSExtension} and child classes for exact examples
325 """
326
328 super(ClientHello, self).__init__(HandshakeType.client_hello)
329 self.ssl2 = ssl2
330 self.client_version = (0, 0)
331 self.random = bytearray(32)
332 self.session_id = bytearray(0)
333 self.cipher_suites = []
334 self.compression_methods = []
335
337 """
338 Return human readable representation of Client Hello.
339
340 @rtype: str
341 """
342 if self.session_id.count(bytearray(b'\x00')) == len(self.session_id)\
343 and len(self.session_id) != 0:
344 session = "bytearray(b'\\x00'*{0})".format(len(self.session_id))
345 else:
346 session = repr(self.session_id)
347 ret = "client_hello,version({0[0]}.{0[1]}),random(...),"\
348 "session ID({1!s}),cipher suites({2!r}),"\
349 "compression methods({3!r})".format(
350 self.client_version, session,
351 self.cipher_suites, self.compression_methods)
352
353 if self.extensions is not None:
354 ret += ",extensions({0!r})".format(self.extensions)
355
356 return ret
357
359 """
360 Return machine readable representation of Client Hello.
361
362 @rtype: str
363 """
364 return "ClientHello(ssl2={0}, client_version=({1[0]}.{1[1]}), "\
365 "random={2!r}, session_id={3!r}, cipher_suites={4!r}, "\
366 "compression_methods={5}, extensions={6})".format(
367 self.ssl2, self.client_version, self.random,
368 self.session_id, self.cipher_suites,
369 self.compression_methods, self.extensions)
370
371 @property
385
386 @certificate_types.setter
388 """
389 Set list of supported certificate types.
390
391 Sets the list of supported types to list given in L{val} if the
392 cert_type extension is present. Creates the extension and places it
393 last in the list otherwise.
394
395 @type val: list
396 @param val: list of supported certificate types by client encoded as
397 single byte integers
398 """
399 cert_type = self.getExtension(ExtensionType.cert_type)
400
401 if cert_type is None:
402 ext = ClientCertTypeExtension().create(val)
403 self.addExtension(ext)
404 else:
405 cert_type.certTypes = val
406
407 @property
409 """
410 Return username for the SRP.
411
412 @deprecated: use extensions field to get the extension for inspection
413 """
414 srp_ext = self.getExtension(ExtensionType.srp)
415
416 if srp_ext is None:
417 return None
418 else:
419 return srp_ext.identity
420
421 @srp_username.setter
436
437 @property
439 """
440 Return whether the client supports TACK.
441
442 @rtype: boolean
443 @deprecated: use extensions field to get the extension for inspection
444 """
445 return self.getExtension(ExtensionType.tack) is not None
446
447 @tack.setter
448 - def tack(self, present):
449 """
450 Create or delete the TACK extension.
451
452 @type present: boolean
453 @param present: True will create extension while False will remove
454 extension from client hello
455 """
456 self._addOrRemoveExt(ExtensionType.tack, present)
457
458 @property
460 """
461 Return whether client supports NPN extension.
462
463 @rtype: boolean
464 @deprecated: use extensions field to get the extension for inspection
465 """
466 return self.getExtension(ExtensionType.supports_npn) is not None
467
468 @supports_npn.setter
470 """
471 Create or delete the NPN extension.
472
473 @type present: boolean
474 @param present: selects whatever to create or remove the extension
475 from list of supported ones
476 """
477 self._addOrRemoveExt(ExtensionType.supports_npn, present)
478
479 @property
481 """
482 Return first host_name present in SNI extension.
483
484 @rtype: bytearray
485 @deprecated: use extensions field to get the extension for inspection
486 """
487 sni_ext = self.getExtension(ExtensionType.server_name)
488 if sni_ext is None:
489 return bytearray(0)
490 else:
491 if len(sni_ext.hostNames) > 0:
492 return sni_ext.hostNames[0]
493 else:
494 return bytearray(0)
495
496 @server_name.setter
512
513 - def create(self, version, random, session_id, cipher_suites,
514 certificate_types=None, srpUsername=None,
515 tack=False, supports_npn=None, serverName=None,
516 extensions=None):
517 """
518 Create a ClientHello message for sending.
519
520 @type version: tuple
521 @param version: the highest supported TLS version encoded as two int
522 tuple
523
524 @type random: bytearray
525 @param random: client provided random value, in old versions of TLS
526 (before 1.2) the first 32 bits should include system time, also
527 used as the "challenge" field in SSLv2
528
529 @type session_id: bytearray
530 @param session_id: ID of session, set when doing session resumption
531
532 @type cipher_suites: list
533 @param cipher_suites: list of ciphersuites advertised as supported
534
535 @type certificate_types: list
536 @param certificate_types: list of supported certificate types, uses
537 TLS extension for signalling, as such requires TLS1.0 to work
538
539 @type srpUsername: bytearray
540 @param srpUsername: utf-8 encoded username for SRP, TLS extension
541
542 @type tack: boolean
543 @param tack: whatever to advertise support for TACK, TLS extension
544
545 @type supports_npn: boolean
546 @param supports_npn: whatever to advertise support for NPN, TLS
547 extension
548
549 @type serverName: bytearray
550 @param serverName: the hostname to request in server name indication
551 extension, TLS extension. Note that SNI allows to set multiple
552 hostnames and values that are not hostnames, use L{SNIExtension}
553 together with L{extensions} to use it.
554
555 @type extensions: list of L{TLSExtension}
556 @param extensions: list of extensions to advertise
557 """
558 self.client_version = version
559 self.random = random
560 self.session_id = session_id
561 self.cipher_suites = cipher_suites
562 self.compression_methods = [0]
563 if extensions is not None:
564 self.extensions = extensions
565 if certificate_types is not None:
566 self.certificate_types = certificate_types
567 if srpUsername is not None:
568 if not isinstance(srpUsername, bytearray):
569 raise TypeError("srpUsername must be a bytearray object")
570 self.srp_username = srpUsername
571 self.tack = tack
572 if supports_npn is not None:
573 self.supports_npn = supports_npn
574 if serverName is not None:
575 self.server_name = bytearray(serverName, "utf-8")
576 return self
577
612
614 """Serialise SSLv2 object to on the wire data."""
615 writer = Writer()
616 writer.add(self.handshakeType, 1)
617 writer.add(self.client_version[0], 1)
618 writer.add(self.client_version[1], 1)
619
620 ciphersWriter = Writer()
621 ciphersWriter.addFixSeq(self.cipher_suites, 3)
622
623 writer.add(len(ciphersWriter.bytes), 2)
624 writer.add(len(self.session_id), 2)
625 writer.add(len(self.random), 2)
626
627 writer.bytes += ciphersWriter.bytes
628 writer.bytes += self.session_id
629 writer.bytes += self.random
630
631
632 return writer.bytes
633
635 """Serialise SSLv3 or TLS object to on the wire data."""
636 w = Writer()
637 w.add(self.client_version[0], 1)
638 w.add(self.client_version[1], 1)
639 w.addFixSeq(self.random, 1)
640 w.addVarSeq(self.session_id, 1, 1)
641 w.addVarSeq(self.cipher_suites, 2, 2)
642 w.addVarSeq(self.compression_methods, 1, 1)
643
644 if self.extensions is not None:
645 w2 = Writer()
646 for ext in self.extensions:
647 w2.bytes += ext.write()
648
649 w.add(len(w2.bytes), 2)
650 w.bytes += w2.bytes
651 return self.postWrite(w)
652
654 """Serialise object to on the wire data."""
655 if self.ssl2:
656 return self._writeSSL2()
657 else:
658 return self._write()
659
662 """
663 Handling of Server Hello messages.
664
665 @type server_version: tuple
666 @ivar server_version: protocol version encoded as two int tuple
667
668 @type random: bytearray
669 @ivar random: server random value
670
671 @type session_id: bytearray
672 @ivar session_id: session identifier for resumption
673
674 @type cipher_suite: int
675 @ivar cipher_suite: server selected cipher_suite
676
677 @type compression_method: int
678 @ivar compression_method: server selected compression method
679
680 @type next_protos: list of bytearray
681 @ivar next_protos: list of advertised protocols in NPN extension
682
683 @type next_protos_advertised: list of bytearray
684 @ivar next_protos_advertised: list of protocols advertised in NPN extension
685
686 @type certificate_type: int
687 @ivar certificate_type: certificate type selected by server
688
689 @type extensions: list
690 @ivar extensions: list of TLS extensions present in server_hello message,
691 see L{TLSExtension} and child classes for exact examples
692 """
693
695 """Initialise ServerHello object."""
696 super(ServerHello, self).__init__(HandshakeType.server_hello)
697 self.server_version = (0, 0)
698 self.random = bytearray(32)
699 self.session_id = bytearray(0)
700 self.cipher_suite = 0
701 self.compression_method = 0
702 self._tack_ext = None
703
705 base = "server_hello,length({0}),version({1[0]}.{1[1]}),random(...),"\
706 "session ID({2!r}),cipher({3:#x}),compression method({4})"\
707 .format(len(self.write())-4, self.server_version,
708 self.session_id, self.cipher_suite,
709 self.compression_method)
710
711 if self.extensions is None:
712 return base
713
714 ret = ",extensions["
715 ret += ",".join(repr(x) for x in self.extensions)
716 ret += "]"
717 return base + ret
718
720 return "ServerHello(server_version=({0[0]}, {0[1]}), random={1!r}, "\
721 "session_id={2!r}, cipher_suite={3}, compression_method={4}, "\
722 "_tack_ext={5}, extensions={6!r})".format(
723 self.server_version, self.random, self.session_id,
724 self.cipher_suite, self.compression_method, self._tack_ext,
725 self.extensions)
726
727 @property
729 """Return the TACK extension."""
730 if self._tack_ext is None:
731 ext = self.getExtension(ExtensionType.tack)
732 if ext is None or not tackpyLoaded:
733 return None
734 else:
735 self._tack_ext = TackExtension(ext.extData)
736 return self._tack_ext
737
738 @tackExt.setter
740 """Set the TACK extension."""
741 self._tack_ext = val
742
743 if val is not None:
744 if self.extensions is None:
745 self.extensions = []
746
747 @property
760
761 @certificate_type.setter
779
780 @property
782 """
783 Return the advertised protocols in NPN extension.
784
785 @rtype: list of bytearrays
786 """
787 npn_ext = self.getExtension(ExtensionType.supports_npn)
788
789 if npn_ext is None:
790 return None
791 else:
792 return npn_ext.protocols
793
794 @next_protos.setter
796 """
797 Set the advertised protocols in NPN extension.
798
799 @type val: list
800 @param val: list of protocols to advertise as UTF-8 encoded names
801 """
802 if val is None:
803 return
804 else:
805
806 val = [bytearray(x) for x in val]
807
808 npn_ext = self.getExtension(ExtensionType.supports_npn)
809
810 if npn_ext is None:
811 ext = NPNExtension().create(val)
812 self.addExtension(ext)
813 else:
814 npn_ext.protocols = val
815
816 @property
818 """
819 Return the advertised protocols in NPN extension.
820
821 @rtype: list of bytearrays
822 """
823 return self.next_protos
824
825 @next_protos_advertised.setter
827 """
828 Set the advertised protocols in NPN extension.
829
830 @type val: list
831 @param val: list of protocols to advertise as UTF-8 encoded names
832 """
833 self.next_protos = val
834
835 - def create(self, version, random, session_id, cipher_suite,
836 certificate_type=None, tackExt=None,
837 next_protos_advertised=None,
838 extensions=None):
851
868
870 w = Writer()
871 w.add(self.server_version[0], 1)
872 w.add(self.server_version[1], 1)
873 w.addFixSeq(self.random, 1)
874 w.addVarSeq(self.session_id, 1, 1)
875 w.add(self.cipher_suite, 2)
876 w.add(self.compression_method, 1)
877
878 if self.extensions is not None:
879 w2 = Writer()
880 for ext in self.extensions:
881 w2.bytes += ext.write()
882
883 if self.tackExt:
884 b = self.tackExt.serialize()
885 w2.add(ExtensionType.tack, 2)
886 w2.add(len(b), 2)
887 w2.bytes += b
888
889 w.add(len(w2.bytes), 2)
890 w.bytes += w2.bytes
891 return self.postWrite(w)
892
895 """
896 SERVER-HELLO message from SSLv2.
897
898 @type session_id_hit: int
899 @ivar session_id_hit: non zero if the client provided session ID was
900 matched in server's session cache
901
902 @type certificate_type: int
903 @ivar certificate_type: type of certificate sent
904
905 @type server_version: tuple of ints
906 @ivar server_version: protocol version selected by server
907
908 @type certificate: bytearray
909 @ivar certificate: certificate sent by server
910
911 @type ciphers: array of int
912 @ivar ciphers: list of ciphers supported by server
913
914 @type session_id: bytearray
915 @ivar session_id: idendifier of negotiated session
916 """
917
926
927 - def create(self, session_id_hit, certificate_type, server_version,
928 certificate, ciphers, session_id):
929 """Initialize fields of the SERVER-HELLO message."""
930 self.session_id_hit = session_id_hit
931 self.certificate_type = certificate_type
932 self.server_version = server_version
933 self.certificate = certificate
934 self.ciphers = ciphers
935 self.session_id = session_id
936 return self
937
939 """Serialise object to on the wire data."""
940 writer = Writer()
941 writer.add(self.handshakeType, 1)
942 writer.add(self.session_id_hit, 1)
943 writer.add(self.certificate_type, 1)
944 if len(self.server_version) != 2:
945 raise ValueError("server version must be a 2-element tuple")
946 writer.addFixSeq(self.server_version, 1)
947 writer.add(len(self.certificate), 2)
948
949 ciphersWriter = Writer()
950 ciphersWriter.addFixSeq(self.ciphers, 3)
951
952 writer.add(len(ciphersWriter.bytes), 2)
953 writer.add(len(self.session_id), 2)
954
955 writer.bytes += self.certificate
956 writer.bytes += ciphersWriter.bytes
957 writer.bytes += self.session_id
958
959
960 return writer.bytes
961
962 - def parse(self, parser):
963 """Deserialise object from on the wire data."""
964 self.session_id_hit = parser.get(1)
965 self.certificate_type = parser.get(1)
966 self.server_version = (parser.get(1), parser.get(1))
967 certificateLength = parser.get(2)
968 ciphersLength = parser.get(2)
969 sessionIDLength = parser.get(2)
970 parser.setLengthCheck(certificateLength +
971 ciphersLength +
972 sessionIDLength)
973 self.certificate = parser.getFixBytes(certificateLength)
974 self.ciphers = parser.getFixList(3, ciphersLength // 3)
975 self.session_id = parser.getFixBytes(sessionIDLength)
976 parser.stopLengthCheck()
977 return self
978
985
987 self.certChain = certChain
988 return self
989
1009
1011 w = Writer()
1012 if self.certificateType == CertificateType.x509:
1013 chainLength = 0
1014 if self.certChain:
1015 certificate_list = self.certChain.x509List
1016 else:
1017 certificate_list = []
1018
1019 for cert in certificate_list:
1020 bytes = cert.writeBytes()
1021 chainLength += len(bytes)+3
1022
1023 w.add(chainLength, 3)
1024 for cert in certificate_list:
1025 bytes = cert.writeBytes()
1026 w.addVarSeq(bytes, 1, 3)
1027 else:
1028 raise AssertionError()
1029 return self.postWrite(w)
1030
1039
1040 - def create(self, certificate_types, certificate_authorities, sig_algs=()):
1041 self.certificate_types = certificate_types
1042 self.certificate_authorities = certificate_authorities
1043 self.supported_signature_algs = sig_algs
1044 return self
1045
1060
1062 w = Writer()
1063 w.addVarSeq(self.certificate_types, 1, 1)
1064 if self.version >= (3, 3):
1065 w.addVarTupleSeq(self.supported_signature_algs, 1, 2)
1066 caLength = 0
1067
1068 for ca_dn in self.certificate_authorities:
1069 caLength += len(ca_dn)+2
1070 w.add(caLength, 2)
1071
1072 for ca_dn in self.certificate_authorities:
1073 w.addVarSeq(ca_dn, 1, 2)
1074 return self.postWrite(w)
1075
1078 """
1079 Handling TLS Handshake protocol Server Key Exchange messages.
1080
1081 @type cipherSuite: int
1082 @cvar cipherSuite: id of ciphersuite selected in Server Hello message
1083 @type srp_N: int
1084 @cvar srp_N: SRP protocol prime
1085 @type srp_g: int
1086 @cvar srp_g: SRP protocol generator
1087 @type srp_s: bytearray
1088 @cvar srp_s: SRP protocol salt value
1089 @type srp_B: int
1090 @cvar srp_B: SRP protocol server public value
1091 @type dh_p: int
1092 @cvar dh_p: FFDHE protocol prime
1093 @type dh_g: int
1094 @cvar dh_g: FFDHE protocol generator
1095 @type dh_Ys: int
1096 @cvar dh_Ys: FFDH protocol server key share
1097 @type curve_type: int
1098 @cvar curve_type: Type of curve used (explicit, named, etc.)
1099 @type named_curve: int
1100 @cvar named_curve: TLS ID of named curve
1101 @type ecdh_Ys: bytearray
1102 @cvar ecdh_Ys: ECDH protocol encoded point key share
1103 @type signature: bytearray
1104 @cvar signature: signature performed over the parameters by server
1105 @type hashAlg: int
1106 @cvar hashAlg: id of hash algorithm used for signature
1107 @type signAlg: int
1108 @cvar signAlg: id of signature algorithm used for signature
1109 """
1110
1111 - def __init__(self, cipherSuite, version):
1112 """
1113 Initialise Server Key Exchange for reading or writing.
1114
1115 @type cipherSuite: int
1116 @param cipherSuite: id of ciphersuite selected by server
1117 """
1118 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange)
1119 self.cipherSuite = cipherSuite
1120 self.version = version
1121 self.srp_N = 0
1122 self.srp_g = 0
1123 self.srp_s = bytearray(0)
1124 self.srp_B = 0
1125
1126 self.dh_p = 0
1127 self.dh_g = 0
1128 self.dh_Ys = 0
1129
1130 self.curve_type = None
1131 self.named_curve = None
1132 self.ecdh_Ys = bytearray(0)
1133
1134 self.signature = bytearray(0)
1135
1136 self.hashAlg = 0
1137 self.signAlg = 0
1138
1140 ret = "ServerKeyExchange(cipherSuite=CipherSuite.{0}, version={1}"\
1141 "".format(CipherSuite.ietfNames[self.cipherSuite], self.version)
1142
1143 if self.srp_N != 0:
1144 ret += ", srp_N={0}, srp_g={1}, srp_s={2!r}, srp_B={3}".format(
1145 self.srp_N, self.srp_g, self.srp_s, self.srp_B)
1146 if self.dh_p != 0:
1147 ret += ", dh_p={0}, dh_g={1}, dh_Ys={2}".format(
1148 self.dh_p, self.dh_g, self.dh_Ys)
1149 if self.signAlg != 0:
1150 ret += ", hashAlg={0}, signAlg={1}".format(
1151 self.hashAlg, self.signAlg)
1152 if self.signature != bytearray(0):
1153 ret += ", signature={0!r}".format(self.signature)
1154 ret += ")"
1155
1156 return ret
1157
1158 - def createSRP(self, srp_N, srp_g, srp_s, srp_B):
1159 """Set SRP protocol parameters."""
1160 self.srp_N = srp_N
1161 self.srp_g = srp_g
1162 self.srp_s = srp_s
1163 self.srp_B = srp_B
1164 return self
1165
1166 - def createDH(self, dh_p, dh_g, dh_Ys):
1167 """Set FFDH protocol parameters."""
1168 self.dh_p = dh_p
1169 self.dh_g = dh_g
1170 self.dh_Ys = dh_Ys
1171 return self
1172
1173 - def createECDH(self, curve_type, named_curve=None, point=None):
1174 """Set ECDH protocol parameters."""
1175 self.curve_type = curve_type
1176 self.named_curve = named_curve
1177 self.ecdh_Ys = point
1178
1179 - def parse(self, parser):
1213
1215 """
1216 Serialise the key exchange parameters.
1217
1218 @rtype: bytearray
1219 """
1220 writer = Writer()
1221 if self.cipherSuite in CipherSuite.srpAllSuites:
1222 writer.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
1223 writer.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
1224 writer.addVarSeq(self.srp_s, 1, 1)
1225 writer.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
1226 elif self.cipherSuite in CipherSuite.dhAllSuites:
1227 writer.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
1228 writer.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
1229 writer.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
1230 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1231 writer.add(self.curve_type, 1)
1232 assert self.curve_type == 3
1233 writer.add(self.named_curve, 2)
1234 writer.addVarSeq(self.ecdh_Ys, 1, 1)
1235 else:
1236 assert(False)
1237 return writer.bytes
1238
1240 """
1241 Serialise complete message.
1242
1243 @rtype: bytearray
1244 """
1245 writer = Writer()
1246 writer.bytes += self.writeParams()
1247 if self.cipherSuite in CipherSuite.certAllSuites:
1248 if self.version >= (3, 3):
1249 assert self.hashAlg != 0 and self.signAlg != 0
1250 writer.add(self.hashAlg, 1)
1251 writer.add(self.signAlg, 1)
1252 writer.addVarSeq(self.signature, 1, 2)
1253 return self.postWrite(writer)
1254
1255 - def hash(self, clientRandom, serverRandom):
1256 """
1257 Calculate hash of parameters to sign.
1258
1259 @rtype: bytearray
1260 """
1261 bytesToHash = clientRandom + serverRandom + self.writeParams()
1262 if self.version >= (3, 3):
1263 hashAlg = HashAlgorithm.toRepr(self.hashAlg)
1264 if hashAlg is None:
1265 raise AssertionError("Unknown hash algorithm: {0}".
1266 format(self.hashAlg))
1267 return secureHash(bytesToHash, hashAlg)
1268 return MD5(bytesToHash) + SHA1(bytesToHash)
1269
1274
1277
1282
1286
1288 """Human readable representation of object."""
1289 return "ServerHelloDone()"
1290
1293 """
1294 Handling of TLS Handshake protocol ClientKeyExchange message.
1295
1296 @type cipherSuite: int
1297 @ivar cipherSuite: the cipher suite id used for the connection
1298 @type version: tuple(int, int)
1299 @ivar version: TLS protocol version used for the connection
1300 @type srp_A: int
1301 @ivar srp_A: SRP protocol client answer value
1302 @type dh_Yc: int
1303 @ivar dh_Yc: client Finite Field Diffie-Hellman protocol key share
1304 @type ecdh_Yc: bytearray
1305 @ivar ecdh_Yc: encoded curve coordinates
1306 @type encryptedPreMasterSecret: bytearray
1307 @ivar encryptedPreMasterSecret: client selected PremMaster secret encrypted
1308 with server public key (from certificate)
1309 """
1310
1311 - def __init__(self, cipherSuite, version=None):
1312 """
1313 Initialise ClientKeyExchange for reading or writing.
1314
1315 @type cipherSuite: int
1316 @param cipherSuite: id of the ciphersuite selected by server
1317 @type version: tuple(int, int)
1318 @param version: protocol version selected by server
1319 """
1320 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange)
1321 self.cipherSuite = cipherSuite
1322 self.version = version
1323 self.srp_A = 0
1324 self.dh_Yc = 0
1325 self.ecdh_Yc = bytearray(0)
1326 self.encryptedPreMasterSecret = bytearray(0)
1327
1329 """
1330 Set the SRP client answer.
1331
1332 returns self
1333
1334 @type srp_A: int
1335 @param srp_A: client SRP answer
1336 @rtype: L{ClientKeyExchange}
1337 """
1338 self.srp_A = srp_A
1339 return self
1340
1341 - def createRSA(self, encryptedPreMasterSecret):
1342 """
1343 Set the encrypted PreMaster Secret.
1344
1345 returns self
1346
1347 @type encryptedPreMasterSecret: bytearray
1348 @rtype: L{ClientKeyExchange}
1349 """
1350 self.encryptedPreMasterSecret = encryptedPreMasterSecret
1351 return self
1352
1354 """
1355 Set the client FFDH key share.
1356
1357 returns self
1358
1359 @type dh_Yc: int
1360 @rtype: L{ClientKeyExchange}
1361 """
1362 self.dh_Yc = dh_Yc
1363 return self
1364
1366 """
1367 Set the client ECDH key share.
1368
1369 returns self
1370
1371 @type ecdh_Yc: bytearray
1372 @rtype: L{ClientKeyExchange}
1373 """
1374 self.ecdh_Yc = ecdh_Yc
1375 return self
1376
1377 - def parse(self, parser):
1405
1407 """
1408 Serialise the object.
1409
1410 @rtype: bytearray
1411 """
1412 w = Writer()
1413 if self.cipherSuite in CipherSuite.srpAllSuites:
1414 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2)
1415 elif self.cipherSuite in CipherSuite.certSuites:
1416 if self.version in ((3, 1), (3, 2), (3, 3)):
1417 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2)
1418 elif self.version == (3, 0):
1419 w.addFixSeq(self.encryptedPreMasterSecret, 1)
1420 else:
1421 raise AssertionError()
1422 elif self.cipherSuite in CipherSuite.dhAllSuites:
1423 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2)
1424 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1425 w.addVarSeq(self.ecdh_Yc, 1, 1)
1426 else:
1427 raise AssertionError()
1428 return self.postWrite(w)
1429
1432 """
1433 Handling of SSLv2 CLIENT-MASTER-KEY message.
1434
1435 @type cipher: int
1436 @ivar cipher: negotiated cipher
1437
1438 @type clear_key: bytearray
1439 @ivar clear_key: the part of master secret key that is sent in clear for
1440 export cipher suites
1441
1442 @type encrypted_key: bytearray
1443 @ivar encrypted_key: (part of) master secret encrypted using server key
1444
1445 @type key_argument: bytearray
1446 @ivar key_argument: additional key argument for block ciphers
1447 """
1448
1456
1457 - def create(self, cipher, clear_key, encrypted_key, key_argument):
1458 """Set values of the CLIENT-MASTER-KEY object."""
1459 self.cipher = cipher
1460 self.clear_key = clear_key
1461 self.encrypted_key = encrypted_key
1462 self.key_argument = key_argument
1463 return self
1464
1466 """Serialise the object to on the wire data."""
1467 writer = Writer()
1468 writer.add(self.handshakeType, 1)
1469 writer.add(self.cipher, 3)
1470 writer.add(len(self.clear_key), 2)
1471 writer.add(len(self.encrypted_key), 2)
1472 writer.add(len(self.key_argument), 2)
1473 writer.bytes += self.clear_key
1474 writer.bytes += self.encrypted_key
1475 writer.bytes += self.key_argument
1476 return writer.bytes
1477
1478 - def parse(self, parser):
1479 """Deserialise object from on the wire data."""
1480 self.cipher = parser.get(3)
1481 clear_key_length = parser.get(2)
1482 encrypted_key_length = parser.get(2)
1483 key_argument_length = parser.get(2)
1484 parser.setLengthCheck(clear_key_length +
1485 encrypted_key_length +
1486 key_argument_length)
1487 self.clear_key = parser.getFixBytes(clear_key_length)
1488 self.encrypted_key = parser.getFixBytes(encrypted_key_length)
1489 self.key_argument = parser.getFixBytes(key_argument_length)
1490 parser.stopLengthCheck()
1491 return self
1492
1495 """Serializer for TLS handshake protocol Certificate Verify message."""
1496
1507
1508 - def create(self, signature, signatureAlgorithm=None):
1509 """
1510 Provide data for serialisation of message.
1511
1512 @param signature: signature carried in the message
1513 @param signatureAlgorithm: signature algorithm used to make the
1514 signature (TLSv1.2 only)
1515 """
1516 self.signatureAlgorithm = signatureAlgorithm
1517 self.signature = signature
1518 return self
1519
1520 - def parse(self, parser):
1521 """
1522 Deserialize message from parser.
1523
1524 @param parser: parser with data to read
1525 """
1526 parser.startLengthCheck(3)
1527 if self.version >= (3, 3):
1528 self.signatureAlgorithm = (parser.get(1), parser.get(1))
1529 self.signature = parser.getVarBytes(2)
1530 parser.stopLengthCheck()
1531 return self
1532
1534 """
1535 Serialize the data to bytearray.
1536
1537 @rtype: bytearray
1538 """
1539 writer = Writer()
1540 if self.version >= (3, 3):
1541 writer.add(self.signatureAlgorithm[0], 1)
1542 writer.add(self.signatureAlgorithm[1], 1)
1543 writer.addVarSeq(self.signature, 1, 2)
1544 return self.postWrite(writer)
1545
1551
1553 self.type = 1
1554 return self
1555
1561
1563 w = Writer()
1564 w.add(self.type, 1)
1565 return w.bytes
1566
1572
1573 - def create(self, next_proto):
1574 self.next_proto = next_proto
1575 return self
1576
1583
1584 - def write(self, trial=False):
1585 w = Writer()
1586 w.addVarSeq(self.next_proto, 1, 1)
1587 paddingLen = 32 - ((len(self.next_proto) + 2) % 32)
1588 w.addVarSeq(bytearray(paddingLen), 1, 1)
1589 return self.postWrite(w)
1590
1597
1598 - def create(self, verify_data):
1599 self.verify_data = verify_data
1600 return self
1601
1612
1617
1620 """Handling of the SSL2 FINISHED messages."""
1621
1625
1626 - def create(self, verify_data):
1627 """Set the message payload."""
1628 self.verify_data = verify_data
1629 return self
1630
1631 - def parse(self, parser):
1632 """Deserialise the message from on the wire data."""
1633 self.verify_data = parser.getFixBytes(parser.getRemainingLength())
1634 return self
1635
1637 """Serialise the message to on the wire data."""
1638 writer = Writer()
1639 writer.add(self.handshakeType, 1)
1640 writer.addFixSeq(self.verify_data, 1)
1641
1642 return writer.bytes
1643
1646 """
1647 Handling of SSLv2 CLIENT-FINISHED message.
1648
1649 @type verify_data: bytearray
1650 @ivar verify_data: payload of the message, should be the CONNECTION-ID
1651 """
1652
1655
1658 """
1659 Handling of SSLv2 SERVER-FINISHED message.
1660
1661 @type verify_data: bytearray
1662 @ivar verify_data: payload of the message, should be SESSION-ID
1663 """
1664
1667
1673
1675 self.bytes = bytes
1676 return self
1677
1679 newMsg = ApplicationData().create(self.bytes[:1])
1680 self.bytes = self.bytes[1:]
1681 return newMsg
1682
1684 self.bytes = p.bytes
1685 return self
1686
1689