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 *
24
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
35
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, self.length)
79
81 return "RecordHeader3(type={0}, version=({1[0]}.{1[1]}), length={2})".\
82 format(self.type, self.version, self.length)
83
85 """
86 SSLv2 record header
87
88 @type padding: int
89 @ivar padding: number of bytes added at end of message to make it multiple
90 of block cipher size
91 @type securityEscape: boolean
92 @ivar securityEscape: whether the record contains a security escape message
93 """
94
96 """Define a SSLv2 style class"""
97 super(RecordHeader2, self).__init__(ssl2=True)
98 self.padding = 0
99 self.securityEscape = False
100
102 """Deserialise object from Parser"""
103 firstByte = parser.get(1)
104 secondByte = parser.get(1)
105 if firstByte & 0x80:
106 self.length = ((firstByte & 0x7f) << 8) | secondByte
107 else:
108 self.length = ((firstByte & 0x3f) << 8) | secondByte
109 self.securityEscape = firstByte & 0x40 != 0
110 self.padding = parser.get(1)
111
112 self.type = ContentType.handshake
113 self.version = (2, 0)
114 return self
115
117 """Set object's values"""
118 self.length = length
119 self.padding = padding
120 self.securityEscape = securityEscape
121 return self
122
124 """Serialise object to bytearray"""
125 writer = Writer()
126
127 if not (self.padding or self.securityEscape):
128 shortHeader = True
129 else:
130 shortHeader = False
131
132 if ((shortHeader and self.length >= 0x8000) or
133 (not shortHeader and self.length >= 0x4000)):
134 raise ValueError("length too large")
135
136 firstByte = 0
137 if shortHeader:
138 firstByte |= 0x80
139 if self.securityEscape:
140 firstByte |= 0x40
141 firstByte |= self.length >> 8
142 secondByte = self.length & 0xff
143
144 writer.add(firstByte, 1)
145 writer.add(secondByte, 1)
146 if not shortHeader:
147 writer.add(self.padding, 1)
148
149 return writer.bytes
150
152
153 """Generic TLS message"""
154
156 """
157 Initialize object with specified contentType and data
158
159 @type contentType: int
160 @param contentType: TLS record layer content type of associated data
161 @type data: bytearray
162 @param data: data
163 """
164 self.contentType = contentType
165 self.data = data
166
168 """Return serialised object data"""
169 return self.data
170
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 @property
197 matching = [x[0] for x in AlertLevel.__dict__.items()
198 if x[1] == self.level]
199 if len(matching) == 0:
200 return "unknown({0})".format(self.level)
201 else:
202 return str(matching[0])
203
204 @property
206 matching = [x[0] for x in AlertDescription.__dict__.items()
207 if x[1] == self.description]
208 if len(matching) == 0:
209 return "unknown({0})".format(self.description)
210 else:
211 return str(matching[0])
212
216
218 return "Alert(level={0}, description={1})".format(self.level,
219 self.description)
220
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
233 """
234 Class for handling the ClientHello TLS message, supports both the SSLv2
235 and SSLv3 style messages.
236
237 @type certificate_types: list
238 @ivar certificate_types: list of supported certificate types (deprecated)
239
240 @type srp_username: bytearray
241 @ivar srp_username: name of the user in SRP extension (deprecated)
242
243 @type supports_npn: boolean
244 @ivar supports_npn: NPN extension presence (deprecated)
245
246 @type tack: boolean
247 @ivar tack: TACK extension presence (deprecated)
248
249 @type server_name: bytearray
250 @ivar server_name: first host_name (type 0) present in SNI extension
251 (deprecated)
252
253 @type extensions: list of L{TLSExtension}
254 @ivar extensions: list of TLS extensions parsed from wire or to send, see
255 L{TLSExtension} and child classes for exact examples
256 """
266
268 """
269 Return human readable representation of Client Hello
270
271 @rtype: str
272 """
273
274 if self.session_id.count(bytearray(b'\x00')) == len(self.session_id)\
275 and len(self.session_id) != 0:
276 session = "bytearray(b'\\x00'*{0})".format(len(self.session_id))
277 else:
278 session = repr(self.session_id)
279 ret = "client_hello,version({0[0]}.{0[1]}),random(...),"\
280 "session ID({1!s}),cipher suites({2!r}),"\
281 "compression methods({3!r})".format(
282 self.client_version, session,
283 self.cipher_suites, self.compression_methods)
284
285 if self.extensions is not None:
286 ret += ",extensions({0!r})".format(self.extensions)
287
288 return ret
289
291 """
292 Return machine readable representation of Client Hello
293
294 @rtype: str
295 """
296 return "ClientHello(ssl2={0}, client_version=({1[0]}.{1[1]}), "\
297 "random={2!r}, session_id={3!r}, cipher_suites={4!r}, "\
298 "compression_methods={5}, extensions={6})".format(\
299 self.ssl2, self.client_version, self.random, self.session_id,
300 self.cipher_suites, self.compression_methods, self.extensions)
301
302 - def getExtension(self, extType):
303 """
304 Returns extension of given type if present, None otherwise
305
306 @rtype: L{tlslite.extensions.TLSExtension}
307 @raise TLSInternalError: when there are multiple extensions of the
308 same type
309 """
310 if self.extensions is None:
311 return None
312
313 exts = [ext for ext in self.extensions if ext.extType == extType]
314 if len(exts) > 1:
315 raise TLSInternalError(
316 "Multiple extensions of the same type present")
317 elif len(exts) == 1:
318 return exts[0]
319 else:
320 return None
321
323 """
324 Adds extension to internal list of extensions
325
326 @type ext: TLSExtension
327 @param ext: extension object to add to list
328 """
329 if self.extensions is None:
330 self.extensions = []
331
332 self.extensions.append(ext)
333
334 @property
348
349 @certificate_types.setter
351 """
352 Sets the list of supported types to list given in L{val} if the
353 cert_type extension is present. Creates the extension and places it
354 last in the list otherwise.
355
356 @type val: list
357 @param val: list of supported certificate types by client encoded as
358 single byte integers
359 """
360 cert_type = self.getExtension(ExtensionType.cert_type)
361
362 if cert_type is None:
363 ext = ClientCertTypeExtension().create(val)
364 self.addExtension(ext)
365 else:
366 cert_type.certTypes = val
367
368 @property
370 """
371 Returns username for the SRP.
372
373 @deprecated: use extensions field to get the extension for inspection
374 """
375 srp_ext = self.getExtension(ExtensionType.srp)
376
377 if srp_ext is None:
378 return None
379 else:
380 return srp_ext.identity
381
382 @srp_username.setter
397
398 @property
400 """
401 Returns whatever the client supports TACK
402
403 @rtype: boolean
404 @deprecated: use extensions field to get the extension for inspection
405 """
406 tack_ext = self.getExtension(ExtensionType.tack)
407
408 if tack_ext is None:
409 return False
410 else:
411 return True
412
413 @tack.setter
414 - def tack(self, present):
435
436 @property
438 """
439 Returns whatever client supports NPN extension
440
441 @rtype: boolean
442 @deprecated: use extensions field to get the extension for inspection
443 """
444 npn_ext = self.getExtension(ExtensionType.supports_npn)
445
446 if npn_ext is None:
447 return False
448 else:
449 return True
450
451 @supports_npn.setter
475
476 @property
478 """
479 Returns first host_name present in SNI extension
480
481 @rtype: bytearray
482 @deprecated: use extensions field to get the extension for inspection
483 """
484 sni_ext = self.getExtension(ExtensionType.server_name)
485 if sni_ext is None:
486 return bytearray(0)
487 else:
488 if len(sni_ext.hostNames) > 0:
489 return sni_ext.hostNames[0]
490 else:
491 return bytearray(0)
492
493 @server_name.setter
509
510 - def create(self, version, random, session_id, cipher_suites,
511 certificate_types=None, srpUsername=None,
512 tack=False, supports_npn=False, serverName=None,
513 extensions=None):
514 """
515 Create a ClientHello message for sending.
516
517 @type version: tuple
518 @param version: the highest supported TLS version encoded as two int
519 tuple
520
521 @type random: bytearray
522 @param random: client provided random value, in old versions of TLS
523 (before 1.2) the first 32 bits should include system time, also
524 used as the "challenge" field in SSLv2
525
526 @type session_id: bytearray
527 @param session_id: ID of session, set when doing session resumption
528
529 @type cipher_suites: list
530 @param cipher_suites: list of ciphersuites advertised as supported
531
532 @type certificate_types: list
533 @param certificate_types: list of supported certificate types, uses
534 TLS extension for signalling, as such requires TLS1.0 to work
535
536 @type srpUsername: bytearray
537 @param srpUsername: utf-8 encoded username for SRP, TLS extension
538
539 @type tack: boolean
540 @param tack: whatever to advertise support for TACK, TLS extension
541
542 @type supports_npn: boolean
543 @param supports_npn: whatever to advertise support for NPN, TLS
544 extension
545
546 @type serverName: bytearray
547 @param serverName: the hostname to request in server name indication
548 extension, TLS extension. Note that SNI allows to set multiple
549 hostnames and values that are not hostnames, use L{SNIExtension}
550 together with L{extensions} to use it.
551
552 @type extensions: list of L{TLSExtension}
553 @param extensions: list of extensions to advertise
554 """
555 self.client_version = version
556 self.random = random
557 self.session_id = session_id
558 self.cipher_suites = cipher_suites
559 self.compression_methods = [0]
560 if not extensions is None:
561 self.extensions = extensions
562 if not certificate_types is None:
563 self.certificate_types = certificate_types
564 if not srpUsername is None:
565 self.srp_username = bytearray(srpUsername, "utf-8")
566 self.tack = tack
567 self.supports_npn = supports_npn
568 if not serverName is None:
569 self.server_name = bytearray(serverName, "utf-8")
570 return self
571
605
607 """Serialise SSLv2 object to on the wire data"""
608 writer = Writer()
609 writer.add(self.handshakeType, 1)
610 writer.add(self.client_version[0], 1)
611 writer.add(self.client_version[1], 1)
612
613 ciphersWriter = Writer()
614 ciphersWriter.addFixSeq(self.cipher_suites, 3)
615
616 writer.add(len(ciphersWriter.bytes), 2)
617 writer.add(len(self.session_id), 2)
618 writer.add(len(self.random), 2)
619
620 writer.bytes += ciphersWriter.bytes
621 writer.bytes += self.session_id
622 writer.bytes += self.random
623
624
625 return writer.bytes
626
628 """Serialise SSLv3 or TLS object to on the wire data"""
629 w = Writer()
630 w.add(self.client_version[0], 1)
631 w.add(self.client_version[1], 1)
632 w.addFixSeq(self.random, 1)
633 w.addVarSeq(self.session_id, 1, 1)
634 w.addVarSeq(self.cipher_suites, 2, 2)
635 w.addVarSeq(self.compression_methods, 1, 1)
636
637 if not self.extensions is None:
638 w2 = Writer()
639 for ext in self.extensions:
640 w2.bytes += ext.write()
641
642 w.add(len(w2.bytes), 2)
643 w.bytes += w2.bytes
644 return self.postWrite(w)
645
647 """Serialise object to on the wire data"""
648 if self.ssl2:
649 return self._writeSSL2()
650 else:
651 return self._write()
652
654 """server_hello message
655
656 @type server_version: tuple
657 @ivar server_version: protocol version encoded as two int tuple
658
659 @type random: bytearray
660 @ivar random: server random value
661
662 @type session_id: bytearray
663 @ivar session_id: session identifier for resumption
664
665 @type cipher_suite: int
666 @ivar cipher_suite: server selected cipher_suite
667
668 @type compression_method: int
669 @ivar compression_method: server selected compression method
670
671 @type next_protos: list of bytearray
672 @ivar next_protos: list of advertised protocols in NPN extension
673
674 @type next_protos_advertised: list of bytearray
675 @ivar next_protos_advertised: list of protocols advertised in NPN extension
676
677 @type certificate_type: int
678 @ivar certificate_type: certificate type selected by server
679
680 @type extensions: list
681 @ivar extensions: list of TLS extensions present in server_hello message,
682 see L{TLSExtension} and child classes for exact examples
683 """
685 """Initialise ServerHello object"""
686
687 HandshakeMsg.__init__(self, HandshakeType.server_hello)
688 self.server_version = (0,0)
689 self.random = bytearray(32)
690 self.session_id = bytearray(0)
691 self.cipher_suite = 0
692 self.compression_method = 0
693 self._tack_ext = None
694 self.extensions = None
695
697 base = "server_hello,length({0}),version({1[0]}.{1[1]}),random(...),"\
698 "session ID({2!r}),cipher({3:#x}),compression method({4})"\
699 .format(len(self.write())-4, self.server_version,
700 self.session_id, self.cipher_suite,
701 self.compression_method)
702
703 if self.extensions is None:
704 return base
705
706 ret = ",extensions["
707 ret += ",".join(repr(x) for x in self.extensions)
708 ret += "]"
709 return base + ret
710
712 return "ServerHello(server_version=({0[0]}, {0[1]}), random={1!r}, "\
713 "session_id={2!r}, cipher_suite={3}, compression_method={4}, "\
714 "_tack_ext={5}, extensions={6!r})".format(\
715 self.server_version, self.random, self.session_id,
716 self.cipher_suite, self.compression_method, self._tack_ext,
717 self.extensions)
718
719 - def getExtension(self, extType):
720 """Return extension of a given type, None if extension of given type
721 is not present
722
723 @rtype: L{TLSExtension}
724 @raise TLSInternalError: multiple extensions of the same type present
725 """
726 if self.extensions is None:
727 return None
728
729 exts = [ext for ext in self.extensions if ext.extType == extType]
730 if len(exts) > 1:
731 raise TLSInternalError(
732 "Multiple extensions of the same type present")
733 elif len(exts) == 1:
734 return exts[0]
735 else:
736 return None
737
739 """
740 Add extension to internal list of extensions
741
742 @type ext: TLSExtension
743 @param ext: extension to add to list
744 """
745 if self.extensions is None:
746 self.extensions = []
747 self.extensions.append(ext)
748
749 @property
751 """ Returns the TACK extension
752 """
753 if self._tack_ext is None:
754 ext = self.getExtension(ExtensionType.tack)
755 if ext is None or not tackpyLoaded:
756 return None
757 else:
758 self._tack_ext = TackExtension(ext.extData)
759 return self._tack_ext
760
761 @tackExt.setter
763 """ Set the TACK extension
764 """
765 self._tack_ext = val
766
767 if not val is None:
768 if self.extensions is None:
769 self.extensions = []
770
771 @property
783
784 @certificate_type.setter
801
802 @property
804 """Returns the advertised protocols in NPN extension
805
806 @rtype: list of bytearrays
807 """
808 npn_ext = self.getExtension(ExtensionType.supports_npn)
809
810 if npn_ext is None:
811 return None
812 else:
813 return npn_ext.protocols
814
815 @next_protos.setter
817 """Sets the advertised protocols in NPN extension
818
819 @type val: list
820 @param val: list of protocols to advertise as UTF-8 encoded names
821 """
822 if val is None:
823 return
824 else:
825
826 val = [ bytearray(x) for x in val ]
827
828 npn_ext = self.getExtension(ExtensionType.supports_npn)
829
830 if npn_ext is None:
831 ext = NPNExtension().create(val)
832 self.addExtension(ext)
833 else:
834 npn_ext.protocols = val
835
836 @property
838 """Returns the advertised protocols in NPN extension
839
840 @rtype: list of bytearrays
841 """
842 return self.next_protos
843
844 @next_protos_advertised.setter
846 """Sets the advertised protocols in NPN extension
847
848 @type val: list
849 @param val: list of protocols to advertise as UTF-8 encoded names
850 """
851 self.next_protos = val
852
853 - def create(self, version, random, session_id, cipher_suite,
854 certificate_type=None, tackExt=None, next_protos_advertised=None,
855 extensions=None):
868
885
887 w = Writer()
888 w.add(self.server_version[0], 1)
889 w.add(self.server_version[1], 1)
890 w.addFixSeq(self.random, 1)
891 w.addVarSeq(self.session_id, 1, 1)
892 w.add(self.cipher_suite, 2)
893 w.add(self.compression_method, 1)
894
895 if not self.extensions is None:
896 w2 = Writer()
897 for ext in self.extensions:
898 w2.bytes += ext.write()
899
900 if self.tackExt:
901 b = self.tackExt.serialize()
902 w2.add(ExtensionType.tack, 2)
903 w2.add(len(b), 2)
904 w2.bytes += b
905
906 w.add(len(w2.bytes), 2)
907 w.bytes += w2.bytes
908 return self.postWrite(w)
909
911 """
912 SERVER-HELLO message from SSLv2
913
914 @type session_id_hit: int
915 @ivar session_id_hit: non zero if the client provided session ID was
916 matched in server's session cache
917
918 @type certificate_type: int
919 @ivar certificate_type: type of certificate sent
920
921 @type server_version: tuple of ints
922 @ivar server_version: protocol version selected by server
923
924 @type certificate: bytearray
925 @ivar certificate: certificate sent by server
926
927 @type ciphers: array of int
928 @ivar ciphers: list of ciphers supported by server
929
930 @type session_id: bytearray
931 @ivar session_id: idendifier of negotiated session
932 """
933
942
943 - def create(self, session_id_hit, certificate_type, server_version,
944 certificate, ciphers, session_id):
945 """Initialize fields of the SERVER-HELLO message"""
946 self.session_id_hit = session_id_hit
947 self.certificate_type = certificate_type
948 self.server_version = server_version
949 self.certificate = certificate
950 self.ciphers = ciphers
951 self.session_id = session_id
952 return self
953
955 """Serialise object to on the wire data"""
956 writer = Writer()
957 writer.add(self.handshakeType, 1)
958 writer.add(self.session_id_hit, 1)
959 writer.add(self.certificate_type, 1)
960 if len(self.server_version) != 2:
961 raise ValueError("server version must be a 2-element tuple")
962 writer.addFixSeq(self.server_version, 1)
963 writer.add(len(self.certificate), 2)
964
965 ciphersWriter = Writer()
966 ciphersWriter.addFixSeq(self.ciphers, 3)
967
968 writer.add(len(ciphersWriter.bytes), 2)
969 writer.add(len(self.session_id), 2)
970
971 writer.bytes += self.certificate
972 writer.bytes += ciphersWriter.bytes
973 writer.bytes += self.session_id
974
975
976 return writer.bytes
977
978 - def parse(self, parser):
979 """Deserialise object from on the wire data"""
980 self.session_id_hit = parser.get(1)
981 self.certificate_type = parser.get(1)
982 self.server_version = (parser.get(1), parser.get(1))
983 certificateLength = parser.get(2)
984 ciphersLength = parser.get(2)
985 sessionIDLength = parser.get(2)
986 parser.setLengthCheck(certificateLength +
987 ciphersLength +
988 sessionIDLength)
989 self.certificate = parser.getFixBytes(certificateLength)
990 self.ciphers = parser.getFixList(3, ciphersLength // 3)
991 self.session_id = parser.getFixBytes(sessionIDLength)
992 parser.stopLengthCheck()
993 return self
994
1000
1001 - def create(self, certChain):
1002 self.certChain = certChain
1003 return self
1004
1024
1026 w = Writer()
1027 if self.certificateType == CertificateType.x509:
1028 chainLength = 0
1029 if self.certChain:
1030 certificate_list = self.certChain.x509List
1031 else:
1032 certificate_list = []
1033
1034 for cert in certificate_list:
1035 bytes = cert.writeBytes()
1036 chainLength += len(bytes)+3
1037
1038 w.add(chainLength, 3)
1039 for cert in certificate_list:
1040 bytes = cert.writeBytes()
1041 w.addVarSeq(bytes, 1, 3)
1042 else:
1043 raise AssertionError()
1044 return self.postWrite(w)
1045
1053
1054 - def create(self, certificate_types, certificate_authorities, sig_algs=()):
1055 self.certificate_types = certificate_types
1056 self.certificate_authorities = certificate_authorities
1057 self.supported_signature_algs = sig_algs
1058 return self
1059
1074
1076 w = Writer()
1077 w.addVarSeq(self.certificate_types, 1, 1)
1078 if self.version >= (3,3):
1079 w.addVarTupleSeq(self.supported_signature_algs, 1, 2)
1080 caLength = 0
1081
1082 for ca_dn in self.certificate_authorities:
1083 caLength += len(ca_dn)+2
1084 w.add(caLength, 2)
1085
1086 for ca_dn in self.certificate_authorities:
1087 w.addVarSeq(ca_dn, 1, 2)
1088 return self.postWrite(w)
1089
1091
1092 """
1093 Handling TLS Handshake protocol Server Key Exchange messages
1094
1095 @type cipherSuite: int
1096 @cvar cipherSuite: id of ciphersuite selected in Server Hello message
1097 @type srp_N: int
1098 @cvar srp_N: SRP protocol prime
1099 @type srp_g: int
1100 @cvar srp_g: SRP protocol generator
1101 @type srp_s: bytearray
1102 @cvar srp_s: SRP protocol salt value
1103 @type srp_B: int
1104 @cvar srp_B: SRP protocol server public value
1105 @type dh_p: int
1106 @cvar dh_p: FFDHE protocol prime
1107 @type dh_g: int
1108 @cvar dh_g: FFDHE protocol generator
1109 @type dh_Ys: int
1110 @cvar dh_Ys: FFDH protocol server key share
1111 @type curve_type: int
1112 @cvar curve_type: Type of curve used (explicit, named, etc.)
1113 @type named_curve: int
1114 @cvar named_curve: TLS ID of named curve
1115 @type ecdh_Ys: bytearray
1116 @cvar ecdh_Ys: ECDH protocol encoded point key share
1117 @type signature: bytearray
1118 @cvar signature: signature performed over the parameters by server
1119 @type hashAlg: int
1120 @cvar hashAlg: id of hash algorithm used for signature
1121 @type signAlg: int
1122 @cvar signAlg: id of signature algorithm used for signature
1123 """
1124
1125 - def __init__(self, cipherSuite, version):
1126 """
1127 Initialise Server Key Exchange for reading or writing
1128
1129 @type cipherSuite: int
1130 @param cipherSuite: id of ciphersuite selected by server
1131 """
1132 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange)
1133 self.cipherSuite = cipherSuite
1134 self.version = version
1135 self.srp_N = 0
1136 self.srp_g = 0
1137 self.srp_s = bytearray(0)
1138 self.srp_B = 0
1139
1140 self.dh_p = 0
1141 self.dh_g = 0
1142 self.dh_Ys = 0
1143
1144 self.curve_type = None
1145 self.named_curve = None
1146 self.ecdh_Ys = bytearray(0)
1147
1148 self.signature = bytearray(0)
1149
1150 self.hashAlg = 0
1151 self.signAlg = 0
1152
1154
1155 ret = "ServerKeyExchange(cipherSuite=CipherSuite.{0}, version={1}"\
1156 "".format(CipherSuite.ietfNames[self.cipherSuite], self.version)
1157
1158 if self.srp_N != 0:
1159 ret += ", srp_N={0}, srp_g={1}, srp_s={2!r}, srp_B={3}".format(\
1160 self.srp_N, self.srp_g, self.srp_s, self.srp_B)
1161 if self.dh_p != 0:
1162 ret += ", dh_p={0}, dh_g={1}, dh_Ys={2}".format(\
1163 self.dh_p, self.dh_g, self.dh_Ys)
1164 if self.signAlg != 0:
1165 ret += ", hashAlg={0}, signAlg={1}".format(\
1166 self.hashAlg, self.signAlg)
1167 if self.signature != bytearray(0):
1168 ret += ", signature={0!r}".format(self.signature)
1169 ret += ")"
1170
1171 return ret
1172
1173
1174 - def createSRP(self, srp_N, srp_g, srp_s, srp_B):
1175 """Set SRP protocol parameters"""
1176 self.srp_N = srp_N
1177 self.srp_g = srp_g
1178 self.srp_s = srp_s
1179 self.srp_B = srp_B
1180 return self
1181
1182 - def createDH(self, dh_p, dh_g, dh_Ys):
1183 """Set FFDH protocol parameters"""
1184 self.dh_p = dh_p
1185 self.dh_g = dh_g
1186 self.dh_Ys = dh_Ys
1187 return self
1188
1189 - def createECDH(self, curve_type, named_curve=None, point=None):
1190 """Set ECDH protocol parameters"""
1191 self.curve_type = curve_type
1192 self.named_curve = named_curve
1193 self.ecdh_Ys = point
1194
1195 - def parse(self, parser):
1228
1230 """Serialise the key exchange parameters
1231
1232 @rtype: bytearray
1233 """
1234 writer = Writer()
1235 if self.cipherSuite in CipherSuite.srpAllSuites:
1236 writer.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
1237 writer.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
1238 writer.addVarSeq(self.srp_s, 1, 1)
1239 writer.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
1240 elif self.cipherSuite in CipherSuite.dhAllSuites:
1241 writer.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
1242 writer.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
1243 writer.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
1244 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1245 writer.add(self.curve_type, 1)
1246 assert self.curve_type == 3
1247 writer.add(self.named_curve, 2)
1248 writer.addVarSeq(self.ecdh_Ys, 1, 1)
1249 else:
1250 assert(False)
1251 return writer.bytes
1252
1254 """
1255 Serialise complete message
1256
1257 @rtype: bytearray
1258 """
1259 writer = Writer()
1260 writer.bytes += self.writeParams()
1261 if self.cipherSuite in CipherSuite.certAllSuites:
1262 if self.version >= (3, 3):
1263 assert self.hashAlg != 0 and self.signAlg != 0
1264 writer.add(self.hashAlg, 1)
1265 writer.add(self.signAlg, 1)
1266 writer.addVarSeq(self.signature, 1, 2)
1267 return self.postWrite(writer)
1268
1269 - def hash(self, clientRandom, serverRandom):
1270 """
1271 Calculate hash of parameters to sign
1272
1273 @rtype: bytearray
1274 """
1275 bytesToHash = clientRandom + serverRandom + self.writeParams()
1276 if self.version >= (3, 3):
1277 hashAlg = HashAlgorithm.toRepr(self.hashAlg)
1278 if hashAlg is None:
1279 raise AssertionError("Unknown hash algorithm: {0}".\
1280 format(self.hashAlg))
1281 return secureHash(bytesToHash, hashAlg)
1282 return MD5(bytesToHash) + SHA1(bytesToHash)
1283
1287
1290
1295
1299
1301 """Human readable representation of object"""
1302 return "ServerHelloDone()"
1303
1305
1306 """
1307 Handling of TLS Handshake protocol ClientKeyExchange message
1308
1309 @type cipherSuite: int
1310 @ivar cipherSuite: the cipher suite id used for the connection
1311 @type version: tuple(int, int)
1312 @ivar version: TLS protocol version used for the connection
1313 @type srp_A: int
1314 @ivar srp_A: SRP protocol client answer value
1315 @type dh_Yc: int
1316 @ivar dh_Yc: client Finite Field Diffie-Hellman protocol key share
1317 @type ecdh_Yc: bytearray
1318 @ivar ecdh_Yc: encoded curve coordinates
1319 @type encryptedPreMasterSecret: bytearray
1320 @ivar encryptedPreMasterSecret: client selected PremMaster secret encrypted
1321 with server public key (from certificate)
1322 """
1323
1324 - def __init__(self, cipherSuite, version=None):
1325 """
1326 Initialise ClientKeyExchange for reading or writing
1327
1328 @type cipherSuite: int
1329 @param cipherSuite: id of the ciphersuite selected by server
1330 @type version: tuple(int, int)
1331 @param version: protocol version selected by server
1332 """
1333 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange)
1334 self.cipherSuite = cipherSuite
1335 self.version = version
1336 self.srp_A = 0
1337 self.dh_Yc = 0
1338 self.ecdh_Yc = bytearray(0)
1339 self.encryptedPreMasterSecret = bytearray(0)
1340
1342 """
1343 Set the SRP client answer
1344
1345 returns self
1346
1347 @type srp_A: int
1348 @param srp_A: client SRP answer
1349 @rtype: L{ClientKeyExchange}
1350 """
1351 self.srp_A = srp_A
1352 return self
1353
1354 - def createRSA(self, encryptedPreMasterSecret):
1355 """
1356 Set the encrypted PreMaster Secret
1357
1358 returns self
1359
1360 @type encryptedPreMasterSecret: bytearray
1361 @rtype: L{ClientKeyExchange}
1362 """
1363 self.encryptedPreMasterSecret = encryptedPreMasterSecret
1364 return self
1365
1367 """
1368 Set the client FFDH key share
1369
1370 returns self
1371
1372 @type dh_Yc: int
1373 @rtype: L{ClientKeyExchange}
1374 """
1375 self.dh_Yc = dh_Yc
1376 return self
1377
1379 """
1380 Set the client ECDH key share
1381
1382 returns self
1383
1384 @type ecdh_Yc: bytearray
1385 @rtype: L{ClientKeyExchange}
1386 """
1387 self.ecdh_Yc = ecdh_Yc
1388 return self
1389
1390 - def parse(self, parser):
1418
1420 """
1421 Serialise the object
1422
1423 @rtype: bytearray
1424 """
1425 w = Writer()
1426 if self.cipherSuite in CipherSuite.srpAllSuites:
1427 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2)
1428 elif self.cipherSuite in CipherSuite.certSuites:
1429 if self.version in ((3,1), (3,2), (3,3)):
1430 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2)
1431 elif self.version == (3,0):
1432 w.addFixSeq(self.encryptedPreMasterSecret, 1)
1433 else:
1434 raise AssertionError()
1435 elif self.cipherSuite in CipherSuite.dhAllSuites:
1436 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2)
1437 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1438 w.addVarSeq(self.ecdh_Yc, 1, 1)
1439 else:
1440 raise AssertionError()
1441 return self.postWrite(w)
1442
1444 """
1445 Handling of SSLv2 CLIENT-MASTER-KEY message
1446
1447 @type cipher: int
1448 @ivar cipher: negotiated cipher
1449
1450 @type clear_key: bytearray
1451 @ivar clear_key: the part of master secret key that is sent in clear for
1452 export cipher suites
1453
1454 @type encrypted_key: bytearray
1455 @ivar encrypted_key: (part of) master secret encrypted using server key
1456
1457 @type key_argument: bytearray
1458 @ivar key_argument: additional key argument for block ciphers
1459 """
1460
1468
1469 - def create(self, cipher, clear_key, encrypted_key, key_argument):
1470 """Set values of the CLIENT-MASTER-KEY object"""
1471 self.cipher = cipher
1472 self.clear_key = clear_key
1473 self.encrypted_key = encrypted_key
1474 self.key_argument = key_argument
1475 return self
1476
1478 """Serialise the object to on the wire data"""
1479 writer = Writer()
1480 writer.add(self.handshakeType, 1)
1481 writer.add(self.cipher, 3)
1482 writer.add(len(self.clear_key), 2)
1483 writer.add(len(self.encrypted_key), 2)
1484 writer.add(len(self.key_argument), 2)
1485 writer.bytes += self.clear_key
1486 writer.bytes += self.encrypted_key
1487 writer.bytes += self.key_argument
1488 return writer.bytes
1489
1490 - def parse(self, parser):
1491 """Deserialise object from on the wire data"""
1492 self.cipher = parser.get(3)
1493 clear_key_length = parser.get(2)
1494 encrypted_key_length = parser.get(2)
1495 key_argument_length = parser.get(2)
1496 parser.setLengthCheck(clear_key_length +
1497 encrypted_key_length +
1498 key_argument_length)
1499 self.clear_key = parser.getFixBytes(clear_key_length)
1500 self.encrypted_key = parser.getFixBytes(encrypted_key_length)
1501 self.key_argument = parser.getFixBytes(key_argument_length)
1502 parser.stopLengthCheck()
1503 return self
1504
1506
1507 """Serializer for TLS handshake protocol Certificate Verify message"""
1508
1518
1519 - def create(self, signature, signatureAlgorithm=None):
1520 """
1521 Provide data for serialisation of message
1522
1523 @param signature: signature carried in the message
1524 @param signatureAlgorithm: signature algorithm used to make the
1525 signature (TLSv1.2 only)
1526 """
1527 self.signatureAlgorithm = signatureAlgorithm
1528 self.signature = signature
1529 return self
1530
1531 - def parse(self, parser):
1532 """
1533 Deserialize message from parser
1534
1535 @param parser: parser with data to read
1536 """
1537 parser.startLengthCheck(3)
1538 if self.version >= (3, 3):
1539 self.signatureAlgorithm = (parser.get(1), parser.get(1))
1540 self.signature = parser.getVarBytes(2)
1541 parser.stopLengthCheck()
1542 return self
1543
1545 """
1546 Serialize the data to bytearray
1547
1548 @rtype: bytearray
1549 """
1550 writer = Writer()
1551 if self.version >= (3, 3):
1552 writer.add(self.signatureAlgorithm[0], 1)
1553 writer.add(self.signatureAlgorithm[1], 1)
1554 writer.addVarSeq(self.signature, 1, 2)
1555 return self.postWrite(writer)
1556
1561
1563 self.type = 1
1564 return self
1565
1571
1573 w = Writer()
1574 w.add(self.type,1)
1575 return w.bytes
1576
1582
1583 - def create(self, next_proto):
1584 self.next_proto = next_proto
1585 return self
1586
1593
1594 - def write(self, trial=False):
1595 w = Writer()
1596 w.addVarSeq(self.next_proto, 1, 1)
1597 paddingLen = 32 - ((len(self.next_proto) + 2) % 32)
1598 w.addVarSeq(bytearray(paddingLen), 1, 1)
1599 return self.postWrite(w)
1600
1606
1607 - def create(self, verify_data):
1608 self.verify_data = verify_data
1609 return self
1610
1621
1626
1629 """Handling of the SSL2 FINISHED messages"""
1630
1634
1635 - def create(self, verify_data):
1636 """Set the message payload"""
1637 self.verify_data = verify_data
1638 return self
1639
1640 - def parse(self, parser):
1641 """Deserialise the message from on the wire data"""
1642 self.verify_data = parser.getFixBytes(parser.getRemainingLength())
1643 return self
1644
1646 """Serialise the message to on the wire data"""
1647 writer = Writer()
1648 writer.add(self.handshakeType, 1)
1649 writer.addFixSeq(self.verify_data, 1)
1650
1651 return writer.bytes
1652
1655 """
1656 Handling of SSLv2 CLIENT-FINISHED message
1657
1658 @type verify_data: bytearray
1659 @ivar verify_data: payload of the message, should be the CONNECTION-ID
1660 """
1661
1664
1667 """
1668 Handling of SSLv2 SERVER-FINISHED message
1669
1670 @type verify_data: bytearray
1671 @ivar verify_data: payload of the message, should be SESSION-ID
1672 """
1673
1676
1682
1684 self.bytes = bytes
1685 return self
1686
1688 newMsg = ApplicationData().create(self.bytes[:1])
1689 self.bytes = self.bytes[1:]
1690 return newMsg
1691
1693 self.bytes = p.bytes
1694 return self
1695
1698