diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2013-10-16 18:00:50 -0700 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2013-10-16 18:00:50 -0700 |
commit | 8ee102762525ff7619bc5b9c16f53f4c8537abfc (patch) | |
tree | 1b30ed1d1a45895c0f979c1869b9b6386213890c /cryptography | |
parent | 169dee88faa7c46b5551b89cf97a1b30c0a1c6ea (diff) | |
download | cryptography-8ee102762525ff7619bc5b9c16f53f4c8537abfc.tar.gz cryptography-8ee102762525ff7619bc5b9c16f53f4c8537abfc.tar.bz2 cryptography-8ee102762525ff7619bc5b9c16f53f4c8537abfc.zip |
Refactor how cipher names are computed
Diffstat (limited to 'cryptography')
-rw-r--r-- | cryptography/bindings/openssl/api.py | 52 | ||||
-rw-r--r-- | cryptography/primitives/block/base.py | 4 |
2 files changed, 45 insertions, 11 deletions
diff --git a/cryptography/bindings/openssl/api.py b/cryptography/bindings/openssl/api.py index f1a2c087..ced2cf89 100644 --- a/cryptography/bindings/openssl/api.py +++ b/cryptography/bindings/openssl/api.py @@ -13,11 +13,23 @@ from __future__ import absolute_import, division, print_function +import itertools import sys import cffi from cryptography.primitives import interfaces +from cryptography.primitives.block.ciphers import AES, Camellia +from cryptography.primitives.block.modes import CBC, ECB, OFB, CFB + + +class GetCipherByName(object): + def __init__(self, fmt): + self._fmt = fmt + + def __call__(self, api, cipher, mode): + cipher_name = self._fmt.format(cipher=cipher, mode=mode).lower() + return api.lib.EVP_get_cipherbyname(cipher_name) class API(object): @@ -78,6 +90,9 @@ class API(object): self.lib.OpenSSL_add_all_algorithms() self.lib.SSL_load_error_strings() + self._cipher_registry = {} + self._register_default_ciphers() + def openssl_version_text(self): """ Friendly string name of linked OpenSSL. @@ -86,20 +101,41 @@ class API(object): """ return self.ffi.string(self.lib.OPENSSL_VERSION_TEXT).decode("ascii") - def supports_cipher(self, ciphername): - return (self.ffi.NULL != - self.lib.EVP_get_cipherbyname(ciphername.encode("ascii"))) + def supports_cipher(self, cipher, mode): + try: + adapter = self._cipher_registry[type(cipher), type(mode)] + except KeyError: + return False + evp_cipher = adapter(self, cipher, mode) + return self.ffi.NULL != evp_cipher + + def register_cipher_adapter(self, cipher_cls, mode_cls, adapter): + if (cipher_cls, mode_cls) in self._cipher_registry: + raise ValueError("Duplicate registration for: {0} {1}".format( + cipher_cls, mode_cls) + ) + self._cipher_registry[cipher_cls, mode_cls] = adapter + + def _register_default_ciphers(self): + for cipher_cls, mode_cls in itertools.product( + [AES, Camellia], + [CBC, ECB, OFB, CFB], + ): + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName("{cipher.name}-{cipher.key_size}-{mode.name}") + ) def create_block_cipher_context(self, cipher, mode): ctx = self.ffi.new("EVP_CIPHER_CTX *") res = self.lib.EVP_CIPHER_CTX_init(ctx) assert res != 0 ctx = self.ffi.gc(ctx, self.lib.EVP_CIPHER_CTX_cleanup) - # TODO: compute name using a better algorithm - ciphername = "{0}-{1}-{2}".format( - cipher.name, cipher.key_size, mode.name - ).lower() - evp_cipher = self.lib.EVP_get_cipherbyname(ciphername.encode("ascii")) + evp_cipher = self._cipher_registry[type(cipher), type(mode)]( + self, cipher, mode + ) + assert evp_cipher != self.ffi.NULL if isinstance(mode, interfaces.ModeWithInitializationVector): iv_nonce = mode.initialization_vector diff --git a/cryptography/primitives/block/base.py b/cryptography/primitives/block/base.py index b84ca9c4..cb68361b 100644 --- a/cryptography/primitives/block/base.py +++ b/cryptography/primitives/block/base.py @@ -15,8 +15,6 @@ from __future__ import absolute_import, division, print_function from enum import Enum -from cryptography.bindings import _default_api - class _Operation(Enum): encrypt = 0 @@ -28,7 +26,7 @@ class BlockCipher(object): super(BlockCipher, self).__init__() if api is None: - api = _default_api + from cryptography.bindings import _default_api as api self.cipher = cipher self.mode = mode |