aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAyrx <terrycwk1994@gmail.com>2014-04-16 21:39:26 +0800
committerAyrx <terrycwk1994@gmail.com>2014-04-22 12:11:34 +0800
commitd53de818ac5abaa5c251d8d585b143555224bdb0 (patch)
tree77a7a7618a01f772596ed62b0bd1caa40377a71d
parent30752cdde9c149ede7c3eec5aea4e72944d99ac4 (diff)
downloadcryptography-d53de818ac5abaa5c251d8d585b143555224bdb0.tar.gz
cryptography-d53de818ac5abaa5c251d8d585b143555224bdb0.tar.bz2
cryptography-d53de818ac5abaa5c251d8d585b143555224bdb0.zip
OpenSSL backend's CMAC implementation
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py78
1 files changed, 76 insertions, 2 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 5e13bfc1..4054e56c 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -25,8 +25,8 @@ from cryptography.exceptions import (
UnsupportedAlgorithm, _Reasons
)
from cryptography.hazmat.backends.interfaces import (
- CipherBackend, DSABackend, HMACBackend, HashBackend, PBKDF2HMACBackend,
- RSABackend
+ CipherBackend, CMACBackend, DSABackend, HMACBackend, HashBackend,
+ PBKDF2HMACBackend, RSABackend
)
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import hashes, interfaces
@@ -47,6 +47,7 @@ _OpenSSLError = collections.namedtuple("_OpenSSLError",
@utils.register_interface(CipherBackend)
+@utils.register_interface(CMACBackend)
@utils.register_interface(DSABackend)
@utils.register_interface(HashBackend)
@utils.register_interface(HMACBackend)
@@ -554,6 +555,12 @@ class Backend(object):
return self._ffi.buffer(buf)[:res]
+ def cmac_supported(self):
+ return backend._lib.Cryptography_HAS_CMAC == 1
+
+ def create_cmac_ctx(self, algorithm):
+ return _CMACContext(self, algorithm)
+
class GetCipherByName(object):
def __init__(self, fmt):
@@ -1240,4 +1247,71 @@ class _RSAVerificationContext(object):
raise InvalidSignature
+@utils.register_interface(interfaces.CMACContext)
+class _CMACContext(object):
+ def __init__(self, backend, algorithm, ctx=None):
+
+ if not backend.cmac_supported():
+ raise UnsupportedAlgorithm("This backend does not support CMAC")
+
+ self._backend = backend
+ self._key = algorithm.key
+ self._algorithm = algorithm
+ self._output_length = algorithm.block_size // 8
+
+ if ctx is None:
+ registry = self._backend._cipher_registry
+ try:
+ adapter = registry[type(algorithm), CBC]
+ except KeyError:
+ raise UnsupportedAlgorithm(
+ "cipher {0} is not supported by this backend".format(
+ algorithm.name), _Reasons.UNSUPPORTED_CIPHER
+ )
+
+ evp_cipher = adapter(self._backend, algorithm, CBC)
+ if evp_cipher == self._backend._ffi.NULL:
+ raise UnsupportedAlgorithm(
+ "cipher {0} is not supported by this backend".format(
+ algorithm.name), _Reasons.UNSUPPORTED_CIPHER
+ )
+
+ ctx = self._backend._lib.CMAC_CTX_new()
+ self._backend._lib.CMAC_Init(
+ ctx, self._key, len(self._key),
+ evp_cipher, self._backend._ffi.NULL
+ )
+
+ self._ctx = ctx
+
+ def update(self, data):
+ res = self._backend._lib.CMAC_Update(self._ctx, data, len(data))
+ assert res == 1
+
+ def finalize(self):
+ buf = self._backend._ffi.new("unsigned char[]", self._output_length)
+ length = self._backend._ffi.new("size_t *", self._output_length)
+ res = self._backend._lib.CMAC_Final(
+ self._ctx, buf, length
+ )
+ assert res == 1
+
+ self._backend._lib.CMAC_CTX_free(self._ctx)
+ return self._backend._ffi.buffer(buf)[:]
+
+ def copy(self):
+ copied_ctx = self._backend._lib.CMAC_CTX_new()
+ self._backend._lib.CMAC_CTX_init(copied_ctx)
+ copied_ctx = self._backend._ffi.gc(
+ copied_ctx, self._backend._lib.CMAC_CTX_free()
+ )
+ res = self._backend._lib.CMAC_CTX_copy(
+ copied_ctx, self._ctx
+ )
+ assert res != 0
+ return _CMACContext(
+ self._backend, self.algorithm, ctx=copied_ctx
+ )
+
+
backend = Backend()