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.bytes += self.random
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.bytes += self.random
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_N_len: int
1086 @cvar srp_N_len: length of srp_N in bytes
1087 @type srp_g: int
1088 @cvar srp_g: SRP protocol generator
1089 @type srp_g_len: int
1090 @cvar srp_g_len: length of srp_g in bytes
1091 @type srp_s: bytearray
1092 @cvar srp_s: SRP protocol salt value
1093 @type srp_B: int
1094 @cvar srp_B: SRP protocol server public value
1095 @type srp_B_len: int
1096 @cvar srp_B_len: length of srp_B in bytes
1097 @type dh_p: int
1098 @cvar dh_p: FFDHE protocol prime
1099 @type dh_p_len: int
1100 @cvar dh_p_len: length of dh_p in bytes
1101 @type dh_g: int
1102 @cvar dh_g: FFDHE protocol generator
1103 @type dh_g_len: int
1104 @type dh_g_len: length of dh_g in bytes
1105 @type dh_Ys: int
1106 @cvar dh_Ys: FFDH protocol server key share
1107 @type dh_Ys_len: int
1108 @cvar dh_Ys_len: length of dh_Ys in bytes
1109 @type curve_type: int
1110 @cvar curve_type: Type of curve used (explicit, named, etc.)
1111 @type named_curve: int
1112 @cvar named_curve: TLS ID of named curve
1113 @type ecdh_Ys: bytearray
1114 @cvar ecdh_Ys: ECDH protocol encoded point key share
1115 @type signature: bytearray
1116 @cvar signature: signature performed over the parameters by server
1117 @type hashAlg: int
1118 @cvar hashAlg: id of hash algorithm used for signature
1119 @type signAlg: int
1120 @cvar signAlg: id of signature algorithm used for signature
1121 """
1122
1123 - def __init__(self, cipherSuite, version):
1124 """
1125 Initialise Server Key Exchange for reading or writing.
1126
1127 @type cipherSuite: int
1128 @param cipherSuite: id of ciphersuite selected by server
1129 """
1130 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange)
1131 self.cipherSuite = cipherSuite
1132 self.version = version
1133 self.srp_N = 0
1134 self.srp_N_len = None
1135 self.srp_g = 0
1136 self.srp_g_len = None
1137 self.srp_s = bytearray(0)
1138 self.srp_B = 0
1139 self.srp_B_len = None
1140
1141 self.dh_p = 0
1142 self.dh_p_len = None
1143 self.dh_g = 0
1144 self.dh_g_len = None
1145 self.dh_Ys = 0
1146 self.dh_Ys_len = None
1147
1148 self.curve_type = None
1149 self.named_curve = None
1150 self.ecdh_Ys = bytearray(0)
1151
1152 self.signature = bytearray(0)
1153
1154 self.hashAlg = 0
1155 self.signAlg = 0
1156
1158 ret = "ServerKeyExchange(cipherSuite=CipherSuite.{0}, version={1}"\
1159 "".format(CipherSuite.ietfNames[self.cipherSuite], self.version)
1160
1161 if self.srp_N != 0:
1162 ret += ", srp_N={0}, srp_g={1}, srp_s={2!r}, srp_B={3}".format(
1163 self.srp_N, self.srp_g, self.srp_s, self.srp_B)
1164 if self.dh_p != 0:
1165 ret += ", dh_p={0}, dh_g={1}, dh_Ys={2}".format(
1166 self.dh_p, self.dh_g, self.dh_Ys)
1167 if self.signAlg != 0:
1168 ret += ", hashAlg={0}, signAlg={1}".format(
1169 self.hashAlg, self.signAlg)
1170 if self.signature != bytearray(0):
1171 ret += ", signature={0!r}".format(self.signature)
1172 ret += ")"
1173
1174 return ret
1175
1176 - def createSRP(self, srp_N, srp_g, srp_s, srp_B):
1177 """Set SRP protocol parameters."""
1178 self.srp_N = srp_N
1179 self.srp_N_len = None
1180 self.srp_g = srp_g
1181 self.srp_g_len = None
1182 self.srp_s = srp_s
1183 self.srp_B = srp_B
1184 self.srp_B_len = None
1185 return self
1186
1187 - def createDH(self, dh_p, dh_g, dh_Ys):
1188 """Set FFDH protocol parameters."""
1189 self.dh_p = dh_p
1190 self.dh_p_len = None
1191 self.dh_g = dh_g
1192 self.dh_g_len = None
1193 self.dh_Ys = dh_Ys
1194 self.dh_Ys_len = None
1195 return self
1196
1197 - def createECDH(self, curve_type, named_curve=None, point=None):
1198 """Set ECDH protocol parameters."""
1199 self.curve_type = curve_type
1200 self.named_curve = named_curve
1201 self.ecdh_Ys = point
1202
1203 - def parse(self, parser):
1243
1245 """
1246 Serialise the key exchange parameters.
1247
1248 @rtype: bytearray
1249 """
1250 writer = Writer()
1251 if self.cipherSuite in CipherSuite.srpAllSuites:
1252 writer.addVarSeq(numberToByteArray(self.srp_N, self.srp_N_len),
1253 1, 2)
1254 writer.addVarSeq(numberToByteArray(self.srp_g, self.srp_g_len),
1255 1, 2)
1256 writer.addVarSeq(self.srp_s, 1, 1)
1257 writer.addVarSeq(numberToByteArray(self.srp_B, self.srp_B_len),
1258 1, 2)
1259 elif self.cipherSuite in CipherSuite.dhAllSuites:
1260 writer.addVarSeq(numberToByteArray(self.dh_p, self.dh_p_len),
1261 1, 2)
1262 writer.addVarSeq(numberToByteArray(self.dh_g, self.dh_g_len),
1263 1, 2)
1264 writer.addVarSeq(numberToByteArray(self.dh_Ys, self.dh_Ys_len),
1265 1, 2)
1266 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1267 writer.add(self.curve_type, 1)
1268 assert self.curve_type == 3
1269 writer.add(self.named_curve, 2)
1270 writer.addVarSeq(self.ecdh_Ys, 1, 1)
1271 else:
1272 assert(False)
1273 return writer.bytes
1274
1276 """
1277 Serialise complete message.
1278
1279 @rtype: bytearray
1280 """
1281 writer = Writer()
1282 writer.bytes += self.writeParams()
1283 if self.cipherSuite in CipherSuite.certAllSuites:
1284 if self.version >= (3, 3):
1285 assert self.hashAlg != 0 and self.signAlg != 0
1286 writer.add(self.hashAlg, 1)
1287 writer.add(self.signAlg, 1)
1288 writer.addVarSeq(self.signature, 1, 2)
1289 return self.postWrite(writer)
1290
1291 - def hash(self, clientRandom, serverRandom):
1292 """
1293 Calculate hash of parameters to sign.
1294
1295 @rtype: bytearray
1296 """
1297 bytesToHash = clientRandom + serverRandom + self.writeParams()
1298 if self.version >= (3, 3):
1299 sigScheme = SignatureScheme.toRepr((self.hashAlg, self.signAlg))
1300 if sigScheme is None:
1301 hashAlg = HashAlgorithm.toRepr(self.hashAlg)
1302 if hashAlg is None:
1303 raise AssertionError("Unknown hash algorithm: {0}".
1304 format(self.hashAlg))
1305 else:
1306 hashAlg = SignatureScheme.getHash(sigScheme)
1307 return secureHash(bytesToHash, hashAlg)
1308 return MD5(bytesToHash) + SHA1(bytesToHash)
1309
1314
1317
1322
1326
1328 """Human readable representation of object."""
1329 return "ServerHelloDone()"
1330
1333 """
1334 Handling of TLS Handshake protocol ClientKeyExchange message.
1335
1336 @type cipherSuite: int
1337 @ivar cipherSuite: the cipher suite id used for the connection
1338 @type version: tuple(int, int)
1339 @ivar version: TLS protocol version used for the connection
1340 @type srp_A: int
1341 @ivar srp_A: SRP protocol client answer value
1342 @type dh_Yc: int
1343 @ivar dh_Yc: client Finite Field Diffie-Hellman protocol key share
1344 @type ecdh_Yc: bytearray
1345 @ivar ecdh_Yc: encoded curve coordinates
1346 @type encryptedPreMasterSecret: bytearray
1347 @ivar encryptedPreMasterSecret: client selected PremMaster secret encrypted
1348 with server public key (from certificate)
1349 """
1350
1351 - def __init__(self, cipherSuite, version=None):
1352 """
1353 Initialise ClientKeyExchange for reading or writing.
1354
1355 @type cipherSuite: int
1356 @param cipherSuite: id of the ciphersuite selected by server
1357 @type version: tuple(int, int)
1358 @param version: protocol version selected by server
1359 """
1360 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange)
1361 self.cipherSuite = cipherSuite
1362 self.version = version
1363 self.srp_A = 0
1364 self.dh_Yc = 0
1365 self.ecdh_Yc = bytearray(0)
1366 self.encryptedPreMasterSecret = bytearray(0)
1367
1369 """
1370 Set the SRP client answer.
1371
1372 returns self
1373
1374 @type srp_A: int
1375 @param srp_A: client SRP answer
1376 @rtype: L{ClientKeyExchange}
1377 """
1378 self.srp_A = srp_A
1379 return self
1380
1381 - def createRSA(self, encryptedPreMasterSecret):
1382 """
1383 Set the encrypted PreMaster Secret.
1384
1385 returns self
1386
1387 @type encryptedPreMasterSecret: bytearray
1388 @rtype: L{ClientKeyExchange}
1389 """
1390 self.encryptedPreMasterSecret = encryptedPreMasterSecret
1391 return self
1392
1394 """
1395 Set the client FFDH key share.
1396
1397 returns self
1398
1399 @type dh_Yc: int
1400 @rtype: L{ClientKeyExchange}
1401 """
1402 self.dh_Yc = dh_Yc
1403 return self
1404
1406 """
1407 Set the client ECDH key share.
1408
1409 returns self
1410
1411 @type ecdh_Yc: bytearray
1412 @rtype: L{ClientKeyExchange}
1413 """
1414 self.ecdh_Yc = ecdh_Yc
1415 return self
1416
1417 - def parse(self, parser):
1445
1447 """
1448 Serialise the object.
1449
1450 @rtype: bytearray
1451 """
1452 w = Writer()
1453 if self.cipherSuite in CipherSuite.srpAllSuites:
1454 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2)
1455 elif self.cipherSuite in CipherSuite.certSuites:
1456 if self.version in ((3, 1), (3, 2), (3, 3)):
1457 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2)
1458 elif self.version == (3, 0):
1459 w.bytes += self.encryptedPreMasterSecret
1460 else:
1461 raise AssertionError()
1462 elif self.cipherSuite in CipherSuite.dhAllSuites:
1463 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2)
1464 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1465 w.addVarSeq(self.ecdh_Yc, 1, 1)
1466 else:
1467 raise AssertionError()
1468 return self.postWrite(w)
1469
1472 """
1473 Handling of SSLv2 CLIENT-MASTER-KEY message.
1474
1475 @type cipher: int
1476 @ivar cipher: negotiated cipher
1477
1478 @type clear_key: bytearray
1479 @ivar clear_key: the part of master secret key that is sent in clear for
1480 export cipher suites
1481
1482 @type encrypted_key: bytearray
1483 @ivar encrypted_key: (part of) master secret encrypted using server key
1484
1485 @type key_argument: bytearray
1486 @ivar key_argument: additional key argument for block ciphers
1487 """
1488
1496
1497 - def create(self, cipher, clear_key, encrypted_key, key_argument):
1498 """Set values of the CLIENT-MASTER-KEY object."""
1499 self.cipher = cipher
1500 self.clear_key = clear_key
1501 self.encrypted_key = encrypted_key
1502 self.key_argument = key_argument
1503 return self
1504
1506 """Serialise the object to on the wire data."""
1507 writer = Writer()
1508 writer.add(self.handshakeType, 1)
1509 writer.add(self.cipher, 3)
1510 writer.add(len(self.clear_key), 2)
1511 writer.add(len(self.encrypted_key), 2)
1512 writer.add(len(self.key_argument), 2)
1513 writer.bytes += self.clear_key
1514 writer.bytes += self.encrypted_key
1515 writer.bytes += self.key_argument
1516 return writer.bytes
1517
1518 - def parse(self, parser):
1519 """Deserialise object from on the wire data."""
1520 self.cipher = parser.get(3)
1521 clear_key_length = parser.get(2)
1522 encrypted_key_length = parser.get(2)
1523 key_argument_length = parser.get(2)
1524 parser.setLengthCheck(clear_key_length +
1525 encrypted_key_length +
1526 key_argument_length)
1527 self.clear_key = parser.getFixBytes(clear_key_length)
1528 self.encrypted_key = parser.getFixBytes(encrypted_key_length)
1529 self.key_argument = parser.getFixBytes(key_argument_length)
1530 parser.stopLengthCheck()
1531 return self
1532
1535 """Serializer for TLS handshake protocol Certificate Verify message."""
1536
1547
1548 - def create(self, signature, signatureAlgorithm=None):
1549 """
1550 Provide data for serialisation of message.
1551
1552 @param signature: signature carried in the message
1553 @param signatureAlgorithm: signature algorithm used to make the
1554 signature (TLSv1.2 only)
1555 """
1556 self.signatureAlgorithm = signatureAlgorithm
1557 self.signature = signature
1558 return self
1559
1560 - def parse(self, parser):
1561 """
1562 Deserialize message from parser.
1563
1564 @param parser: parser with data to read
1565 """
1566 parser.startLengthCheck(3)
1567 if self.version >= (3, 3):
1568 self.signatureAlgorithm = (parser.get(1), parser.get(1))
1569 self.signature = parser.getVarBytes(2)
1570 parser.stopLengthCheck()
1571 return self
1572
1574 """
1575 Serialize the data to bytearray.
1576
1577 @rtype: bytearray
1578 """
1579 writer = Writer()
1580 if self.version >= (3, 3):
1581 writer.add(self.signatureAlgorithm[0], 1)
1582 writer.add(self.signatureAlgorithm[1], 1)
1583 writer.addVarSeq(self.signature, 1, 2)
1584 return self.postWrite(writer)
1585
1591
1593 self.type = 1
1594 return self
1595
1601
1603 w = Writer()
1604 w.add(self.type, 1)
1605 return w.bytes
1606
1612
1613 - def create(self, next_proto):
1614 self.next_proto = next_proto
1615 return self
1616
1623
1624 - def write(self, trial=False):
1625 w = Writer()
1626 w.addVarSeq(self.next_proto, 1, 1)
1627 paddingLen = 32 - ((len(self.next_proto) + 2) % 32)
1628 w.addVarSeq(bytearray(paddingLen), 1, 1)
1629 return self.postWrite(w)
1630
1637
1638 - def create(self, verify_data):
1639 self.verify_data = verify_data
1640 return self
1641
1652
1654 w = Writer()
1655 w.bytes += self.verify_data
1656 return self.postWrite(w)
1657
1660 """Handling of the SSL2 FINISHED messages."""
1661
1665
1666 - def create(self, verify_data):
1667 """Set the message payload."""
1668 self.verify_data = verify_data
1669 return self
1670
1671 - def parse(self, parser):
1672 """Deserialise the message from on the wire data."""
1673 self.verify_data = parser.getFixBytes(parser.getRemainingLength())
1674 return self
1675
1677 """Serialise the message to on the wire data."""
1678 writer = Writer()
1679 writer.add(self.handshakeType, 1)
1680 writer.bytes += self.verify_data
1681
1682 return writer.bytes
1683
1686 """
1687 Handling of SSLv2 CLIENT-FINISHED message.
1688
1689 @type verify_data: bytearray
1690 @ivar verify_data: payload of the message, should be the CONNECTION-ID
1691 """
1692
1695
1698 """
1699 Handling of SSLv2 SERVER-FINISHED message.
1700
1701 @type verify_data: bytearray
1702 @ivar verify_data: payload of the message, should be SESSION-ID
1703 """
1704
1707
1710 """
1711 Handling of the CertificateStatus message from RFC 6066.
1712
1713 Handling of the handshake protocol message that includes the OCSP staple.
1714
1715 @type status_type: int
1716 @ivar status_type: type of response returned
1717
1718 @type ocsp: bytearray
1719 @ivar ocsp: OCSPResponse from RFC 2560
1720 """
1721
1728
1729 - def create(self, status_type, ocsp):
1730 """Set up message payload."""
1731 self.status_type = status_type
1732 self.ocsp = ocsp
1733 return self
1734
1735 - def parse(self, parser):
1742
1744 """Serialise the message."""
1745 writer = Writer()
1746 writer.add(self.status_type, 1)
1747 writer.add(len(self.ocsp), 3)
1748 writer.bytes += self.ocsp
1749 return self.postWrite(writer)
1750
1756
1758 self.bytes = bytes
1759 return self
1760
1762 newMsg = ApplicationData().create(self.bytes[:1])
1763 self.bytes = self.bytes[1:]
1764 return newMsg
1765
1767 self.bytes = p.bytes
1768 return self
1769
1772