1
2
3
4 """Secure Sockets Layer / Transport Layer Security."""
5 from __future__ import absolute_import
6
7 import struct
8 import binascii
9
10 from . import dpkt
11 from . import ssl_ciphersuites
12
13
14
15
16
17
18
19
20 -class SSL2(dpkt.Packet):
21 __hdr__ = (
22 ('len', 'H', 0),
23 ('msg', 's', ''),
24 ('pad', 's', ''),
25 )
26
38
39
40
41
42 -class TLS(dpkt.Packet):
43 __hdr__ = (
44 ('type', 'B', ''),
45 ('version', 'H', ''),
46 ('len', 'H', ''),
47 )
48
52
53
55 dpkt.Packet.unpack(self, buf)
56 pointer = 0
57 while len(self.data[pointer:]) > 0:
58 end = pointer + 5 + struct.unpack("!H", buf[pointer+3:pointer+5])[0]
59 self.records.append(TLSRecord(buf[pointer:end]))
60 pointer = end
61 self.data = self.data[pointer:]
62
63
64
65 SSL3_V = 0x0300
66 TLS1_V = 0x0301
67 TLS11_V = 0x0302
68 TLS12_V = 0x0303
69
70 ssl3_versions_str = {
71 SSL3_V: 'SSL3',
72 TLS1_V: 'TLS 1.0',
73 TLS11_V: 'TLS 1.1',
74 TLS12_V: 'TLS 1.2'
75 }
76
77 SSL3_VERSION_BYTES = set((b'\x03\x00', b'\x03\x01', b'\x03\x02', b'\x03\x03'))
78
79
80
81 SSL3_AD_WARNING = 1
82 SSL3_AD_FATAL = 2
83 alert_level_str = {
84 SSL3_AD_WARNING: 'SSL3_AD_WARNING',
85 SSL3_AD_FATAL: 'SSL3_AD_FATAL'
86 }
87
88
89 SSL3_AD_CLOSE_NOTIFY = 0
90 SSL3_AD_UNEXPECTED_MESSAGE = 10
91 SSL3_AD_BAD_RECORD_MAC = 20
92 SSL3_AD_DECOMPRESSION_FAILURE = 30
93 SSL3_AD_HANDSHAKE_FAILURE = 40
94 SSL3_AD_NO_CERTIFICATE = 41
95 SSL3_AD_BAD_CERTIFICATE = 42
96 SSL3_AD_UNSUPPORTED_CERTIFICATE = 43
97 SSL3_AD_CERTIFICATE_REVOKED = 44
98 SSL3_AD_CERTIFICATE_EXPIRED = 45
99 SSL3_AD_CERTIFICATE_UNKNOWN = 46
100 SSL3_AD_ILLEGAL_PARAMETER = 47
101
102
103 TLS1_AD_DECRYPTION_FAILED = 21
104 TLS1_AD_RECORD_OVERFLOW = 22
105 TLS1_AD_UNKNOWN_CA = 48
106 TLS1_AD_ACCESS_DENIED = 49
107 TLS1_AD_DECODE_ERROR = 50
108 TLS1_AD_DECRYPT_ERROR = 51
109 TLS1_AD_EXPORT_RESTRICTION = 60
110 TLS1_AD_PROTOCOL_VERSION = 70
111 TLS1_AD_INSUFFICIENT_SECURITY = 71
112 TLS1_AD_INTERNAL_ERROR = 80
113 TLS1_AD_USER_CANCELLED = 90
114 TLS1_AD_NO_RENEGOTIATION = 100
115
116 TLS1_AD_UNSUPPORTED_EXTENSION = 110
117 TLS1_AD_CERTIFICATE_UNOBTAINABLE = 111
118 TLS1_AD_UNRECOGNIZED_NAME = 112
119 TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE = 113
120 TLS1_AD_BAD_CERTIFICATE_HASH_VALUE = 114
121 TLS1_AD_UNKNOWN_PSK_IDENTITY = 115
122
123
124
125 alert_description_str = {
126 SSL3_AD_CLOSE_NOTIFY: 'SSL3_AD_CLOSE_NOTIFY',
127 SSL3_AD_UNEXPECTED_MESSAGE: 'SSL3_AD_UNEXPECTED_MESSAGE',
128 SSL3_AD_BAD_RECORD_MAC: 'SSL3_AD_BAD_RECORD_MAC',
129 SSL3_AD_DECOMPRESSION_FAILURE: 'SSL3_AD_DECOMPRESSION_FAILURE',
130 SSL3_AD_HANDSHAKE_FAILURE: 'SSL3_AD_HANDSHAKE_FAILURE',
131 SSL3_AD_NO_CERTIFICATE: 'SSL3_AD_NO_CERTIFICATE',
132 SSL3_AD_BAD_CERTIFICATE: 'SSL3_AD_BAD_CERTIFICATE',
133 SSL3_AD_UNSUPPORTED_CERTIFICATE: 'SSL3_AD_UNSUPPORTED_CERTIFICATE',
134 SSL3_AD_CERTIFICATE_REVOKED: 'SSL3_AD_CERTIFICATE_REVOKED',
135 SSL3_AD_CERTIFICATE_EXPIRED: 'SSL3_AD_CERTIFICATE_EXPIRED',
136 SSL3_AD_CERTIFICATE_UNKNOWN: 'SSL3_AD_CERTIFICATE_UNKNOWN',
137 SSL3_AD_ILLEGAL_PARAMETER: 'SSL3_AD_ILLEGAL_PARAMETER',
138 TLS1_AD_DECRYPTION_FAILED: 'TLS1_AD_DECRYPTION_FAILED',
139 TLS1_AD_RECORD_OVERFLOW: 'TLS1_AD_RECORD_OVERFLOW',
140 TLS1_AD_UNKNOWN_CA: 'TLS1_AD_UNKNOWN_CA',
141 TLS1_AD_ACCESS_DENIED: 'TLS1_AD_ACCESS_DENIED',
142 TLS1_AD_DECODE_ERROR: 'TLS1_AD_DECODE_ERROR',
143 TLS1_AD_DECRYPT_ERROR: 'TLS1_AD_DECRYPT_ERROR',
144 TLS1_AD_EXPORT_RESTRICTION: 'TLS1_AD_EXPORT_RESTRICTION',
145 TLS1_AD_PROTOCOL_VERSION: 'TLS1_AD_PROTOCOL_VERSION',
146 TLS1_AD_INSUFFICIENT_SECURITY: 'TLS1_AD_INSUFFICIENT_SECURITY',
147 TLS1_AD_INTERNAL_ERROR: 'TLS1_AD_INTERNAL_ERROR',
148 TLS1_AD_USER_CANCELLED: 'TLS1_AD_USER_CANCELLED',
149 TLS1_AD_NO_RENEGOTIATION: 'TLS1_AD_NO_RENEGOTIATION',
150 TLS1_AD_UNSUPPORTED_EXTENSION: 'TLS1_AD_UNSUPPORTED_EXTENSION',
151 TLS1_AD_CERTIFICATE_UNOBTAINABLE: 'TLS1_AD_CERTIFICATE_UNOBTAINABLE',
152 TLS1_AD_UNRECOGNIZED_NAME: 'TLS1_AD_UNRECOGNIZED_NAME',
153 TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: 'TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE',
154 TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: 'TLS1_AD_BAD_CERTIFICATE_HASH_VALUE',
155 TLS1_AD_UNKNOWN_PSK_IDENTITY: 'TLS1_AD_UNKNOWN_PSK_IDENTITY'
156 }
157
158
159
160
161 _SIZE_FORMATS = ['!B', '!H', '!I', '!I']
165 """
166 Parse an array described using the 'Type name<x..y>' syntax from the spec
167 Read a length at the start of buf, and returns that many bytes
168 after, in a tuple with the TOTAL bytes consumed (including the size). This
169 does not check that the array is the right length for any given datatype.
170 """
171
172 assert lenbytes <= 4
173 size_format = _SIZE_FORMATS[lenbytes - 1]
174 padding = b'\x00' if lenbytes == 3 else b''
175
176 size = struct.unpack(size_format, padding + buf[:lenbytes])[0]
177
178 data = buf[lenbytes:lenbytes + size]
179
180 return data, size + lenbytes
181
184 """
185 Parse TLS extensions in passed buf. Returns an ordered list of extension tuples with
186 ordinal extension type as first value and extension data as second value.
187 Passed buf must start with the 2-byte extensions length TLV.
188 http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
189 """
190 extensions_length = struct.unpack('!H', buf[:2])[0]
191 extensions = []
192
193 pointer = 2
194 while pointer < extensions_length:
195 ext_type = struct.unpack('!H', buf[pointer:pointer+2])[0]
196 pointer += 2
197 ext_data, parsed = parse_variable_array(buf[pointer:], 2)
198 extensions.append((ext_type, ext_data))
199 pointer += parsed
200 return extensions
201
205
208
209 """
210 SSLv3 or TLSv1+ packet.
211
212 In addition to the fields specified in the header, there are
213 compressed and decrypted fields, indicating whether, in the language
214 of the spec, this is a TLSPlaintext, TLSCompressed, or
215 TLSCiphertext. The application will have to figure out when it's
216 appropriate to change these values.
217 """
218
219 __hdr__ = (
220 ('type', 'B', 0),
221 ('version', 'H', 0),
222 ('length', 'H', 0),
223 )
224
233
245
248
249 """
250 ChangeCipherSpec message is just a single byte with value 1
251 """
252
253 __hdr__ = (('type', 'B', 1),)
254
257
258 """
259 As far as TLSRecord is concerned, AppData is just an opaque blob.
260 """
261
262 pass
263
266 __hdr__ = (
267 ('level', 'B', 1),
268 ('description', 'B', 0),
269 )
270
274
277 __hdr__ = (
278 ('version', 'H', 0x0301),
279 ('random', '32s', '\x00' * 32),
280 )
281
301
304 __hdr__ = (
305 ('version', 'H', '0x0301'),
306 ('random', '32s', '\x00' * 32),
307 )
308
325
342
346
347
348 TLSServerKeyExchange = TLSUnknownHandshake
349 TLSCertificateRequest = TLSUnknownHandshake
350 TLSServerHelloDone = TLSUnknownHandshake
351 TLSCertificateVerify = TLSUnknownHandshake
352 TLSClientKeyExchange = TLSUnknownHandshake
353 TLSFinished = TLSUnknownHandshake
354
355
356
357
358 HANDSHAKE_TYPES = {
359 0: ('HelloRequest', TLSHelloRequest),
360 1: ('ClientHello', TLSClientHello),
361 2: ('ServerHello', TLSServerHello),
362 11: ('Certificate', TLSCertificate),
363 12: ('ServerKeyExchange', TLSServerKeyExchange),
364 13: ('CertificateRequest', TLSCertificateRequest),
365 14: ('ServerHelloDone', TLSServerHelloDone),
366 15: ('CertificateVerify', TLSCertificateVerify),
367 16: ('ClientKeyExchange', TLSClientKeyExchange),
368 20: ('Finished', TLSFinished),
369 }
373
374 """
375 A TLS Handshake message
376
377 This goes for all messages encapsulated in the Record layer, but especially
378 important for handshakes and app data: A message may be spread across a
379 number of TLSRecords, in addition to the possibility of there being more
380 than one in a given Record. You have to put together the contents of
381 TLSRecord's yourself.
382 """
383
384
385
386
387 __hdr__ = (
388 ('type', 'B', 0),
389 ('length_bytes', '3s', 0),
390 )
391
405
406 @property
409
410
411 RECORD_TYPES = {
412 20: TLSChangeCipherSpec,
413 21: TLSAlert,
414 22: TLSHandshake,
415 23: TLSAppData,
416 }
427
430 """
431 Attempt to parse one or more TLSRecord's out of buf
432
433 Args:
434 buf: string containing SSL/TLS messages. May have an incomplete record
435 on the end
436
437 Returns:
438 [TLSRecord]
439 int, total bytes consumed, != len(buf) if an incomplete record was left at
440 the end.
441
442 Raises SSL3Exception.
443 """
444 i, n = 0, len(buf)
445 msgs = []
446 while i < n:
447 v = buf[i + 1:i + 3]
448 if v in SSL3_VERSION_BYTES:
449 try:
450 msg = TLSRecord(buf[i:])
451 msgs.append(msg)
452 except dpkt.NeedData:
453 break
454 else:
455 raise SSL3Exception('Bad TLS version in buf: %r' % buf[i:i + 5])
456 i += len(msg)
457 return msgs, i
458
459 _hexdecode = binascii.a2b_hex
463
464 """
465 Test basic TLS functionality.
466 Test that each TLSRecord is correctly discovered and added to TLS.records
467 """
468
469 @classmethod
471 cls.p = TLS(_hexdecode('1603000206010002020303585c2ff72a6599498771f59514f10af68c68f9ef30d0dadc9e1af64d1091476a000084c02bc02cc086c087c009c023c00ac024c072c073c008c007c02fc030c08ac08bc013c027c014c028c076c077c012c011009c009dc07ac07b002f003c0035003d004100ba008400c0000a00050004009e009fc07cc07d003300670039006b004500be008800c4001600a200a3c080c081003200400038006a004400bd008700c3001300660100015500050005010000000000000011000f00000c7777772e69616e612e6f7267ff0100010000230000000a000c000a00130015001700180019000b00020100000d001c001a0401040204030501050306010603030103020303020102020203001500f400f20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))
472
474 assert (len(self.p.records) == 1)
475
477 assert (self.p.records[0].type == 22)
478
480 assert (self.p.records[0].version == 768)
481
484
485 """
486 Test basic TLSRecord functionality
487 For this test, the contents of the record doesn't matter, since we're not parsing the next layer.
488 """
489
490 @classmethod
492
493 cls.p = TLSRecord(b'\x17\x03\x01\x00\x08abcdefghzzzzzzzzzzz')
494
496 assert (self.p.type == 23)
497
500
503
505 assert (self.p.data == b'abcdefgh')
506
508 assert (self.p.compressed == True)
509 assert (self.p.encrypted == True)
510
518
520
521 assert (len(self.p) == 13)
522
526
529
530 """It's just a byte. This will be quick, I promise"""
531
532 @classmethod
535
537 assert (self.p.type == 1)
538
540 assert (len(self.p) == 1)
541
544
545 """AppData is basically just a string"""
546
548 d = TLSAppData('abcdefgh')
549 assert (d == 'abcdefgh')
550
553 @classmethod
556
559
561 assert (self.h.length == 0x01)
562
566
569
570 """This data is extracted from and verified by Wireshark"""
571
572 @classmethod
574 cls.data = _hexdecode(
575 b"01000199"
576 b"0301"
577 b"5008220ce5e0e78b6891afe204498c9363feffbe03235a2d9e05b7d990eb708d"
578 b"2009bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed1"
579
580 b"005400ffc00ac0140088008700390038c00fc00500840035c007c009c011c0130045004400330032c00cc00ec002c0040096004100050004002fc008c01200160013c00dc003feff000ac006c010c00bc00100020001"
581 b"0100"
582
583 b"00fc0000000e000c0000096c6f63616c686f7374000a00080006001700180019000b00020100002300d0a50b2e9f618a9ea9bf493ef49b421835cd2f6b05bbe1179d8edf70d58c33d656e8696d36d7e7e0b9d3ecc0e4de339552fa06c64c0fcb550a334bc43944e2739ca342d15a9ebbe981ac87a0d38160507d47af09bdc16c5f0ee4cdceea551539382333226048a026d3a90a0535f4a64236467db8fee22b041af986ad0f253bc369137cd8d8cd061925461d7f4d7895ca9a4181ab554dad50360ac31860e971483877c9335ac1300c5e78f3e56f3b8e0fc16358fcaceefd5c8d8aaae7b35be116f8832856ca61144fcdd95e071b94d0cf7233740000"
584 b"FFFFFFFFFFFFFFFF")
585 cls.p = TLSHandshake(cls.data)
586
588 """Make sure the correct class was constructed"""
589
590 assert (isinstance(self.p.data, TLSClientHello) == True)
591
592
593
594
596 assert (self.p.data.random == _hexdecode(b'5008220ce5e0e78b6891afe204498c9363feffbe03235a2d9e05b7d990eb708d'))
597
599
600 assert (self.p.data.num_ciphersuites == 42)
601
602
604 assert (self.p.data.session_id == _hexdecode(b'09bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed1'))
605
607 assert (self.p.data.num_compression_methods == 1)
608
610 assert (len(self.p) == 413)
611
614
615 """Again, from Wireshark"""
616
617 @classmethod
619 cls.data = _hexdecode(
620 b'0200004d03015008220c8ec43c5462315a7c99f5d5b6bff009ad285b51dc18485f352e9fdecd2009bc0192e008e6fa8fe47998fca91311ba30ddde14a9587dc674b11c3d3e5ed10002000005ff01000100')
621 cls.p = TLSHandshake(cls.data)
622
625
626
627
628
630 assert (self.p.data.random == _hexdecode(b'5008220c8ec43c5462315a7c99f5d5b6bff009ad285b51dc18485f352e9fdecd'))
631
634
636 assert (len(self.p) == 81)
637
640
641 """We use a 2016 certificate record from iana.org as test data."""
642
643 @classmethod
645 cls.p = TLSHandshake(_hexdecode('0b000b45000b42000687308206833082056ba003020102021009cabbe2191c8f569dd4b6dd250f21d8300d06092a864886f70d01010b05003070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e636520536572766572204341301e170d3134313032373030303030305a170d3138303130333132303030305a3081a3310b3009060355040613025553311330110603550408130a43616c69666f726e6961311430120603550407130b4c6f7320416e67656c6573313c303a060355040a1333496e7465726e657420436f72706f726174696f6e20666f722041737369676e6564204e616d657320616e64204e756d6265727331163014060355040b130d4954204f7065726174696f6e733113301106035504030c0a2a2e69616e612e6f726730820222300d06092a864886f70d01010105000382020f003082020a02820201009dbdfddeb5cae53a559747e2fda63728e4aba60f18b79a69f03310bf0164e5ee7db6b15bf56df23fddbae6a1bb38449b8c883f18102bbd8bb655ac0e2dac2ee3ed5cf4315868d2c598068284854b24894dcd4bd37811f0ad3a282cd4b4e599ffd07d8d2d3f2478554f81020b320ee12f44948e2ea1edbc990b830ca5cca6b4a839fb27b51850c9847eac74f26609eb24365b9751fb1c3208f56913bacbcae49201347c78b7e54a9d99979404c37f00fb65db849fd75e3a68770c30f2abe65b33256fb59b450050b00d8139d4d80d36f7bc46daf303e48f0f0791b2fdd72ec60b2cb3ad533c3f288c9c194e49337a69c496731f086d4f1f9825900713e2a551d05cb6057567850d91e6001c4ce27176f0957873a95b880acbec19e7bd9bcf1286d0452b73789c41905dd470971cd73aea52c77b080cd779af58234f337225c26f87a8c13e2a65e9dd4e03a5b41d7e06b3353f38129b2327a531ec9627a21dc423733aa029d4989448ba3322891c1a5690ddf2d25c8ec8aaa894b14aa92130c6b6d969a21ff671b60c4c923a94a93ea1dd0492c93393ca6edd61f33ca77e9208d01d6bd15107662ec088733df4c876a7e1608b82973a0f7592e84ed15579d181e79024ae8a7e4b9f0078eb2005b23f9d09a1df1bbc7de2a5a6085a3646d9fadb0e9da273a5f403cdd42831ce6f0ca46889585602bb8bc36bb3be861ff6d1a62e350203010001a38201e3308201df301f0603551d230418301680145168ff90af0207753cccd9656462a212b859723b301d0603551d0e04160414c7d0acef898b20e4b914668933032394f6bf3a61301f0603551d1104183016820a2a2e69616e612e6f7267820869616e612e6f7267300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b0601050507030230750603551d1f046e306c3034a032a030862e687474703a2f2f63726c332e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c3034a032a030862e687474703a2f2f63726c342e64696769636572742e636f6d2f736861322d68612d7365727665722d67332e63726c30420603551d20043b3039303706096086480186fd6c0101302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f43505330818306082b0601050507010104773075302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304d06082b060105050730028641687474703a2f2f636163657274732e64696769636572742e636f6d2f446967694365727453484132486967684173737572616e636553657276657243412e637274300c0603551d130101ff04023000300d06092a864886f70d01010b0500038201010070314c38e7c02fd80810500b9df6dae85de9b23e29fbd68bfdb5f23411c89acfaf9ae05af9123a8aa6bce6954a4e68dc7cfc480a65d76f229c4bd5f5674b0c9ac6d06a37a1a1c145c3956120b8efe67c887ab4ff7d6aa950ff3698f27c4a19d59d93a39aca5a7b6d6c75e34974e50f5a590005b3cb665ddbd7074f9fcbcbf9c50228d5e25596b64ada160b48f77a93aaced22617bfe005e00fe20a532a0adcb818c878dc5d6649277777ca1a814e21d0b53308af4078be4554715e4ce4828b012f25ffa13a6ceb30d20a75deba8a344e41d627fa638feff38a3063a0187519b39b053f7134d9cd83e6091accf5d2e3a05edfa1dfbe181a87ad86ba24fe6b97fe0004b5308204b130820399a003020102021004e1e7a4dc5cf2f36dc02b42b85d159f300d06092a864886f70d01010b0500306c310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312b30290603550403132244696769436572742048696768204173737572616e636520455620526f6f74204341301e170d3133313032323132303030305a170d3238313032323132303030305a3070310b300906035504061302555331153013060355040a130c446967694365727420496e6331193017060355040b13107777772e64696769636572742e636f6d312f302d06035504031326446967694365727420534841322048696768204173737572616e63652053657276657220434130820122300d06092a864886f70d01010105000382010f003082010a0282010100b6e02fc22406c86d045fd7ef0a6406b27d22266516ae42409bcedc9f9f76073ec330558719b94f940e5a941f5556b4c2022aafd098ee0b40d7c4d03b72c8149eef90b111a9aed2c8b8433ad90b0bd5d595f540afc81ded4d9c5f57b786506899f58adad2c7051fa897c9dca4b182842dc6ada59cc71982a6850f5e44582a378ffd35f10b0827325af5bb8b9ea4bd51d027e2dd3b4233a30528c4bb28cc9aac2b230d78c67be65e71b74a3e08fb81b71616a19d23124de5d79208ac75a49cbacd17b21e4435657f532539d11c0a9a631b199274680a37c2c25248cb395aa2b6e15dc1dda020b821a293266f144a2141c7ed6d9bf2482ff303f5a26892532f5ee30203010001a38201493082014530120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020186301d0603551d250416301406082b0601050507030106082b06010505070302303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d304b0603551d1f044430423040a03ea03c863a687474703a2f2f63726c342e64696769636572742e636f6d2f4469676943657274486967684173737572616e63654556526f6f7443412e63726c303d0603551d200436303430320604551d2000302a302806082b06010505070201161c68747470733a2f2f7777772e64696769636572742e636f6d2f435053301d0603551d0e041604145168ff90af0207753cccd9656462a212b859723b301f0603551d23041830168014b13ec36903f8bf4701d498261a0802ef63642bc3300d06092a864886f70d01010b05000382010100188a958903e66ddf5cfc1d68ea4a8f83d6512f8d6b44169eac63f5d26e6c84998baa8171845bed344eb0b7799229cc2d806af08e20e179a4fe034713eaf586ca59717df404966bd359583dfed331255c183884a3e69f82fd8c5b98314ecd789e1afd85cb49aaf2278b9972fc3eaad5410bdad536a1bf1c6e47497f5ed9487c03d9fd8b49a098264240ebd69211a4640a5754c4f51dd6025e6baceec4809a1272fa5693d7ffbf30850630bf0b7f4eff57059d24ed85c32bfba675a8ac2d16ef7d7927b2ebc29d0b07eaaa85d301a3202841594328d281e3aaf6ec7b3b77b640628005414501ef17063edec0339b67d3612e7287e469fc120057401e70f51ec9b4'))
646
648 assert (len(self.p.data.certificates) == 2)
649
652
653 """Made up test data"""
654
655 @classmethod
657 cls.data = _hexdecode(b'1703010010'
658 b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
659 b'1703010010'
660 b'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
661 b'1703010010'
662 b'CCCCCCCC')
663 cls.msgs, cls.bytes_parsed = tls_multi_factory(cls.data)
664
666
667
668 assert (len(self.msgs) == 2)
669
671 assert (self.bytes_parsed == (5 + 16) * 2)
672
674 assert (self.msgs[0].data == _hexdecode(b'AA' * 16))
675
677 assert (self.msgs[1].data == _hexdecode(b'BB' * 16))
678