Skip to content

Commit 41e1631

Browse files
committed
Streamline M2Crypto 3DES IV handling
M2Crypto defaults to padding the ciphertext, and the previous implementation danced around that awkwardly by padding and unpadding ciphertext on decryption and updating the IV manually. `m2.cipher_set_padding(context, 0)` allows to shoulder the IV handling back to where it belongs and to get rid of unnecessary context reinitializations. (Investigative work courtesy of @tomato42: #377 (review))
1 parent adefcaf commit 41e1631

File tree

2 files changed

+14
-23
lines changed

2 files changed

+14
-23
lines changed

tlslite/utils/openssl_tripledes.py

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,24 @@ class OpenSSL_TripleDES(TripleDES):
1515

1616
def __init__(self, key, mode, IV):
1717
TripleDES.__init__(self, key, mode, IV, "openssl")
18-
self.key = key
19-
self.IV = IV
20-
21-
def _createContext(self, encrypt):
22-
context = m2.cipher_ctx_new()
2318
cipherType = m2.des_ede3_cbc()
24-
m2.cipher_init(context, cipherType, self.key, self.IV, encrypt)
25-
return context
19+
self.encrypt_context = m2.cipher_ctx_new()
20+
self.decrypt_context = m2.cipher_ctx_new()
21+
m2.cipher_init(self.encrypt_context, cipherType, key, IV, 1)
22+
m2.cipher_init(self.decrypt_context, cipherType, key, IV, 0)
23+
m2.cipher_set_padding(self.encrypt_context, 0)
24+
m2.cipher_set_padding(self.decrypt_context, 0)
2625

2726
def encrypt(self, plaintext):
2827
TripleDES.encrypt(self, plaintext)
29-
context = self._createContext(1)
30-
ciphertext = m2.cipher_update(context, plaintext)
31-
m2.cipher_ctx_free(context)
32-
self.IV = ciphertext[-self.block_size:]
28+
ciphertext = m2.cipher_update(self.encrypt_context, plaintext)
3329
return bytearray(ciphertext)
3430

3531
def decrypt(self, ciphertext):
3632
TripleDES.decrypt(self, ciphertext)
37-
context = self._createContext(0)
38-
#I think M2Crypto has a bug - it fails to decrypt and return the last block passed in.
39-
#To work around this, we append sixteen zeros to the string, below:
40-
plaintext = m2.cipher_update(context, ciphertext+(b'\0'*16))
41-
42-
#If this bug is ever fixed, then plaintext will end up having a garbage
43-
#plaintext block on the end. That's okay - the below code will ignore it.
44-
plaintext = plaintext[:len(ciphertext)]
45-
m2.cipher_ctx_free(context)
46-
self.IV = ciphertext[-self.block_size:]
33+
plaintext = m2.cipher_update(self.decrypt_context, ciphertext)
4734
return bytearray(plaintext)
35+
36+
def __del__(self):
37+
m2.cipher_ctx_free(self.encrypt_context)
38+
m2.cipher_ctx_free(self.decrypt_context)

unit_tests/test_tlslite_utils_tripledes_split.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class TestTripleDES(unittest.TestCase):
2727
_given = given(binary(min_size=24, max_size=24), # key
2828
binary(min_size=8, max_size=8), # iv
2929
binary(min_size=13*8, max_size=13*8), # plaintext
30-
(tuples(integers(1, 12), integers(1, 12)) # split points
31-
.filter(lambda split_pts: split_pts[0] < split_pts[1])
30+
(tuples(integers(0, 13), integers(0, 13)) # split points
31+
.filter(lambda split_pts: split_pts[0] <= split_pts[1])
3232
.map(lambda lengths: [i * 8 for i in lengths])))
3333

3434
def split_test(self, key, iv, plaintext, split_points, make_impl=py_3des):

0 commit comments

Comments
 (0)