diff options
-rw-r--r-- | CHANGELOG.rst | 2 | ||||
-rw-r--r-- | cryptography/hazmat/backends/multibackend.py | 20 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/evp.py | 11 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/x509.py | 44 | ||||
-rw-r--r-- | docs/hazmat/backends/openssl.rst | 2 | ||||
-rw-r--r-- | docs/hazmat/primitives/mac/cmac.rst | 4 | ||||
-rw-r--r-- | tests/hazmat/backends/test_multibackend.py | 34 |
7 files changed, 109 insertions, 8 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9e89e563..106e0ab2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,8 @@ Changelog to :class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS`. It will be removed from ``MGF1`` in two releases per our :doc:`/api-stability` policy. +* Added :class:`~cryptography.hazmat.primitives.cmac.CMAC`. + 0.3 - 2014-03-27 ~~~~~~~~~~~~~~~~ diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py index 86cded85..981a60bd 100644 --- a/cryptography/hazmat/backends/multibackend.py +++ b/cryptography/hazmat/backends/multibackend.py @@ -16,11 +16,12 @@ from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends.interfaces import ( - CipherBackend, DSABackend, HMACBackend, HashBackend, PBKDF2HMACBackend, - RSABackend + CMACBackend, CipherBackend, DSABackend, HMACBackend, HashBackend, + PBKDF2HMACBackend, RSABackend ) +@utils.register_interface(CMACBackend) @utils.register_interface(CipherBackend) @utils.register_interface(HashBackend) @utils.register_interface(HMACBackend) @@ -156,3 +157,18 @@ class MultiBackend(object): return b.generate_dsa_private_key(parameters) raise UnsupportedAlgorithm("DSA is not supported by the backend", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) + + def cmac_algorithm_supported(self, algorithm): + return any( + b.cmac_algorithm_supported(algorithm) + for b in self._filtered_backends(CMACBackend) + ) + + def create_cmac_ctx(self, algorithm): + for b in self._filtered_backends(CMACBackend): + try: + return b.create_cmac_ctx(algorithm) + except UnsupportedAlgorithm: + pass + raise UnsupportedAlgorithm("This backend does not support CMAC", + _Reasons.UNSUPPORTED_CIPHER) diff --git a/cryptography/hazmat/bindings/openssl/evp.py b/cryptography/hazmat/bindings/openssl/evp.py index 963537c8..b3d958e6 100644 --- a/cryptography/hazmat/bindings/openssl/evp.py +++ b/cryptography/hazmat/bindings/openssl/evp.py @@ -87,6 +87,8 @@ int EVP_PKEY_type(int); int EVP_PKEY_bits(EVP_PKEY *); int EVP_PKEY_size(EVP_PKEY *); RSA *EVP_PKEY_get1_RSA(EVP_PKEY *); +DSA *EVP_PKEY_get1_DSA(EVP_PKEY *); +DH *EVP_PKEY_get1_DH(EVP_PKEY *); int EVP_SignInit(EVP_MD_CTX *, const EVP_MD *); int EVP_SignUpdate(EVP_MD_CTX *, const void *, size_t); @@ -104,6 +106,7 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *, int, const unsigned char *, int, int, int EVP_PKEY_set1_RSA(EVP_PKEY *, struct rsa_st *); int EVP_PKEY_set1_DSA(EVP_PKEY *, struct dsa_st *); +int EVP_PKEY_set1_DH(EVP_PKEY *, DH *); int EVP_PKEY_get_attr_count(const EVP_PKEY *); int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *, int, int); @@ -123,7 +126,11 @@ MACROS = """ void OpenSSL_add_all_algorithms(void); int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *); int EVP_PKEY_assign_DSA(EVP_PKEY *, DSA *); + int EVP_PKEY_assign_EC_KEY(EVP_PKEY *, EC_KEY *); +EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *); +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *, EC_KEY *); + int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *); int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *, int, int, void *); @@ -215,6 +222,8 @@ int (*Cryptography_EVP_PKEY_decrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *, #endif #ifdef OPENSSL_NO_EC int (*EVP_PKEY_assign_EC_KEY)(EVP_PKEY *, EC_KEY *) = NULL; +EC_KEY *(*EVP_PKEY_get1_EC_KEY)(EVP_PKEY *) = NULL; +int (*EVP_PKEY_set1_EC_KEY)(EVP_PKEY *, EC_KEY *) = NULL; #endif """ @@ -245,5 +254,7 @@ CONDITIONAL_NAMES = { ], "Cryptography_HAS_EC": [ "EVP_PKEY_assign_EC_KEY", + "EVP_PKEY_get1_EC_KEY", + "EVP_PKEY_set1_EC_KEY", ] } diff --git a/cryptography/hazmat/bindings/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py index e800d272..92870369 100644 --- a/cryptography/hazmat/bindings/openssl/x509.py +++ b/cryptography/hazmat/bindings/openssl/x509.py @@ -160,6 +160,8 @@ X509_REQ *d2i_X509_REQ_bio(BIO *, X509_REQ **); int i2d_PrivateKey_bio(BIO *, EVP_PKEY *); EVP_PKEY *d2i_PrivateKey_bio(BIO *, EVP_PKEY **); +int i2d_PUBKEY_bio(BIO *, EVP_PKEY *); +EVP_PKEY *d2i_PUBKEY_bio(BIO *, EVP_PKEY **); ASN1_INTEGER *X509_get_serialNumber(X509 *); int X509_set_serialNumber(X509 *, ASN1_INTEGER *); @@ -178,6 +180,22 @@ const char *X509_get_default_cert_file(void); const char *X509_get_default_cert_dir_env(void); const char *X509_get_default_cert_file_env(void); const char *X509_get_default_private_dir(void); + +int i2d_RSA_PUBKEY(RSA *, unsigned char **); +RSA *d2i_RSA_PUBKEY(RSA **, const unsigned char **, long); +int i2d_DSA_PUBKEY(DSA *, unsigned char **); +DSA *d2i_DSA_PUBKEY(DSA **, const unsigned char **, long); + +RSA *d2i_RSAPrivateKey_bio(BIO *, RSA **); +int i2d_RSAPrivateKey_bio(BIO *, RSA *); +RSA *d2i_RSAPublicKey_bio(BIO *, RSA **); +int i2d_RSAPublicKey_bio(BIO *, RSA *); +RSA *d2i_RSA_PUBKEY_bio(BIO *, RSA **); +int i2d_RSA_PUBKEY_bio(BIO *, RSA *); +DSA *d2i_DSA_PUBKEY_bio(BIO *, DSA **); +int i2d_DSA_PUBKEY_bio(BIO *, DSA *); +DSA *d2i_DSAPrivateKey_bio(BIO *, DSA **); +int i2d_DSAPrivateKey_bio(BIO *, DSA *); """ MACROS = """ @@ -213,6 +231,13 @@ int X509_CRL_set_nextUpdate(X509_CRL *, ASN1_TIME *); RHEL/CentOS 5 we should move these back to FUNCTIONS. */ int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *); X509_EXTENSIONS *X509_REQ_get_extensions(X509_REQ *); + +int i2d_EC_PUBKEY(EC_KEY *, unsigned char **); +EC_KEY *d2i_EC_PUBKEY(EC_KEY **, const unsigned char **, long); +EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **); +int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *); +EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **); +int i2d_ECPrivateKey_bio(BIO *, EC_KEY *); """ CUSTOMIZATIONS = """ @@ -220,6 +245,23 @@ CUSTOMIZATIONS = """ #if OPENSSL_VERSION_NUMBER <= 0x0090805fL typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; #endif +#ifdef OPENSSL_NO_EC +int (*i2d_EC_PUBKEY)(EC_KEY *, unsigned char **) = NULL; +EC_KEY *(*d2i_EC_PUBKEY)(EC_KEY **, const unsigned char **, long) = NULL; +EC_KEY *(*d2i_EC_PUBKEY_bio)(BIO *, EC_KEY **) = NULL; +int (*i2d_EC_PUBKEY_bio)(BIO *, EC_KEY *) = NULL; +EC_KEY *(*d2i_ECPrivateKey_bio)(BIO *, EC_KEY **) = NULL; +int (*i2d_ECPrivateKey_bio)(BIO *, EC_KEY *) = NULL; +#endif """ -CONDITIONAL_NAMES = {} +CONDITIONAL_NAMES = { + "Cryptography_HAS_EC": [ + "i2d_EC_PUBKEY", + "d2i_EC_PUBKEY", + "d2i_EC_PUBKEY_bio", + "i2d_EC_PUBKEY_bio", + "d2i_ECPrivateKey_bio", + "i2d_ECPrivateKey_bio", + ] +} diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst index fdfadf0b..43e5d8f3 100644 --- a/docs/hazmat/backends/openssl.rst +++ b/docs/hazmat/backends/openssl.rst @@ -73,6 +73,6 @@ from the same pool as ``/dev/random``. .. _`OpenSSL`: https://www.openssl.org/ -.. _`initializing the RNG`: http://en.wikipedia.org/wiki/OpenSSL#Vulnerability_in_the_Debian_implementation +.. _`initializing the RNG`: https://en.wikipedia.org/wiki/OpenSSL#Predictable_keys_.28Debian-specific.29 .. _`Yarrow`: http://en.wikipedia.org/wiki/Yarrow_algorithm .. _`Microsoft documentation`: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379942(v=vs.85).aspx diff --git a/docs/hazmat/primitives/mac/cmac.rst b/docs/hazmat/primitives/mac/cmac.rst index 8b88a3ce..a6b048b5 100644 --- a/docs/hazmat/primitives/mac/cmac.rst +++ b/docs/hazmat/primitives/mac/cmac.rst @@ -19,10 +19,12 @@ A subset of CMAC with the AES-128 algorithm is described in :rfc:`4493`. .. class:: CMAC(algorithm, backend) + .. versionadded:: 0.4 + CMAC objects take a :class:`~cryptography.hazmat.primitives.interfaces.BlockCipherAlgorithm` provider. - .. code-block:: pycon + .. doctest:: >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import cmac diff --git a/tests/hazmat/backends/test_multibackend.py b/tests/hazmat/backends/test_multibackend.py index f46009d4..d8c09bd7 100644 --- a/tests/hazmat/backends/test_multibackend.py +++ b/tests/hazmat/backends/test_multibackend.py @@ -18,11 +18,11 @@ from cryptography.exceptions import ( UnsupportedAlgorithm, _Reasons ) from cryptography.hazmat.backends.interfaces import ( - CipherBackend, DSABackend, HMACBackend, HashBackend, PBKDF2HMACBackend, - RSABackend + CMACBackend, CipherBackend, DSABackend, HMACBackend, HashBackend, + PBKDF2HMACBackend, RSABackend ) from cryptography.hazmat.backends.multibackend import MultiBackend -from cryptography.hazmat.primitives import hashes, hmac +from cryptography.hazmat.primitives import cmac, hashes, hmac from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes @@ -108,6 +108,19 @@ class DummyDSABackend(object): pass +@utils.register_interface(CMACBackend) +class DummyCMACBackend(object): + def __init__(self, supported_algorithms): + self._algorithms = supported_algorithms + + def cmac_algorithm_supported(self, algorithm): + return type(algorithm) in self._algorithms + + def create_cmac_ctx(self, algorithm): + if not self.cmac_algorithm_supported(algorithm): + raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_CIPHER) + + class TestMultiBackend(object): def test_ciphers(self): backend = MultiBackend([ @@ -224,3 +237,18 @@ class TestMultiBackend(object): _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ): backend.generate_dsa_private_key(parameters) + + def test_cmac(self): + backend = MultiBackend([ + DummyCMACBackend([algorithms.AES]) + ]) + + fake_key = b"\x00" * 16 + + assert backend.cmac_algorithm_supported( + algorithms.AES(fake_key)) is True + + cmac.CMAC(algorithms.AES(fake_key), backend) + + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + cmac.CMAC(algorithms.TripleDES(fake_key), backend) |