1
2
3
4
5 """Implementation of the TLS Record Layer protocol"""
6
7 import socket
8 import errno
9 from .utils import tlshashlib as hashlib
10 from .constants import ContentType, CipherSuite
11 from .messages import RecordHeader3, RecordHeader2, Message
12 from .utils.cipherfactory import createAESGCM, createAES, createRC4, \
13 createTripleDES, createCHACHA20
14 from .utils.codec import Parser, Writer
15 from .utils.compat import compatHMAC
16 from .utils.cryptomath import getRandomBytes, MD5
17 from .utils.constanttime import ct_compare_digest, ct_check_cbc_mac_and_pad
18 from .errors import TLSRecordOverflow, TLSIllegalParameterException,\
19 TLSAbruptCloseError, TLSDecryptionFailed, TLSBadRecordMAC
20 from .mathtls import createMAC_SSL, createHMAC, PRF_SSL, PRF, PRF_1_2, \
21 PRF_1_2_SHA384
24
25 """Socket wrapper for reading and writing TLS Records"""
26
28 """
29 Assign socket to wrapper
30
31 @type sock: socket.socket
32 """
33 self.sock = sock
34 self.version = (0, 0)
35
37 """
38 Send all data through socket
39
40 @type data: bytearray
41 @param data: data to send
42 @raise socket.error: when write to socket failed
43 """
44 while 1:
45 try:
46 bytesSent = self.sock.send(data)
47 except socket.error as why:
48 if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
49 yield 1
50 continue
51 raise
52
53 if bytesSent == len(data):
54 return
55 data = data[bytesSent:]
56 yield 1
57
58 - def send(self, msg, padding=0):
59 """
60 Send the message through socket.
61
62 @type msg: bytearray
63 @param msg: TLS message to send
64 @type padding: int
65 @param padding: amount of padding to specify for SSLv2
66 @raise socket.error: when write to socket failed
67 """
68 data = msg.write()
69
70 if self.version in ((2, 0), (0, 2)):
71 header = RecordHeader2().create(len(data),
72 padding)
73 else:
74 header = RecordHeader3().create(self.version,
75 msg.contentType,
76 len(data))
77
78 data = header.write() + data
79
80 for result in self._sockSendAll(data):
81 yield result
82
84 """
85 Read exactly the amount of bytes specified in L{length} from raw socket.
86
87 @rtype: generator
88 @return: generator that will return 0 or 1 in case the socket is non
89 blocking and would block and bytearray in case the read finished
90 @raise TLSAbruptCloseError: when the socket closed
91 """
92 buf = bytearray(0)
93
94 if length == 0:
95 yield buf
96
97 while True:
98 try:
99 socketBytes = self.sock.recv(length - len(buf))
100 except socket.error as why:
101 if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
102 yield 0
103 continue
104 else:
105 raise
106
107
108 if len(socketBytes) == 0:
109 raise TLSAbruptCloseError()
110
111 buf += bytearray(socketBytes)
112 if len(buf) == length:
113 yield buf
114
116 """Read a single record header from socket"""
117
118 buf = bytearray(0)
119 ssl2 = False
120
121 result = None
122 for result in self._sockRecvAll(1):
123 if result in (0, 1):
124 yield result
125 else: break
126 assert result is not None
127
128 buf += result
129
130 if buf[0] in ContentType.all:
131 ssl2 = False
132
133 result = None
134 for result in self._sockRecvAll(4):
135 if result in (0, 1):
136 yield result
137 else: break
138 assert result is not None
139 buf += result
140 else:
141
142
143 ssl2 = True
144 if buf[0] & 0x80:
145 readLen = 1
146 else:
147 readLen = 2
148 result = None
149 for result in self._sockRecvAll(readLen):
150 if result in (0, 1):
151 yield result
152 else: break
153 assert result is not None
154 buf += result
155
156
157
158 if ssl2:
159 record = RecordHeader2().parse(Parser(buf))
160
161
162 if ((record.padding > record.length) or
163 (record.padding and record.length % 8)):
164 raise TLSIllegalParameterException(\
165 "Malformed record layer header")
166 else:
167 record = RecordHeader3().parse(Parser(buf))
168
169 yield record
170
172 """
173 Read a single record from socket, handle SSLv2 and SSLv3 record layer
174
175 @rtype: generator
176 @return: generator that returns 0 or 1 in case the read would be
177 blocking or a tuple containing record header (object) and record
178 data (bytearray) read from socket
179 @raise socket.error: In case of network error
180 @raise TLSAbruptCloseError: When the socket was closed on the other
181 side in middle of record receiving
182 @raise TLSRecordOverflow: When the received record was longer than
183 allowed by TLS
184 @raise TLSIllegalParameterException: When the record header was
185 malformed
186 """
187 record = None
188 for record in self._recvHeader():
189 if record in (0, 1):
190 yield record
191 else: break
192 assert record is not None
193
194
195
196
197 if record.length > 18432:
198 raise TLSRecordOverflow()
199
200
201 buf = bytearray(0)
202
203 result = None
204 for result in self._sockRecvAll(record.length):
205 if result in (0, 1):
206 yield result
207 else: break
208 assert result is not None
209
210 buf += result
211
212 yield (record, buf)
213
215
216 """Preserve the connection state for reading and writing data to records"""
217
219 """Create an instance with empty encryption and MACing contexts"""
220 self.macContext = None
221 self.encContext = None
222 self.fixedNonce = None
223 self.seqnum = 0
224
226 """Return encoded sequence number and increment it."""
227 writer = Writer()
228 writer.add(self.seqnum, 8)
229 self.seqnum += 1
230 return writer.bytes
231
233
234 """
235 Implementation of TLS record layer protocol
236
237 @ivar version: the TLS version to use (tuple encoded as on the wire)
238 @ivar sock: underlying socket
239 @ivar client: whether the connection should use encryption
240 @ivar encryptThenMAC: use the encrypt-then-MAC mechanism for record
241 integrity
242 @ivar handshake_finished: used in SSL2, True if handshake protocol is over
243 """
244
261
262 @property
264 """Return the size of block used by current symmetric cipher (R/O)"""
265 return self._writeState.encContext.block_size
266
267 @property
269 """Return the TLS version used by record layer"""
270 return self._version
271
272 @version.setter
274 """Set the TLS version used by record layer"""
275 self._version = val
276 self._recordSocket.version = val
277
279 """
280 Return the name of the bulk cipher used by this connection
281
282 @rtype: str
283 @return: The name of the cipher, like 'aes128', 'rc4', etc.
284 """
285 if self._writeState.encContext is None:
286 return None
287 return self._writeState.encContext.name
288
290 """
291 Return the name of the implementation used for the connection
292
293 'python' for tlslite internal implementation, 'openssl' for M2crypto
294 and 'pycrypto' for pycrypto
295 @rtype: str
296 @return: Name of cipher implementation used, None if not initialised
297 """
298 if self._writeState.encContext is None:
299 return None
300 return self._writeState.encContext.implementation
301
308
310 """Returns true if cipher uses CBC mode"""
311 if self._writeState and self._writeState.encContext and \
312 self._writeState.encContext.isBlockCipher:
313 return True
314 else:
315 return False
316
317
318
319
321 """Add padding to data so that it is multiple of block size"""
322 currentLength = len(data)
323 blockLength = self.blockSize
324 paddingLength = blockLength - 1 - (currentLength % blockLength)
325
326 paddingBytes = bytearray([paddingLength] * (paddingLength+1))
327 data += paddingBytes
328 return data
329
330 - def calculateMAC(self, mac, seqnumBytes, contentType, data):
342
344 """MAC, pad then encrypt data"""
345 if self._writeState.macContext:
346 seqnumBytes = self._writeState.getSeqNumBytes()
347 mac = self._writeState.macContext.copy()
348 macBytes = self.calculateMAC(mac, seqnumBytes, contentType, data)
349 data += macBytes
350
351
352 if self._writeState.encContext:
353
354 if self._writeState.encContext.isBlockCipher:
355
356
357 if self.version >= (3, 2):
358 data = self.fixedIVBlock + data
359
360 data = self.addPadding(data)
361
362
363 data = self._writeState.encContext.encrypt(data)
364
365 return data
366
368 """Pad, encrypt and then MAC the data"""
369 if self._writeState.encContext:
370
371 if self.version >= (3, 2):
372 buf = self.fixedIVBlock + buf
373
374 buf = self.addPadding(buf)
375
376 buf = self._writeState.encContext.encrypt(buf)
377
378
379 if self._writeState.macContext:
380 seqnumBytes = self._writeState.getSeqNumBytes()
381 mac = self._writeState.macContext.copy()
382
383
384 macBytes = self.calculateMAC(mac, seqnumBytes, contentType, buf)
385 buf += macBytes
386
387 return buf
388
389 @staticmethod
391 """Calculate a nonce for a given enc/dec context"""
392
393 if state.encContext.name == "chacha20-poly1305" and \
394 len(state.fixedNonce) == 12:
395
396 nonce = bytearray(i ^ j for i, j in zip(bytearray(4) + seqnum,
397 state.fixedNonce))
398 else:
399 nonce = state.fixedNonce + seqnum
400 return nonce
401
402
404 """Encrypt with AEAD cipher"""
405
406 seqNumBytes = self._writeState.getSeqNumBytes()
407 authData = seqNumBytes + bytearray([contentType,
408 self.version[0],
409 self.version[1],
410 len(buf)//256,
411 len(buf)%256])
412
413 nonce = self._getNonce(self._writeState, seqNumBytes)
414
415 assert len(nonce) == self._writeState.encContext.nonceLength
416
417 buf = self._writeState.encContext.seal(nonce, buf, authData)
418
419
420 if "aes" in self._writeState.encContext.name:
421 buf = seqNumBytes + buf
422
423 return buf
424
426 """Encrypt in SSL2 mode"""
427
428 seqnumBytes = self._writeState.getSeqNumBytes()
429
430 if (self._writeState.encContext and
431 self._writeState.encContext.isBlockCipher):
432 plaintext_len = len(data)
433 data = self.addPadding(data)
434 padding = len(data) - plaintext_len
435 else:
436 padding = 0
437
438 if self._writeState.macContext:
439 mac = self._writeState.macContext.copy()
440 mac.update(compatHMAC(data))
441 mac.update(compatHMAC(seqnumBytes[-4:]))
442
443 data = bytearray(mac.digest()) + data
444
445 if self._writeState.encContext:
446 data = self._writeState.encContext.encrypt(data)
447
448 return data, padding
449
451 """
452 Encrypt, MAC and send arbitrary message as-is through socket.
453
454 Note that if the message was not fragmented to below 2**14 bytes
455 it will be rejected by the other connection side.
456
457 @param msg: TLS message to send
458 @type msg: ApplicationData, HandshakeMessage, etc.
459 """
460 data = msg.write()
461 contentType = msg.contentType
462
463 padding = 0
464 if self.version in ((0, 2), (2, 0)):
465 data, padding = self._ssl2Encrypt(data)
466 elif self._writeState and \
467 self._writeState.encContext and \
468 self._writeState.encContext.isAEAD:
469 data = self._encryptThenSeal(data, contentType)
470 elif self.encryptThenMAC:
471 data = self._encryptThenMAC(data, contentType)
472 else:
473 data = self._macThenEncrypt(data, contentType)
474
475 encryptedMessage = Message(contentType, data)
476
477 for result in self._recordSocket.send(encryptedMessage, padding):
478 yield result
479
480
481
482
483
485 """Decrypt a stream cipher and check MAC"""
486 if self._readState.encContext:
487 assert self.version in ((3, 0), (3, 1), (3, 2), (3, 3))
488
489 data = self._readState.encContext.decrypt(data)
490
491 if self._readState.macContext:
492
493 macGood = True
494 macLength = self._readState.macContext.digest_size
495 endLength = macLength
496 if endLength > len(data):
497 macGood = False
498 else:
499
500 startIndex = len(data) - endLength
501 endIndex = startIndex + macLength
502 checkBytes = data[startIndex : endIndex]
503
504
505 seqnumBytes = self._readState.getSeqNumBytes()
506 data = data[:-endLength]
507 mac = self._readState.macContext.copy()
508 macBytes = self.calculateMAC(mac, seqnumBytes, recordType,
509 data)
510
511
512 if not ct_compare_digest(macBytes, checkBytes):
513 macGood = False
514
515 if not macGood:
516 raise TLSBadRecordMAC()
517
518 return data
519
520
522 """Decrypt data, check padding and MAC"""
523 if self._readState.encContext:
524 assert self.version in ((3, 0), (3, 1), (3, 2), (3, 3))
525 assert self._readState.encContext.isBlockCipher
526 assert self._readState.macContext
527
528
529
530
531 blockLength = self._readState.encContext.block_size
532 if len(data) % blockLength != 0:
533 raise TLSDecryptionFailed()
534 data = self._readState.encContext.decrypt(data)
535 if self.version >= (3, 2):
536 data = data[self._readState.encContext.block_size : ]
537
538
539
540
541 seqnumBytes = self._readState.getSeqNumBytes()
542
543 if not ct_check_cbc_mac_and_pad(data,
544 self._readState.macContext,
545 seqnumBytes,
546 recordType,
547 self.version):
548 raise TLSBadRecordMAC()
549
550
551
552
553
554 endLength = data[-1] + 1 + self._readState.macContext.digest_size
555
556 data = data[:-endLength]
557
558 return data
559
561 """
562 Check MAC of data, then decrypt and remove padding
563
564 @raise TLSBadRecordMAC: when the mac value is invalid
565 @raise TLSDecryptionFailed: when the data to decrypt has invalid size
566 """
567 if self._readState.macContext:
568 macLength = self._readState.macContext.digest_size
569 if len(buf) < macLength:
570 raise TLSBadRecordMAC("Truncated data")
571
572 checkBytes = buf[-macLength:]
573 buf = buf[:-macLength]
574
575 seqnumBytes = self._readState.getSeqNumBytes()
576 mac = self._readState.macContext.copy()
577
578 macBytes = self.calculateMAC(mac, seqnumBytes, recordType, buf)
579
580 if not ct_compare_digest(macBytes, checkBytes):
581 raise TLSBadRecordMAC("MAC mismatch")
582
583 if self._readState.encContext:
584 blockLength = self._readState.encContext.block_size
585 if len(buf) % blockLength != 0:
586 raise TLSDecryptionFailed("data length not multiple of "\
587 "block size")
588
589 buf = self._readState.encContext.decrypt(buf)
590
591
592 if self.version >= (3, 2):
593 buf = buf[blockLength:]
594
595 if len(buf) == 0:
596 raise TLSBadRecordMAC("No data left after IV removal")
597
598
599 paddingLength = buf[-1]
600 if paddingLength + 1 > len(buf):
601 raise TLSBadRecordMAC("Invalid padding length")
602
603 paddingGood = True
604 totalPaddingLength = paddingLength+1
605 if self.version != (3, 0):
606 paddingBytes = buf[-totalPaddingLength:-1]
607 for byte in paddingBytes:
608 if byte != paddingLength:
609 paddingGood = False
610
611 if not paddingGood:
612 raise TLSBadRecordMAC("Invalid padding byte values")
613
614
615 buf = buf[:-totalPaddingLength]
616
617 return buf
618
620 """Decrypt AEAD encrypted data"""
621 seqnumBytes = self._readState.getSeqNumBytes()
622
623 if "aes" in self._readState.encContext.name:
624 explicitNonceLength = 8
625 if explicitNonceLength > len(buf):
626
627 raise TLSBadRecordMAC("Truncated nonce")
628 nonce = self._readState.fixedNonce + buf[:explicitNonceLength]
629 buf = buf[8:]
630 else:
631 nonce = self._getNonce(self._readState, seqnumBytes)
632
633 if self._readState.encContext.tagLength > len(buf):
634
635 raise TLSBadRecordMAC("Truncated tag")
636
637 plaintextLen = len(buf) - self._readState.encContext.tagLength
638 authData = seqnumBytes + bytearray([recordType, self.version[0],
639 self.version[1],
640 plaintextLen//256,
641 plaintextLen%256])
642
643 buf = self._readState.encContext.open(nonce, buf, authData)
644 if buf is None:
645 raise TLSBadRecordMAC("Invalid tag, decryption failure")
646 return buf
647
649 """Decrypt SSL2 encrypted data"""
650
651 seqnumBytes = self._readState.getSeqNumBytes()
652
653
654
655
656 if self._readState.encContext:
657 if self._readState.encContext.isBlockCipher:
658 blockLength = self._readState.encContext.block_size
659 if len(data) % blockLength:
660 raise TLSDecryptionFailed()
661 data = self._readState.encContext.decrypt(data)
662
663
664
665
666 if self._readState.macContext:
667 macBytes = data[:16]
668 data = data[16:]
669
670 mac = self._readState.macContext.copy()
671 mac.update(compatHMAC(data))
672 mac.update(compatHMAC(seqnumBytes[-4:]))
673 calcMac = bytearray(mac.digest())
674 if macBytes != calcMac:
675 raise TLSBadRecordMAC()
676
677
678
679
680 if padding:
681 data = data[:-padding]
682 return data
683
685 """
686 Read, decrypt and check integrity of a single record
687
688 @rtype: tuple
689 @return: message header and decrypted message payload
690 @raise TLSDecryptionFailed: when decryption of data failed
691 @raise TLSBadRecordMAC: when record has bad MAC or padding
692 @raise socket.error: when reading from socket was unsuccessful
693 """
694 result = None
695 for result in self._recordSocket.recv():
696 if result in (0, 1):
697 yield result
698 else: break
699 assert result is not None
700
701 (header, data) = result
702
703 if isinstance(header, RecordHeader2):
704 data = self._decryptSSL2(data, header.padding)
705 if self.handshake_finished:
706 header.type = ContentType.application_data
707 elif self._readState and \
708 self._readState.encContext and \
709 self._readState.encContext.isAEAD:
710 data = self._decryptAndUnseal(header.type, data)
711 elif self.encryptThenMAC:
712 data = self._macThenDecrypt(header.type, data)
713 elif self._readState and \
714 self._readState.encContext and \
715 self._readState.encContext.isBlockCipher:
716 data = self._decryptThenMAC(header.type, data)
717 else:
718 data = self._decryptStreamThenMAC(header.type, data)
719
720
721 if len(data) > 2**14:
722 raise TLSRecordOverflow()
723
724 yield (header, Parser(data))
725
726
727
728
729
731 """
732 Change the cipher state to the pending one for write operations.
733
734 This should be done only once after a call to L{calcPendingStates} was
735 performed and directly after sending a L{ChangeCipherSpec} message.
736 """
737 if self.version in ((0, 2), (2, 0)):
738
739
740 self._pendingWriteState.seqnum = self._writeState.seqnum
741 self._writeState = self._pendingWriteState
742 self._pendingWriteState = ConnectionState()
743
745 """
746 Change the cipher state to the pending one for read operations.
747
748 This should be done only once after a call to L{calcPendingStates} was
749 performed and directly after receiving a L{ChangeCipherSpec} message.
750 """
751 if self.version in ((0, 2), (2, 0)):
752
753
754 self._pendingReadState.seqnum = self._readState.seqnum
755 self._readState = self._pendingReadState
756 self._pendingReadState = ConnectionState()
757
758 @staticmethod
801
802 @staticmethod
824
825 @staticmethod
827 """Get the HMAC method"""
828 assert version in ((3, 0), (3, 1), (3, 2), (3, 3))
829 if version == (3, 0):
830 createMACFunc = createMAC_SSL
831 elif version in ((3, 1), (3, 2), (3, 3)):
832 createMACFunc = createHMAC
833
834 return createMACFunc
835
836 - def _calcKeyBlock(self, cipherSuite, masterSecret, clientRandom,
837 serverRandom, outputLength):
838 """Calculate the overall key to slice up"""
839 if self.version == (3, 0):
840 keyBlock = PRF_SSL(masterSecret,
841 serverRandom + clientRandom,
842 outputLength)
843 elif self.version in ((3, 1), (3, 2)):
844 keyBlock = PRF(masterSecret,
845 b"key expansion",
846 serverRandom + clientRandom,
847 outputLength)
848 elif self.version == (3, 3):
849 if cipherSuite in CipherSuite.sha384PrfSuites:
850 keyBlock = PRF_1_2_SHA384(masterSecret,
851 b"key expansion",
852 serverRandom + clientRandom,
853 outputLength)
854 else:
855 keyBlock = PRF_1_2(masterSecret,
856 b"key expansion",
857 serverRandom + clientRandom,
858 outputLength)
859 else:
860 raise AssertionError()
861
862 return keyBlock
863
864 - def calcSSL2PendingStates(self, cipherSuite, masterSecret, clientRandom,
865 serverRandom, implementations):
866 """
867 Create the keys for encryption and decryption in SSLv2
868
869 While we could reuse calcPendingStates(), we need to provide the
870 key-arg data for the server that needs to be passed up to handshake
871 protocol.
872 """
873 if cipherSuite in CipherSuite.ssl2_128Key:
874 key_length = 16
875 elif cipherSuite in CipherSuite.ssl2_192Key:
876 key_length = 24
877 elif cipherSuite in CipherSuite.ssl2_64Key:
878 key_length = 8
879 else:
880 raise ValueError("Unknown cipher specified")
881
882 key_material = bytearray(key_length * 2)
883 md5_output_size = 16
884 for i, pos in enumerate(range(0, key_length * 2, md5_output_size)):
885 key_material[pos:pos+md5_output_size] = MD5(\
886 masterSecret +
887 bytearray(str(i), "ascii") +
888 clientRandom + serverRandom)
889
890 serverWriteKey = key_material[:key_length]
891 clientWriteKey = key_material[key_length:]
892
893
894
895
896
897
898
899
900
901 if cipherSuite not in CipherSuite.ssl2rc4:
902 iv = getRandomBytes(8)
903 else:
904 iv = bytearray(0)
905
906 clientPendingState = ConnectionState()
907 serverPendingState = ConnectionState()
908
909
910 clientPendingState.macContext = hashlib.md5()
911 clientPendingState.macContext.update(compatHMAC(clientWriteKey))
912 serverPendingState.macContext = hashlib.md5()
913 serverPendingState.macContext.update(compatHMAC(serverWriteKey))
914
915
916 if cipherSuite in CipherSuite.ssl2rc4:
917 cipherMethod = createRC4
918 elif cipherSuite in CipherSuite.ssl2_3des:
919 cipherMethod = createTripleDES
920 else:
921 raise NotImplementedError("Unknown cipher")
922
923 clientPendingState.encContext = cipherMethod(clientWriteKey, iv,
924 implementations)
925 serverPendingState.encContext = cipherMethod(serverWriteKey, iv,
926 implementations)
927
928
929 if self.client:
930 self._pendingWriteState = clientPendingState
931 self._pendingReadState = serverPendingState
932 else:
933 self._pendingWriteState = serverPendingState
934 self._pendingReadState = clientPendingState
935
936 return iv
937
938 - def calcPendingStates(self, cipherSuite, masterSecret, clientRandom,
939 serverRandom, implementations):
940 """Create pending states for encryption and decryption."""
941 keyLength, ivLength, createCipherFunc = \
942 self._getCipherSettings(cipherSuite)
943
944 macLength, digestmod = self._getMacSettings(cipherSuite)
945
946 if not digestmod:
947 createMACFunc = None
948 else:
949 createMACFunc = self._getHMACMethod(self.version)
950
951 outputLength = (macLength*2) + (keyLength*2) + (ivLength*2)
952
953
954 keyBlock = self._calcKeyBlock(cipherSuite, masterSecret, clientRandom,
955 serverRandom, outputLength)
956
957
958 clientPendingState = ConnectionState()
959 serverPendingState = ConnectionState()
960 parser = Parser(keyBlock)
961 clientMACBlock = parser.getFixBytes(macLength)
962 serverMACBlock = parser.getFixBytes(macLength)
963 clientKeyBlock = parser.getFixBytes(keyLength)
964 serverKeyBlock = parser.getFixBytes(keyLength)
965 clientIVBlock = parser.getFixBytes(ivLength)
966 serverIVBlock = parser.getFixBytes(ivLength)
967
968 if digestmod:
969
970 clientPendingState.macContext = createMACFunc(
971 compatHMAC(clientMACBlock), digestmod=digestmod)
972 serverPendingState.macContext = createMACFunc(
973 compatHMAC(serverMACBlock), digestmod=digestmod)
974 if createCipherFunc is not None:
975 clientPendingState.encContext = \
976 createCipherFunc(clientKeyBlock,
977 clientIVBlock,
978 implementations)
979 serverPendingState.encContext = \
980 createCipherFunc(serverKeyBlock,
981 serverIVBlock,
982 implementations)
983 else:
984
985 clientPendingState.macContext = None
986 serverPendingState.macContext = None
987 clientPendingState.encContext = createCipherFunc(clientKeyBlock,
988 implementations)
989 serverPendingState.encContext = createCipherFunc(serverKeyBlock,
990 implementations)
991 clientPendingState.fixedNonce = clientIVBlock
992 serverPendingState.fixedNonce = serverIVBlock
993
994
995 if self.client:
996 self._pendingWriteState = clientPendingState
997 self._pendingReadState = serverPendingState
998 else:
999 self._pendingWriteState = serverPendingState
1000 self._pendingReadState = clientPendingState
1001
1002 if self.version >= (3, 2) and ivLength:
1003
1004
1005 self.fixedIVBlock = getRandomBytes(ivLength)
1006