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
390 """Encrypt with AEAD cipher"""
391
392 seqNumBytes = self._writeState.getSeqNumBytes()
393 authData = seqNumBytes + bytearray([contentType,
394 self.version[0],
395 self.version[1],
396 len(buf)//256,
397 len(buf)%256])
398
399
400 nonce = self._writeState.fixedNonce + seqNumBytes
401
402 assert len(nonce) == self._writeState.encContext.nonceLength
403
404 buf = self._writeState.encContext.seal(nonce, buf, authData)
405
406
407 if "aes" in self._writeState.encContext.name:
408 buf = seqNumBytes + buf
409
410 return buf
411
413 """Encrypt in SSL2 mode"""
414
415 seqnumBytes = self._writeState.getSeqNumBytes()
416
417 if (self._writeState.encContext and
418 self._writeState.encContext.isBlockCipher):
419 plaintext_len = len(data)
420 data = self.addPadding(data)
421 padding = len(data) - plaintext_len
422 else:
423 padding = 0
424
425 if self._writeState.macContext:
426 mac = self._writeState.macContext.copy()
427 mac.update(compatHMAC(data))
428 mac.update(compatHMAC(seqnumBytes[-4:]))
429
430 data = bytearray(mac.digest()) + data
431
432 if self._writeState.encContext:
433 data = self._writeState.encContext.encrypt(data)
434
435 return data, padding
436
438 """
439 Encrypt, MAC and send arbitrary message as-is through socket.
440
441 Note that if the message was not fragmented to below 2**14 bytes
442 it will be rejected by the other connection side.
443
444 @param msg: TLS message to send
445 @type msg: ApplicationData, HandshakeMessage, etc.
446 """
447 data = msg.write()
448 contentType = msg.contentType
449
450 padding = 0
451 if self.version in ((0, 2), (2, 0)):
452 data, padding = self._ssl2Encrypt(data)
453 elif self._writeState and \
454 self._writeState.encContext and \
455 self._writeState.encContext.isAEAD:
456 data = self._encryptThenSeal(data, contentType)
457 elif self.encryptThenMAC:
458 data = self._encryptThenMAC(data, contentType)
459 else:
460 data = self._macThenEncrypt(data, contentType)
461
462 encryptedMessage = Message(contentType, data)
463
464 for result in self._recordSocket.send(encryptedMessage, padding):
465 yield result
466
467
468
469
470
472 """Decrypt a stream cipher and check MAC"""
473 if self._readState.encContext:
474 assert self.version in ((3, 0), (3, 1), (3, 2), (3, 3))
475
476 data = self._readState.encContext.decrypt(data)
477
478 if self._readState.macContext:
479
480 macGood = True
481 macLength = self._readState.macContext.digest_size
482 endLength = macLength
483 if endLength > len(data):
484 macGood = False
485 else:
486
487 startIndex = len(data) - endLength
488 endIndex = startIndex + macLength
489 checkBytes = data[startIndex : endIndex]
490
491
492 seqnumBytes = self._readState.getSeqNumBytes()
493 data = data[:-endLength]
494 mac = self._readState.macContext.copy()
495 macBytes = self.calculateMAC(mac, seqnumBytes, recordType,
496 data)
497
498
499 if not ct_compare_digest(macBytes, checkBytes):
500 macGood = False
501
502 if not macGood:
503 raise TLSBadRecordMAC()
504
505 return data
506
507
509 """Decrypt data, check padding and MAC"""
510 if self._readState.encContext:
511 assert self.version in ((3, 0), (3, 1), (3, 2), (3, 3))
512 assert self._readState.encContext.isBlockCipher
513 assert self._readState.macContext
514
515
516
517
518 blockLength = self._readState.encContext.block_size
519 if len(data) % blockLength != 0:
520 raise TLSDecryptionFailed()
521 data = self._readState.encContext.decrypt(data)
522 if self.version >= (3, 2):
523 data = data[self._readState.encContext.block_size : ]
524
525
526
527
528 seqnumBytes = self._readState.getSeqNumBytes()
529
530 if not ct_check_cbc_mac_and_pad(data,
531 self._readState.macContext,
532 seqnumBytes,
533 recordType,
534 self.version):
535 raise TLSBadRecordMAC()
536
537
538
539
540
541 endLength = data[-1] + 1 + self._readState.macContext.digest_size
542
543 data = data[:-endLength]
544
545 return data
546
548 """
549 Check MAC of data, then decrypt and remove padding
550
551 @raise TLSBadRecordMAC: when the mac value is invalid
552 @raise TLSDecryptionFailed: when the data to decrypt has invalid size
553 """
554 if self._readState.macContext:
555 macLength = self._readState.macContext.digest_size
556 if len(buf) < macLength:
557 raise TLSBadRecordMAC("Truncated data")
558
559 checkBytes = buf[-macLength:]
560 buf = buf[:-macLength]
561
562 seqnumBytes = self._readState.getSeqNumBytes()
563 mac = self._readState.macContext.copy()
564
565 macBytes = self.calculateMAC(mac, seqnumBytes, recordType, buf)
566
567 if not ct_compare_digest(macBytes, checkBytes):
568 raise TLSBadRecordMAC("MAC mismatch")
569
570 if self._readState.encContext:
571 blockLength = self._readState.encContext.block_size
572 if len(buf) % blockLength != 0:
573 raise TLSDecryptionFailed("data length not multiple of "\
574 "block size")
575
576 buf = self._readState.encContext.decrypt(buf)
577
578
579 if self.version >= (3, 2):
580 buf = buf[blockLength:]
581
582 if len(buf) == 0:
583 raise TLSBadRecordMAC("No data left after IV removal")
584
585
586 paddingLength = buf[-1]
587 if paddingLength + 1 > len(buf):
588 raise TLSBadRecordMAC("Invalid padding length")
589
590 paddingGood = True
591 totalPaddingLength = paddingLength+1
592 if self.version != (3, 0):
593 paddingBytes = buf[-totalPaddingLength:-1]
594 for byte in paddingBytes:
595 if byte != paddingLength:
596 paddingGood = False
597
598 if not paddingGood:
599 raise TLSBadRecordMAC("Invalid padding byte values")
600
601
602 buf = buf[:-totalPaddingLength]
603
604 return buf
605
607 """Decrypt AEAD encrypted data"""
608 seqnumBytes = self._readState.getSeqNumBytes()
609
610 if "aes" in self._readState.encContext.name:
611 explicitNonceLength = 8
612 if explicitNonceLength > len(buf):
613
614 raise TLSBadRecordMAC("Truncated nonce")
615 nonce = self._readState.fixedNonce + buf[:explicitNonceLength]
616 buf = buf[8:]
617 else:
618 nonce = self._readState.fixedNonce + seqnumBytes
619
620 if self._readState.encContext.tagLength > len(buf):
621
622 raise TLSBadRecordMAC("Truncated tag")
623
624 plaintextLen = len(buf) - self._readState.encContext.tagLength
625 authData = seqnumBytes + bytearray([recordType, self.version[0],
626 self.version[1],
627 plaintextLen//256,
628 plaintextLen%256])
629
630 buf = self._readState.encContext.open(nonce, buf, authData)
631 if buf is None:
632 raise TLSBadRecordMAC("Invalid tag, decryption failure")
633 return buf
634
636 """Decrypt SSL2 encrypted data"""
637
638 seqnumBytes = self._readState.getSeqNumBytes()
639
640
641
642
643 if self._readState.encContext:
644 if self._readState.encContext.isBlockCipher:
645 blockLength = self._readState.encContext.block_size
646 if len(data) % blockLength:
647 raise TLSDecryptionFailed()
648 data = self._readState.encContext.decrypt(data)
649
650
651
652
653 if self._readState.macContext:
654 macBytes = data[:16]
655 data = data[16:]
656
657 mac = self._readState.macContext.copy()
658 mac.update(compatHMAC(data))
659 mac.update(compatHMAC(seqnumBytes[-4:]))
660 calcMac = bytearray(mac.digest())
661 if macBytes != calcMac:
662 raise TLSBadRecordMAC()
663
664
665
666
667 if padding:
668 data = data[:-padding]
669 return data
670
672 """
673 Read, decrypt and check integrity of a single record
674
675 @rtype: tuple
676 @return: message header and decrypted message payload
677 @raise TLSDecryptionFailed: when decryption of data failed
678 @raise TLSBadRecordMAC: when record has bad MAC or padding
679 @raise socket.error: when reading from socket was unsuccessful
680 """
681 result = None
682 for result in self._recordSocket.recv():
683 if result in (0, 1):
684 yield result
685 else: break
686 assert result is not None
687
688 (header, data) = result
689
690 if isinstance(header, RecordHeader2):
691 data = self._decryptSSL2(data, header.padding)
692 if self.handshake_finished:
693 header.type = ContentType.application_data
694 elif self._readState and \
695 self._readState.encContext and \
696 self._readState.encContext.isAEAD:
697 data = self._decryptAndUnseal(header.type, data)
698 elif self.encryptThenMAC:
699 data = self._macThenDecrypt(header.type, data)
700 elif self._readState and \
701 self._readState.encContext and \
702 self._readState.encContext.isBlockCipher:
703 data = self._decryptThenMAC(header.type, data)
704 else:
705 data = self._decryptStreamThenMAC(header.type, data)
706
707 yield (header, Parser(data))
708
709
710
711
712
714 """
715 Change the cipher state to the pending one for write operations.
716
717 This should be done only once after a call to L{calcPendingStates} was
718 performed and directly after sending a L{ChangeCipherSpec} message.
719 """
720 if self.version in ((0, 2), (2, 0)):
721
722
723 self._pendingWriteState.seqnum = self._writeState.seqnum
724 self._writeState = self._pendingWriteState
725 self._pendingWriteState = ConnectionState()
726
728 """
729 Change the cipher state to the pending one for read operations.
730
731 This should be done only once after a call to L{calcPendingStates} was
732 performed and directly after receiving a L{ChangeCipherSpec} message.
733 """
734 if self.version in ((0, 2), (2, 0)):
735
736
737 self._pendingReadState.seqnum = self._readState.seqnum
738 self._readState = self._pendingReadState
739 self._pendingReadState = ConnectionState()
740
741 @staticmethod
780
781 @staticmethod
800
801 @staticmethod
803 """Get the HMAC method"""
804 assert version in ((3, 0), (3, 1), (3, 2), (3, 3))
805 if version == (3, 0):
806 createMACFunc = createMAC_SSL
807 elif version in ((3, 1), (3, 2), (3, 3)):
808 createMACFunc = createHMAC
809
810 return createMACFunc
811
812 - def _calcKeyBlock(self, cipherSuite, masterSecret, clientRandom,
813 serverRandom, outputLength):
814 """Calculate the overall key to slice up"""
815 if self.version == (3, 0):
816 keyBlock = PRF_SSL(masterSecret,
817 serverRandom + clientRandom,
818 outputLength)
819 elif self.version in ((3, 1), (3, 2)):
820 keyBlock = PRF(masterSecret,
821 b"key expansion",
822 serverRandom + clientRandom,
823 outputLength)
824 elif self.version == (3, 3):
825 if cipherSuite in CipherSuite.sha384PrfSuites:
826 keyBlock = PRF_1_2_SHA384(masterSecret,
827 b"key expansion",
828 serverRandom + clientRandom,
829 outputLength)
830 else:
831 keyBlock = PRF_1_2(masterSecret,
832 b"key expansion",
833 serverRandom + clientRandom,
834 outputLength)
835 else:
836 raise AssertionError()
837
838 return keyBlock
839
840 - def calcSSL2PendingStates(self, cipherSuite, masterSecret, clientRandom,
841 serverRandom, implementations):
842 """
843 Create the keys for encryption and decryption in SSLv2
844
845 While we could reuse calcPendingStates(), we need to provide the
846 key-arg data for the server that needs to be passed up to handshake
847 protocol.
848 """
849 if cipherSuite in CipherSuite.ssl2_128Key:
850 key_length = 16
851 elif cipherSuite in CipherSuite.ssl2_192Key:
852 key_length = 24
853 elif cipherSuite in CipherSuite.ssl2_64Key:
854 key_length = 8
855 else:
856 raise ValueError("Unknown cipher specified")
857
858 key_material = bytearray(key_length * 2)
859 md5_output_size = 16
860 for i, pos in enumerate(range(0, key_length * 2, md5_output_size)):
861 key_material[pos:pos+md5_output_size] = MD5(\
862 masterSecret +
863 bytearray(str(i), "ascii") +
864 clientRandom + serverRandom)
865
866 serverWriteKey = key_material[:key_length]
867 clientWriteKey = key_material[key_length:]
868
869
870
871
872
873
874
875
876
877 if cipherSuite not in CipherSuite.ssl2rc4:
878 iv = getRandomBytes(8)
879 else:
880 iv = bytearray(0)
881
882 clientPendingState = ConnectionState()
883 serverPendingState = ConnectionState()
884
885
886 clientPendingState.macContext = hashlib.md5()
887 clientPendingState.macContext.update(compatHMAC(clientWriteKey))
888 serverPendingState.macContext = hashlib.md5()
889 serverPendingState.macContext.update(compatHMAC(serverWriteKey))
890
891
892 if cipherSuite in CipherSuite.ssl2rc4:
893 cipherMethod = createRC4
894 elif cipherSuite in CipherSuite.ssl2_3des:
895 cipherMethod = createTripleDES
896 else:
897 raise NotImplementedError("Unknown cipher")
898
899 clientPendingState.encContext = cipherMethod(clientWriteKey, iv,
900 implementations)
901 serverPendingState.encContext = cipherMethod(serverWriteKey, iv,
902 implementations)
903
904
905 if self.client:
906 self._pendingWriteState = clientPendingState
907 self._pendingReadState = serverPendingState
908 else:
909 self._pendingWriteState = serverPendingState
910 self._pendingReadState = clientPendingState
911
912 return iv
913
914 - def calcPendingStates(self, cipherSuite, masterSecret, clientRandom,
915 serverRandom, implementations):
916 """Create pending states for encryption and decryption."""
917 keyLength, ivLength, createCipherFunc = \
918 self._getCipherSettings(cipherSuite)
919
920 macLength, digestmod = self._getMacSettings(cipherSuite)
921
922 if not digestmod:
923 createMACFunc = None
924 else:
925 createMACFunc = self._getHMACMethod(self.version)
926
927 outputLength = (macLength*2) + (keyLength*2) + (ivLength*2)
928
929
930 keyBlock = self._calcKeyBlock(cipherSuite, masterSecret, clientRandom,
931 serverRandom, outputLength)
932
933
934 clientPendingState = ConnectionState()
935 serverPendingState = ConnectionState()
936 parser = Parser(keyBlock)
937 clientMACBlock = parser.getFixBytes(macLength)
938 serverMACBlock = parser.getFixBytes(macLength)
939 clientKeyBlock = parser.getFixBytes(keyLength)
940 serverKeyBlock = parser.getFixBytes(keyLength)
941 clientIVBlock = parser.getFixBytes(ivLength)
942 serverIVBlock = parser.getFixBytes(ivLength)
943
944 if digestmod:
945
946 clientPendingState.macContext = createMACFunc(
947 compatHMAC(clientMACBlock), digestmod=digestmod)
948 serverPendingState.macContext = createMACFunc(
949 compatHMAC(serverMACBlock), digestmod=digestmod)
950 if createCipherFunc is not None:
951 clientPendingState.encContext = \
952 createCipherFunc(clientKeyBlock,
953 clientIVBlock,
954 implementations)
955 serverPendingState.encContext = \
956 createCipherFunc(serverKeyBlock,
957 serverIVBlock,
958 implementations)
959 else:
960
961 clientPendingState.macContext = None
962 serverPendingState.macContext = None
963 clientPendingState.encContext = createCipherFunc(clientKeyBlock,
964 implementations)
965 serverPendingState.encContext = createCipherFunc(serverKeyBlock,
966 implementations)
967 clientPendingState.fixedNonce = clientIVBlock
968 serverPendingState.fixedNonce = serverIVBlock
969
970
971 if self.client:
972 self._pendingWriteState = clientPendingState
973 self._pendingReadState = serverPendingState
974 else:
975 self._pendingWriteState = serverPendingState
976 self._pendingReadState = clientPendingState
977
978 if self.version >= (3, 2) and ivLength:
979
980
981 self.fixedIVBlock = getRandomBytes(ivLength)
982