aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-05-20 23:10:08 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-05-20 23:10:08 -0500
commit336423ea730ae65a639c33b8b9cd7df75969ccce (patch)
tree02d4cb98ff879975eb566e1bbbd576b702b5a4fb
parentb8c6b4f5dda432b55e707c1903cbb4aaeef0c498 (diff)
downloadcryptography-336423ea730ae65a639c33b8b9cd7df75969ccce.tar.gz
cryptography-336423ea730ae65a639c33b8b9cd7df75969ccce.tar.bz2
cryptography-336423ea730ae65a639c33b8b9cd7df75969ccce.zip
add AES CTR support to OpenSSL 0.9.8
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py51
-rw-r--r--cryptography/hazmat/bindings/openssl/aes.py6
2 files changed, 55 insertions, 2 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 8853646a..d7110f81 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -132,6 +132,14 @@ class Backend(object):
return _HashContext(self, algorithm)
def cipher_supported(self, cipher, mode):
+ if self._cipher_supported(cipher, mode):
+ return True
+ elif isinstance(mode, CTR) and isinstance(cipher, AES):
+ return True
+ else:
+ return False
+
+ def _cipher_supported(self, cipher, mode):
try:
adapter = self._cipher_registry[type(cipher), type(mode)]
except KeyError:
@@ -198,10 +206,18 @@ class Backend(object):
)
def create_symmetric_encryption_ctx(self, cipher, mode):
- return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT)
+ if (isinstance(mode, CTR) and isinstance(cipher, AES)
+ and not self._cipher_supported(cipher, mode)):
+ return _AESCTRCipherContext(self, cipher, mode)
+ else:
+ return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT)
def create_symmetric_decryption_ctx(self, cipher, mode):
- return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT)
+ if (isinstance(mode, CTR) and isinstance(cipher, AES)
+ and not self._cipher_supported(cipher, mode)):
+ return _AESCTRCipherContext(self, cipher, mode)
+ else:
+ return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT)
def pbkdf2_hmac_supported(self, algorithm):
if self._lib.Cryptography_HAS_PBKDF2_HMAC:
@@ -834,6 +850,37 @@ class _CipherContext(object):
return self._tag
+@utils.register_interface(interfaces.CipherContext)
+class _AESCTRCipherContext(object):
+ def __init__(self, backend, cipher, mode):
+ self._backend = backend
+
+ self._key = self._backend._ffi.new("AES_KEY *")
+ assert self._key != self._backend._ffi.NULL
+ res = self._backend._lib.AES_set_encrypt_key(
+ cipher.key, len(cipher.key) * 8, self._key
+ )
+ assert res == 0
+ self._ecount = self._backend._ffi.new("char[]", 16)
+ self._nonce = self._backend._ffi.new("char[]", mode.nonce)
+ self._num = self._backend._ffi.new("unsigned int *", 0)
+
+ def update(self, data):
+ buf = self._backend._ffi.new("unsigned char[]", len(data))
+ self._backend._lib.AES_ctr128_encrypt(
+ data, buf, len(data), self._key, self._nonce,
+ self._ecount, self._num
+ )
+ return self._backend._ffi.buffer(buf)[:]
+
+ def finalize(self):
+ self._key = None
+ self._ecount = None
+ self._nonce = None
+ self._num = None
+ return b""
+
+
@utils.register_interface(interfaces.HashContext)
class _HashContext(object):
def __init__(self, backend, algorithm, ctx=None):
diff --git a/cryptography/hazmat/bindings/openssl/aes.py b/cryptography/hazmat/bindings/openssl/aes.py
index 17c154cf..b0e00721 100644
--- a/cryptography/hazmat/bindings/openssl/aes.py
+++ b/cryptography/hazmat/bindings/openssl/aes.py
@@ -29,6 +29,12 @@ typedef struct aes_key_st AES_KEY;
FUNCTIONS = """
int AES_set_encrypt_key(const unsigned char *, const int, AES_KEY *);
int AES_set_decrypt_key(const unsigned char *, const int, AES_KEY *);
+/* The ctr128_encrypt function is only useful in 0.9.8. You should use EVP for
+ this in 1.0.0+. */
+void AES_ctr128_encrypt(const unsigned char *, unsigned char *,
+ const unsigned long, const AES_KEY *,
+ unsigned char[], unsigned char[], unsigned int *);
+
"""
MACROS = """