Skip to content

Commit 8a514e0

Browse files
committed
Added support for AES-CTR
1 parent c7125b0 commit 8a514e0

4 files changed

Lines changed: 42 additions & 11 deletions

File tree

tests/test_ciphers.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@
5151
from wolfcrypt.ciphers import (Ed448Private, Ed448Public)
5252

5353
from wolfcrypt.ciphers import (
54-
MODE_ECB, MODE_CBC, WolfCryptError
54+
MODE_CTR, MODE_ECB, MODE_CBC, WolfCryptError
5555
)
5656

5757

5858
@pytest.fixture
5959
def vectors():
60-
TestVector = namedtuple("TestVector", """key iv plaintext ciphertext raw_key
61-
pkcs8_key pem""")
60+
TestVector = namedtuple("TestVector", """key iv plaintext ciphertext
61+
ciphertext_ctr raw_key
62+
pkcs8_key pem""")
6263
TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields)
6364

6465
# test vector dictionary
@@ -69,7 +70,9 @@ def vectors():
6970
key="0123456789abcdef",
7071
iv="1234567890abcdef",
7172
plaintext=t2b("now is the time "),
72-
ciphertext=h2b("959492575f4281532ccc9d4677a233cb")
73+
ciphertext=h2b("959492575f4281532ccc9d4677a233cb"),
74+
#ciphertext_ctr = b'(u(\xdd\xf4\x84\xb1\x05]\xeb\xbeu\x1e\xb5+\x8a'
75+
ciphertext_ctr = h2b('287528ddf484b1055debbe751eb52b8a')
7376
)
7477
if _lib.CHACHA_ENABLED:
7578
vectorArray[ChaCha]=TestVector(
@@ -235,12 +238,12 @@ def cipher_new(cipher_cls, vectors):
235238
MODE_CBC,
236239
vectors[cipher_cls].iv)
237240

238-
239241
def test_block_cipher(cipher_cls, vectors):
240242
key = vectors[cipher_cls].key
241243
iv = vectors[cipher_cls].iv
242244
plaintext = vectors[cipher_cls].plaintext
243245
ciphertext = vectors[cipher_cls].ciphertext
246+
ciphertext_ctr = vectors[cipher_cls].ciphertext_ctr
244247

245248
with pytest.raises(ValueError):
246249
cipher_cls.new(key[:-1], MODE_CBC, iv) # invalid key length
@@ -257,11 +260,21 @@ def test_block_cipher(cipher_cls, vectors):
257260
with pytest.raises(ValueError):
258261
cipher_cls.new(key, MODE_CBC, iv[:-1]) # invalid iv length
259262

263+
264+
# Test AES in counter mode
265+
if ciphertext_ctr is not None:
266+
cipher_obj = cipher_cls.new(key, MODE_CTR, iv)
267+
res = cipher_obj.encrypt(plaintext)
268+
assert res == ciphertext_ctr
269+
cipher_obj = cipher_cls.new(key, MODE_CTR, iv)
270+
assert plaintext == cipher_obj.decrypt(res)
271+
260272
# single encryption
261273
cipher_obj = cipher_new(cipher_cls, vectors)
262274

263275
assert cipher_obj.encrypt(plaintext) == ciphertext
264276

277+
265278
# many encryptions
266279
cipher_obj = cipher_new(cipher_cls, vectors)
267280
result = t2b("")

wolfcrypt/_build_ffi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ def generate_libwolfssl():
320320
int wc_AesSetKey(Aes*, const byte*, word32, const byte*, int);
321321
int wc_AesCbcEncrypt(Aes*, byte*, const byte*, word32);
322322
int wc_AesCbcDecrypt(Aes*, byte*, const byte*, word32);
323+
int wc_AesCtrEncrypt(Aes*, byte*, const byte*, word32);
323324
"""
324325

325326
if CHACHA_ENABLED:

wolfcrypt/_build_wolfssl.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def make_flags(prefix):
184184

185185
# symmetric ciphers
186186
flags.append("--enable-aes")
187+
flags.append("--enable-aesctr")
187188
flags.append("--enable-des3")
188189
flags.append("--enable-chacha")
189190

wolfcrypt/ciphers.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,14 @@ def __init__(self, key, mode, IV=None):
9292
if mode not in _FEEDBACK_MODES:
9393
raise ValueError("this mode is not supported")
9494

95-
if mode == MODE_CBC:
95+
if mode == MODE_CBC or mode == MODE_CTR:
9696
if IV is None:
9797
raise ValueError("this mode requires an 'IV' string")
9898
else:
9999
raise ValueError("this mode is not supported by this cipher")
100100

101+
self.mode = mode
102+
101103
if self.key_size:
102104
if self.key_size != len(key):
103105
raise ValueError("key must be %d in length, not %d" %
@@ -218,17 +220,31 @@ def _set_key(self, direction):
218220
if direction == _ENCRYPTION:
219221
return _lib.wc_AesSetKey(
220222
self._enc, self._key, len(self._key), self._IV, _ENCRYPTION)
221-
223+
if self.mode == MODE_CTR:
224+
return _lib.wc_AesSetKey(
225+
self._dec, self._key, len(self._key), self._IV, _ENCRYPTION)
222226
return _lib.wc_AesSetKey(
223227
self._dec, self._key, len(self._key), self._IV, _DECRYPTION)
224228

225229
def _encrypt(self, destination, source):
226-
return _lib.wc_AesCbcEncrypt(self._enc, destination,
227-
source, len(source))
230+
if self.mode == MODE_CBC:
231+
return _lib.wc_AesCbcEncrypt(self._enc, destination,
232+
source, len(source))
233+
elif self.mode == MODE_CTR:
234+
return _lib.wc_AesCtrEncrypt(self._enc, destination,
235+
source, len(source))
236+
else:
237+
raise ValueError("Invalid mode associated to cipher")
228238

229239
def _decrypt(self, destination, source):
230-
return _lib.wc_AesCbcDecrypt(self._dec, destination,
231-
source, len(source))
240+
if self.mode == MODE_CBC:
241+
return _lib.wc_AesCbcDecrypt(self._dec, destination,
242+
source, len(source))
243+
elif self.mode == MODE_CTR:
244+
return _lib.wc_AesCtrEncrypt(self._dec, destination,
245+
source, len(source))
246+
else:
247+
raise ValueError("Invalid mode associated to cipher")
232248

233249
if _lib.CHACHA_ENABLED:
234250
class ChaCha(_Cipher):

0 commit comments

Comments
 (0)