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 self.srp_username = bytearray(srpUsername, "utf-8")
569 self.tack = tack
570 if supports_npn is not None:
571 self.supports_npn = supports_npn
572 if serverName is not None:
573 self.server_name = bytearray(serverName, "utf-8")
574 return self
575
610
612 """Serialise SSLv2 object to on the wire data."""
613 writer = Writer()
614 writer.add(self.handshakeType, 1)
615 writer.add(self.client_version[0], 1)
616 writer.add(self.client_version[1], 1)
617
618 ciphersWriter = Writer()
619 ciphersWriter.addFixSeq(self.cipher_suites, 3)
620
621 writer.add(len(ciphersWriter.bytes), 2)
622 writer.add(len(self.session_id), 2)
623 writer.add(len(self.random), 2)
624
625 writer.bytes += ciphersWriter.bytes
626 writer.bytes += self.session_id
627 writer.bytes += self.random
628
629
630 return writer.bytes
631
633 """Serialise SSLv3 or TLS object to on the wire data."""
634 w = Writer()
635 w.add(self.client_version[0], 1)
636 w.add(self.client_version[1], 1)
637 w.addFixSeq(self.random, 1)
638 w.addVarSeq(self.session_id, 1, 1)
639 w.addVarSeq(self.cipher_suites, 2, 2)
640 w.addVarSeq(self.compression_methods, 1, 1)
641
642 if self.extensions is not None:
643 w2 = Writer()
644 for ext in self.extensions:
645 w2.bytes += ext.write()
646
647 w.add(len(w2.bytes), 2)
648 w.bytes += w2.bytes
649 return self.postWrite(w)
650
652 """Serialise object to on the wire data."""
653 if self.ssl2:
654 return self._writeSSL2()
655 else:
656 return self._write()
657
660 """
661 Handling of Server Hello messages.
662
663 @type server_version: tuple
664 @ivar server_version: protocol version encoded as two int tuple
665
666 @type random: bytearray
667 @ivar random: server random value
668
669 @type session_id: bytearray
670 @ivar session_id: session identifier for resumption
671
672 @type cipher_suite: int
673 @ivar cipher_suite: server selected cipher_suite
674
675 @type compression_method: int
676 @ivar compression_method: server selected compression method
677
678 @type next_protos: list of bytearray
679 @ivar next_protos: list of advertised protocols in NPN extension
680
681 @type next_protos_advertised: list of bytearray
682 @ivar next_protos_advertised: list of protocols advertised in NPN extension
683
684 @type certificate_type: int
685 @ivar certificate_type: certificate type selected by server
686
687 @type extensions: list
688 @ivar extensions: list of TLS extensions present in server_hello message,
689 see L{TLSExtension} and child classes for exact examples
690 """
691
693 """Initialise ServerHello object."""
694 super(ServerHello, self).__init__(HandshakeType.server_hello)
695 self.server_version = (0, 0)
696 self.random = bytearray(32)
697 self.session_id = bytearray(0)
698 self.cipher_suite = 0
699 self.compression_method = 0
700 self._tack_ext = None
701
703 base = "server_hello,length({0}),version({1[0]}.{1[1]}),random(...),"\
704 "session ID({2!r}),cipher({3:#x}),compression method({4})"\
705 .format(len(self.write())-4, self.server_version,
706 self.session_id, self.cipher_suite,
707 self.compression_method)
708
709 if self.extensions is None:
710 return base
711
712 ret = ",extensions["
713 ret += ",".join(repr(x) for x in self.extensions)
714 ret += "]"
715 return base + ret
716
718 return "ServerHello(server_version=({0[0]}, {0[1]}), random={1!r}, "\
719 "session_id={2!r}, cipher_suite={3}, compression_method={4}, "\
720 "_tack_ext={5}, extensions={6!r})".format(
721 self.server_version, self.random, self.session_id,
722 self.cipher_suite, self.compression_method, self._tack_ext,
723 self.extensions)
724
725 @property
727 """Return the TACK extension."""
728 if self._tack_ext is None:
729 ext = self.getExtension(ExtensionType.tack)
730 if ext is None or not tackpyLoaded:
731 return None
732 else:
733 self._tack_ext = TackExtension(ext.extData)
734 return self._tack_ext
735
736 @tackExt.setter
738 """Set the TACK extension."""
739 self._tack_ext = val
740
741 if val is not None:
742 if self.extensions is None:
743 self.extensions = []
744
745 @property
758
759 @certificate_type.setter
777
778 @property
780 """
781 Return the advertised protocols in NPN extension.
782
783 @rtype: list of bytearrays
784 """
785 npn_ext = self.getExtension(ExtensionType.supports_npn)
786
787 if npn_ext is None:
788 return None
789 else:
790 return npn_ext.protocols
791
792 @next_protos.setter
794 """
795 Set the advertised protocols in NPN extension.
796
797 @type val: list
798 @param val: list of protocols to advertise as UTF-8 encoded names
799 """
800 if val is None:
801 return
802 else:
803
804 val = [bytearray(x) for x in val]
805
806 npn_ext = self.getExtension(ExtensionType.supports_npn)
807
808 if npn_ext is None:
809 ext = NPNExtension().create(val)
810 self.addExtension(ext)
811 else:
812 npn_ext.protocols = val
813
814 @property
816 """
817 Return the advertised protocols in NPN extension.
818
819 @rtype: list of bytearrays
820 """
821 return self.next_protos
822
823 @next_protos_advertised.setter
825 """
826 Set the advertised protocols in NPN extension.
827
828 @type val: list
829 @param val: list of protocols to advertise as UTF-8 encoded names
830 """
831 self.next_protos = val
832
833 - def create(self, version, random, session_id, cipher_suite,
834 certificate_type=None, tackExt=None,
835 next_protos_advertised=None,
836 extensions=None):
849
866
868 w = Writer()
869 w.add(self.server_version[0], 1)
870 w.add(self.server_version[1], 1)
871 w.addFixSeq(self.random, 1)
872 w.addVarSeq(self.session_id, 1, 1)
873 w.add(self.cipher_suite, 2)
874 w.add(self.compression_method, 1)
875
876 if self.extensions is not None:
877 w2 = Writer()
878 for ext in self.extensions:
879 w2.bytes += ext.write()
880
881 if self.tackExt:
882 b = self.tackExt.serialize()
883 w2.add(ExtensionType.tack, 2)
884 w2.add(len(b), 2)
885 w2.bytes += b
886
887 w.add(len(w2.bytes), 2)
888 w.bytes += w2.bytes
889 return self.postWrite(w)
890
893 """
894 SERVER-HELLO message from SSLv2.
895
896 @type session_id_hit: int
897 @ivar session_id_hit: non zero if the client provided session ID was
898 matched in server's session cache
899
900 @type certificate_type: int
901 @ivar certificate_type: type of certificate sent
902
903 @type server_version: tuple of ints
904 @ivar server_version: protocol version selected by server
905
906 @type certificate: bytearray
907 @ivar certificate: certificate sent by server
908
909 @type ciphers: array of int
910 @ivar ciphers: list of ciphers supported by server
911
912 @type session_id: bytearray
913 @ivar session_id: idendifier of negotiated session
914 """
915
924
925 - def create(self, session_id_hit, certificate_type, server_version,
926 certificate, ciphers, session_id):
927 """Initialize fields of the SERVER-HELLO message."""
928 self.session_id_hit = session_id_hit
929 self.certificate_type = certificate_type
930 self.server_version = server_version
931 self.certificate = certificate
932 self.ciphers = ciphers
933 self.session_id = session_id
934 return self
935
937 """Serialise object to on the wire data."""
938 writer = Writer()
939 writer.add(self.handshakeType, 1)
940 writer.add(self.session_id_hit, 1)
941 writer.add(self.certificate_type, 1)
942 if len(self.server_version) != 2:
943 raise ValueError("server version must be a 2-element tuple")
944 writer.addFixSeq(self.server_version, 1)
945 writer.add(len(self.certificate), 2)
946
947 ciphersWriter = Writer()
948 ciphersWriter.addFixSeq(self.ciphers, 3)
949
950 writer.add(len(ciphersWriter.bytes), 2)
951 writer.add(len(self.session_id), 2)
952
953 writer.bytes += self.certificate
954 writer.bytes += ciphersWriter.bytes
955 writer.bytes += self.session_id
956
957
958 return writer.bytes
959
960 - def parse(self, parser):
961 """Deserialise object from on the wire data."""
962 self.session_id_hit = parser.get(1)
963 self.certificate_type = parser.get(1)
964 self.server_version = (parser.get(1), parser.get(1))
965 certificateLength = parser.get(2)
966 ciphersLength = parser.get(2)
967 sessionIDLength = parser.get(2)
968 parser.setLengthCheck(certificateLength +
969 ciphersLength +
970 sessionIDLength)
971 self.certificate = parser.getFixBytes(certificateLength)
972 self.ciphers = parser.getFixList(3, ciphersLength // 3)
973 self.session_id = parser.getFixBytes(sessionIDLength)
974 parser.stopLengthCheck()
975 return self
976
983
985 self.certChain = certChain
986 return self
987
1007
1009 w = Writer()
1010 if self.certificateType == CertificateType.x509:
1011 chainLength = 0
1012 if self.certChain:
1013 certificate_list = self.certChain.x509List
1014 else:
1015 certificate_list = []
1016
1017 for cert in certificate_list:
1018 bytes = cert.writeBytes()
1019 chainLength += len(bytes)+3
1020
1021 w.add(chainLength, 3)
1022 for cert in certificate_list:
1023 bytes = cert.writeBytes()
1024 w.addVarSeq(bytes, 1, 3)
1025 else:
1026 raise AssertionError()
1027 return self.postWrite(w)
1028
1037
1038 - def create(self, certificate_types, certificate_authorities, sig_algs=()):
1039 self.certificate_types = certificate_types
1040 self.certificate_authorities = certificate_authorities
1041 self.supported_signature_algs = sig_algs
1042 return self
1043
1058
1060 w = Writer()
1061 w.addVarSeq(self.certificate_types, 1, 1)
1062 if self.version >= (3, 3):
1063 w.addVarTupleSeq(self.supported_signature_algs, 1, 2)
1064 caLength = 0
1065
1066 for ca_dn in self.certificate_authorities:
1067 caLength += len(ca_dn)+2
1068 w.add(caLength, 2)
1069
1070 for ca_dn in self.certificate_authorities:
1071 w.addVarSeq(ca_dn, 1, 2)
1072 return self.postWrite(w)
1073
1076 """
1077 Handling TLS Handshake protocol Server Key Exchange messages.
1078
1079 @type cipherSuite: int
1080 @cvar cipherSuite: id of ciphersuite selected in Server Hello message
1081 @type srp_N: int
1082 @cvar srp_N: SRP protocol prime
1083 @type srp_g: int
1084 @cvar srp_g: SRP protocol generator
1085 @type srp_s: bytearray
1086 @cvar srp_s: SRP protocol salt value
1087 @type srp_B: int
1088 @cvar srp_B: SRP protocol server public value
1089 @type dh_p: int
1090 @cvar dh_p: FFDHE protocol prime
1091 @type dh_g: int
1092 @cvar dh_g: FFDHE protocol generator
1093 @type dh_Ys: int
1094 @cvar dh_Ys: FFDH protocol server key share
1095 @type curve_type: int
1096 @cvar curve_type: Type of curve used (explicit, named, etc.)
1097 @type named_curve: int
1098 @cvar named_curve: TLS ID of named curve
1099 @type ecdh_Ys: bytearray
1100 @cvar ecdh_Ys: ECDH protocol encoded point key share
1101 @type signature: bytearray
1102 @cvar signature: signature performed over the parameters by server
1103 @type hashAlg: int
1104 @cvar hashAlg: id of hash algorithm used for signature
1105 @type signAlg: int
1106 @cvar signAlg: id of signature algorithm used for signature
1107 """
1108
1109 - def __init__(self, cipherSuite, version):
1110 """
1111 Initialise Server Key Exchange for reading or writing.
1112
1113 @type cipherSuite: int
1114 @param cipherSuite: id of ciphersuite selected by server
1115 """
1116 HandshakeMsg.__init__(self, HandshakeType.server_key_exchange)
1117 self.cipherSuite = cipherSuite
1118 self.version = version
1119 self.srp_N = 0
1120 self.srp_g = 0
1121 self.srp_s = bytearray(0)
1122 self.srp_B = 0
1123
1124 self.dh_p = 0
1125 self.dh_g = 0
1126 self.dh_Ys = 0
1127
1128 self.curve_type = None
1129 self.named_curve = None
1130 self.ecdh_Ys = bytearray(0)
1131
1132 self.signature = bytearray(0)
1133
1134 self.hashAlg = 0
1135 self.signAlg = 0
1136
1138 ret = "ServerKeyExchange(cipherSuite=CipherSuite.{0}, version={1}"\
1139 "".format(CipherSuite.ietfNames[self.cipherSuite], self.version)
1140
1141 if self.srp_N != 0:
1142 ret += ", srp_N={0}, srp_g={1}, srp_s={2!r}, srp_B={3}".format(
1143 self.srp_N, self.srp_g, self.srp_s, self.srp_B)
1144 if self.dh_p != 0:
1145 ret += ", dh_p={0}, dh_g={1}, dh_Ys={2}".format(
1146 self.dh_p, self.dh_g, self.dh_Ys)
1147 if self.signAlg != 0:
1148 ret += ", hashAlg={0}, signAlg={1}".format(
1149 self.hashAlg, self.signAlg)
1150 if self.signature != bytearray(0):
1151 ret += ", signature={0!r}".format(self.signature)
1152 ret += ")"
1153
1154 return ret
1155
1156 - def createSRP(self, srp_N, srp_g, srp_s, srp_B):
1157 """Set SRP protocol parameters."""
1158 self.srp_N = srp_N
1159 self.srp_g = srp_g
1160 self.srp_s = srp_s
1161 self.srp_B = srp_B
1162 return self
1163
1164 - def createDH(self, dh_p, dh_g, dh_Ys):
1165 """Set FFDH protocol parameters."""
1166 self.dh_p = dh_p
1167 self.dh_g = dh_g
1168 self.dh_Ys = dh_Ys
1169 return self
1170
1171 - def createECDH(self, curve_type, named_curve=None, point=None):
1172 """Set ECDH protocol parameters."""
1173 self.curve_type = curve_type
1174 self.named_curve = named_curve
1175 self.ecdh_Ys = point
1176
1177 - def parse(self, parser):
1211
1213 """
1214 Serialise the key exchange parameters.
1215
1216 @rtype: bytearray
1217 """
1218 writer = Writer()
1219 if self.cipherSuite in CipherSuite.srpAllSuites:
1220 writer.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
1221 writer.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
1222 writer.addVarSeq(self.srp_s, 1, 1)
1223 writer.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
1224 elif self.cipherSuite in CipherSuite.dhAllSuites:
1225 writer.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
1226 writer.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
1227 writer.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
1228 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1229 writer.add(self.curve_type, 1)
1230 assert self.curve_type == 3
1231 writer.add(self.named_curve, 2)
1232 writer.addVarSeq(self.ecdh_Ys, 1, 1)
1233 else:
1234 assert(False)
1235 return writer.bytes
1236
1238 """
1239 Serialise complete message.
1240
1241 @rtype: bytearray
1242 """
1243 writer = Writer()
1244 writer.bytes += self.writeParams()
1245 if self.cipherSuite in CipherSuite.certAllSuites:
1246 if self.version >= (3, 3):
1247 assert self.hashAlg != 0 and self.signAlg != 0
1248 writer.add(self.hashAlg, 1)
1249 writer.add(self.signAlg, 1)
1250 writer.addVarSeq(self.signature, 1, 2)
1251 return self.postWrite(writer)
1252
1253 - def hash(self, clientRandom, serverRandom):
1254 """
1255 Calculate hash of parameters to sign.
1256
1257 @rtype: bytearray
1258 """
1259 bytesToHash = clientRandom + serverRandom + self.writeParams()
1260 if self.version >= (3, 3):
1261 hashAlg = HashAlgorithm.toRepr(self.hashAlg)
1262 if hashAlg is None:
1263 raise AssertionError("Unknown hash algorithm: {0}".
1264 format(self.hashAlg))
1265 return secureHash(bytesToHash, hashAlg)
1266 return MD5(bytesToHash) + SHA1(bytesToHash)
1267
1272
1275
1280
1284
1286 """Human readable representation of object."""
1287 return "ServerHelloDone()"
1288
1291 """
1292 Handling of TLS Handshake protocol ClientKeyExchange message.
1293
1294 @type cipherSuite: int
1295 @ivar cipherSuite: the cipher suite id used for the connection
1296 @type version: tuple(int, int)
1297 @ivar version: TLS protocol version used for the connection
1298 @type srp_A: int
1299 @ivar srp_A: SRP protocol client answer value
1300 @type dh_Yc: int
1301 @ivar dh_Yc: client Finite Field Diffie-Hellman protocol key share
1302 @type ecdh_Yc: bytearray
1303 @ivar ecdh_Yc: encoded curve coordinates
1304 @type encryptedPreMasterSecret: bytearray
1305 @ivar encryptedPreMasterSecret: client selected PremMaster secret encrypted
1306 with server public key (from certificate)
1307 """
1308
1309 - def __init__(self, cipherSuite, version=None):
1310 """
1311 Initialise ClientKeyExchange for reading or writing.
1312
1313 @type cipherSuite: int
1314 @param cipherSuite: id of the ciphersuite selected by server
1315 @type version: tuple(int, int)
1316 @param version: protocol version selected by server
1317 """
1318 HandshakeMsg.__init__(self, HandshakeType.client_key_exchange)
1319 self.cipherSuite = cipherSuite
1320 self.version = version
1321 self.srp_A = 0
1322 self.dh_Yc = 0
1323 self.ecdh_Yc = bytearray(0)
1324 self.encryptedPreMasterSecret = bytearray(0)
1325
1327 """
1328 Set the SRP client answer.
1329
1330 returns self
1331
1332 @type srp_A: int
1333 @param srp_A: client SRP answer
1334 @rtype: L{ClientKeyExchange}
1335 """
1336 self.srp_A = srp_A
1337 return self
1338
1339 - def createRSA(self, encryptedPreMasterSecret):
1340 """
1341 Set the encrypted PreMaster Secret.
1342
1343 returns self
1344
1345 @type encryptedPreMasterSecret: bytearray
1346 @rtype: L{ClientKeyExchange}
1347 """
1348 self.encryptedPreMasterSecret = encryptedPreMasterSecret
1349 return self
1350
1352 """
1353 Set the client FFDH key share.
1354
1355 returns self
1356
1357 @type dh_Yc: int
1358 @rtype: L{ClientKeyExchange}
1359 """
1360 self.dh_Yc = dh_Yc
1361 return self
1362
1364 """
1365 Set the client ECDH key share.
1366
1367 returns self
1368
1369 @type ecdh_Yc: bytearray
1370 @rtype: L{ClientKeyExchange}
1371 """
1372 self.ecdh_Yc = ecdh_Yc
1373 return self
1374
1375 - def parse(self, parser):
1403
1405 """
1406 Serialise the object.
1407
1408 @rtype: bytearray
1409 """
1410 w = Writer()
1411 if self.cipherSuite in CipherSuite.srpAllSuites:
1412 w.addVarSeq(numberToByteArray(self.srp_A), 1, 2)
1413 elif self.cipherSuite in CipherSuite.certSuites:
1414 if self.version in ((3, 1), (3, 2), (3, 3)):
1415 w.addVarSeq(self.encryptedPreMasterSecret, 1, 2)
1416 elif self.version == (3, 0):
1417 w.addFixSeq(self.encryptedPreMasterSecret, 1)
1418 else:
1419 raise AssertionError()
1420 elif self.cipherSuite in CipherSuite.dhAllSuites:
1421 w.addVarSeq(numberToByteArray(self.dh_Yc), 1, 2)
1422 elif self.cipherSuite in CipherSuite.ecdhAllSuites:
1423 w.addVarSeq(self.ecdh_Yc, 1, 1)
1424 else:
1425 raise AssertionError()
1426 return self.postWrite(w)
1427
1430 """
1431 Handling of SSLv2 CLIENT-MASTER-KEY message.
1432
1433 @type cipher: int
1434 @ivar cipher: negotiated cipher
1435
1436 @type clear_key: bytearray
1437 @ivar clear_key: the part of master secret key that is sent in clear for
1438 export cipher suites
1439
1440 @type encrypted_key: bytearray
1441 @ivar encrypted_key: (part of) master secret encrypted using server key
1442
1443 @type key_argument: bytearray
1444 @ivar key_argument: additional key argument for block ciphers
1445 """
1446
1454
1455 - def create(self, cipher, clear_key, encrypted_key, key_argument):
1456 """Set values of the CLIENT-MASTER-KEY object."""
1457 self.cipher = cipher
1458 self.clear_key = clear_key
1459 self.encrypted_key = encrypted_key
1460 self.key_argument = key_argument
1461 return self
1462
1464 """Serialise the object to on the wire data."""
1465 writer = Writer()
1466 writer.add(self.handshakeType, 1)
1467 writer.add(self.cipher, 3)
1468 writer.add(len(self.clear_key), 2)
1469 writer.add(len(self.encrypted_key), 2)
1470 writer.add(len(self.key_argument), 2)
1471 writer.bytes += self.clear_key
1472 writer.bytes += self.encrypted_key
1473 writer.bytes += self.key_argument
1474 return writer.bytes
1475
1476 - def parse(self, parser):
1477 """Deserialise object from on the wire data."""
1478 self.cipher = parser.get(3)
1479 clear_key_length = parser.get(2)
1480 encrypted_key_length = parser.get(2)
1481 key_argument_length = parser.get(2)
1482 parser.setLengthCheck(clear_key_length +
1483 encrypted_key_length +
1484 key_argument_length)
1485 self.clear_key = parser.getFixBytes(clear_key_length)
1486 self.encrypted_key = parser.getFixBytes(encrypted_key_length)
1487 self.key_argument = parser.getFixBytes(key_argument_length)
1488 parser.stopLengthCheck()
1489 return self
1490
1493 """Serializer for TLS handshake protocol Certificate Verify message."""
1494
1505
1506 - def create(self, signature, signatureAlgorithm=None):
1507 """
1508 Provide data for serialisation of message.
1509
1510 @param signature: signature carried in the message
1511 @param signatureAlgorithm: signature algorithm used to make the
1512 signature (TLSv1.2 only)
1513 """
1514 self.signatureAlgorithm = signatureAlgorithm
1515 self.signature = signature
1516 return self
1517
1518 - def parse(self, parser):
1519 """
1520 Deserialize message from parser.
1521
1522 @param parser: parser with data to read
1523 """
1524 parser.startLengthCheck(3)
1525 if self.version >= (3, 3):
1526 self.signatureAlgorithm = (parser.get(1), parser.get(1))
1527 self.signature = parser.getVarBytes(2)
1528 parser.stopLengthCheck()
1529 return self
1530
1532 """
1533 Serialize the data to bytearray.
1534
1535 @rtype: bytearray
1536 """
1537 writer = Writer()
1538 if self.version >= (3, 3):
1539 writer.add(self.signatureAlgorithm[0], 1)
1540 writer.add(self.signatureAlgorithm[1], 1)
1541 writer.addVarSeq(self.signature, 1, 2)
1542 return self.postWrite(writer)
1543
1549
1551 self.type = 1
1552 return self
1553
1559
1561 w = Writer()
1562 w.add(self.type, 1)
1563 return w.bytes
1564
1570
1571 - def create(self, next_proto):
1572 self.next_proto = next_proto
1573 return self
1574
1581
1582 - def write(self, trial=False):
1583 w = Writer()
1584 w.addVarSeq(self.next_proto, 1, 1)
1585 paddingLen = 32 - ((len(self.next_proto) + 2) % 32)
1586 w.addVarSeq(bytearray(paddingLen), 1, 1)
1587 return self.postWrite(w)
1588
1595
1596 - def create(self, verify_data):
1597 self.verify_data = verify_data
1598 return self
1599
1610
1615
1618 """Handling of the SSL2 FINISHED messages."""
1619
1623
1624 - def create(self, verify_data):
1625 """Set the message payload."""
1626 self.verify_data = verify_data
1627 return self
1628
1629 - def parse(self, parser):
1630 """Deserialise the message from on the wire data."""
1631 self.verify_data = parser.getFixBytes(parser.getRemainingLength())
1632 return self
1633
1635 """Serialise the message to on the wire data."""
1636 writer = Writer()
1637 writer.add(self.handshakeType, 1)
1638 writer.addFixSeq(self.verify_data, 1)
1639
1640 return writer.bytes
1641
1644 """
1645 Handling of SSLv2 CLIENT-FINISHED message.
1646
1647 @type verify_data: bytearray
1648 @ivar verify_data: payload of the message, should be the CONNECTION-ID
1649 """
1650
1653
1656 """
1657 Handling of SSLv2 SERVER-FINISHED message.
1658
1659 @type verify_data: bytearray
1660 @ivar verify_data: payload of the message, should be SESSION-ID
1661 """
1662
1665
1671
1673 self.bytes = bytes
1674 return self
1675
1677 newMsg = ApplicationData().create(self.bytes[:1])
1678 self.bytes = self.bytes[1:]
1679 return newMsg
1680
1682 self.bytes = p.bytes
1683 return self
1684
1687