aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography/hazmat
diff options
context:
space:
mode:
Diffstat (limited to 'cryptography/hazmat')
-rw-r--r--cryptography/hazmat/__init__.py2
-rw-r--r--cryptography/hazmat/backends/__init__.py35
-rw-r--r--cryptography/hazmat/backends/commoncrypto/__init__.py2
-rw-r--r--cryptography/hazmat/backends/commoncrypto/backend.py22
-rw-r--r--cryptography/hazmat/backends/interfaces.py6
-rw-r--r--cryptography/hazmat/backends/multibackend.py43
-rw-r--r--cryptography/hazmat/backends/openssl/__init__.py2
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py408
-rw-r--r--cryptography/hazmat/bindings/__init__.py2
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/__init__.py2
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/binding.py4
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/common_cryptor.py2
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/common_digest.py2
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/common_hmac.py2
-rw-r--r--cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/__init__.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/aes.py30
-rw-r--r--cryptography/hazmat/bindings/openssl/asn1.py7
-rw-r--r--cryptography/hazmat/bindings/openssl/bignum.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/binding.py1
-rw-r--r--cryptography/hazmat/bindings/openssl/bio.py7
-rw-r--r--cryptography/hazmat/bindings/openssl/conf.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/crypto.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/dh.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/dsa.py5
-rw-r--r--cryptography/hazmat/bindings/openssl/ec.py23
-rw-r--r--cryptography/hazmat/bindings/openssl/ecdsa.py130
-rw-r--r--cryptography/hazmat/bindings/openssl/engine.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/err.py69
-rw-r--r--cryptography/hazmat/bindings/openssl/evp.py50
-rw-r--r--cryptography/hazmat/bindings/openssl/hmac.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/nid.py165
-rw-r--r--cryptography/hazmat/bindings/openssl/objects.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/opensslv.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/osrandom_engine.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/pem.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/pkcs12.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/pkcs7.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/rand.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/rsa.py13
-rw-r--r--cryptography/hazmat/bindings/openssl/ssl.py316
-rw-r--r--cryptography/hazmat/bindings/openssl/x509.py13
-rw-r--r--cryptography/hazmat/bindings/openssl/x509name.py2
-rw-r--r--cryptography/hazmat/bindings/openssl/x509v3.py2
-rw-r--r--cryptography/hazmat/bindings/utils.py38
-rw-r--r--cryptography/hazmat/primitives/__init__.py14
-rw-r--r--cryptography/hazmat/primitives/asymmetric/__init__.py14
-rw-r--r--cryptography/hazmat/primitives/asymmetric/dsa.py142
-rw-r--r--cryptography/hazmat/primitives/asymmetric/padding.py29
-rw-r--r--cryptography/hazmat/primitives/asymmetric/rsa.py33
-rw-r--r--cryptography/hazmat/primitives/ciphers/algorithms.py14
-rw-r--r--cryptography/hazmat/primitives/ciphers/base.py10
-rw-r--r--cryptography/hazmat/primitives/constant_time.py20
-rw-r--r--cryptography/hazmat/primitives/hashes.py11
-rw-r--r--cryptography/hazmat/primitives/hmac.py11
-rw-r--r--cryptography/hazmat/primitives/interfaces.py98
-rw-r--r--cryptography/hazmat/primitives/kdf/__init__.py14
-rw-r--r--cryptography/hazmat/primitives/kdf/hkdf.py13
-rw-r--r--cryptography/hazmat/primitives/kdf/pbkdf2.py12
-rw-r--r--cryptography/hazmat/primitives/padding.py22
-rw-r--r--cryptography/hazmat/primitives/twofactor/__init__.py14
-rw-r--r--cryptography/hazmat/primitives/twofactor/hotp.py17
-rw-r--r--cryptography/hazmat/primitives/twofactor/totp.py11
63 files changed, 1674 insertions, 260 deletions
diff --git a/cryptography/hazmat/__init__.py b/cryptography/hazmat/__init__.py
index 55c925c6..2f420574 100644
--- a/cryptography/hazmat/__init__.py
+++ b/cryptography/hazmat/__init__.py
@@ -10,3 +10,5 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/backends/__init__.py b/cryptography/hazmat/backends/__init__.py
index 41d260a8..ae78822c 100644
--- a/cryptography/hazmat/backends/__init__.py
+++ b/cryptography/hazmat/backends/__init__.py
@@ -11,21 +11,44 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from cryptography.hazmat.backends import openssl
+from __future__ import absolute_import, division, print_function
+
from cryptography.hazmat.backends.multibackend import MultiBackend
from cryptography.hazmat.bindings.commoncrypto.binding import (
Binding as CommonCryptoBinding
)
+from cryptography.hazmat.bindings.openssl.binding import (
+ Binding as OpenSSLBinding
+)
+
+
+_available_backends_list = None
+
-_ALL_BACKENDS = [openssl.backend]
+def _available_backends():
+ global _available_backends_list
-if CommonCryptoBinding.is_available():
- from cryptography.hazmat.backends import commoncrypto
- _ALL_BACKENDS.append(commoncrypto.backend)
+ if _available_backends_list is None:
+ _available_backends_list = []
+ if CommonCryptoBinding.is_available():
+ from cryptography.hazmat.backends import commoncrypto
+ _available_backends_list.append(commoncrypto.backend)
-_default_backend = MultiBackend(_ALL_BACKENDS)
+ if OpenSSLBinding.is_available():
+ from cryptography.hazmat.backends import openssl
+ _available_backends_list.append(openssl.backend)
+
+ return _available_backends_list
+
+
+_default_backend = None
def default_backend():
+ global _default_backend
+
+ if _default_backend is None:
+ _default_backend = MultiBackend(_available_backends())
+
return _default_backend
diff --git a/cryptography/hazmat/backends/commoncrypto/__init__.py b/cryptography/hazmat/backends/commoncrypto/__init__.py
index 64a1c01c..f080394f 100644
--- a/cryptography/hazmat/backends/commoncrypto/__init__.py
+++ b/cryptography/hazmat/backends/commoncrypto/__init__.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
from cryptography.hazmat.backends.commoncrypto.backend import backend
diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py
index 4a451d34..4faca73e 100644
--- a/cryptography/hazmat/backends/commoncrypto/backend.py
+++ b/cryptography/hazmat/backends/commoncrypto/backend.py
@@ -17,18 +17,18 @@ from collections import namedtuple
from cryptography import utils
from cryptography.exceptions import (
- UnsupportedAlgorithm, InvalidTag, InternalError
+ InternalError, InvalidTag, UnsupportedAlgorithm, _Reasons
)
from cryptography.hazmat.backends.interfaces import (
- HashBackend, HMACBackend, CipherBackend, PBKDF2HMACBackend
+ CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend
)
from cryptography.hazmat.bindings.commoncrypto.binding import Binding
-from cryptography.hazmat.primitives import interfaces, constant_time
+from cryptography.hazmat.primitives import constant_time, interfaces
from cryptography.hazmat.primitives.ciphers.algorithms import (
- AES, Blowfish, TripleDES, ARC4, CAST5
+ AES, ARC4, Blowfish, CAST5, TripleDES
)
from cryptography.hazmat.primitives.ciphers.modes import (
- CBC, CTR, ECB, OFB, CFB, GCM
+ CBC, CFB, CTR, ECB, GCM, OFB
)
@@ -276,7 +276,8 @@ class _CipherContext(object):
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported "
"by this backend".format(
- cipher.name, mode.name if mode else mode)
+ cipher.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
)
ctx = self._backend._ffi.new("CCCryptorRef *")
@@ -349,7 +350,8 @@ class _GCMCipherContext(object):
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported "
"by this backend".format(
- cipher.name, mode.name if mode else mode)
+ cipher.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
)
ctx = self._backend._ffi.new("CCCryptorRef *")
@@ -422,7 +424,8 @@ class _HashContext(object):
except KeyError:
raise UnsupportedAlgorithm(
"{0} is not a supported hash on this backend".format(
- algorithm.name)
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
)
ctx = self._backend._ffi.new(methods.ctx)
res = methods.hash_init(ctx)
@@ -465,7 +468,8 @@ class _HMACContext(object):
except KeyError:
raise UnsupportedAlgorithm(
"{0} is not a supported HMAC hash on this backend".format(
- algorithm.name)
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
)
self._backend._lib.CCHmacInit(ctx, alg, key, len(key))
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index da41532d..27b609ed 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -106,6 +106,12 @@ class RSABackend(six.with_metaclass(abc.ABCMeta)):
interface.
"""
+ @abc.abstractmethod
+ def mgf1_hash_supported(self, algorithm):
+ """
+ Return True if the hash algorithm is supported for MGF1 in PSS.
+ """
+
class OpenSSLSerializationBackend(six.with_metaclass(abc.ABCMeta)):
@abc.abstractmethod
diff --git a/cryptography/hazmat/backends/multibackend.py b/cryptography/hazmat/backends/multibackend.py
index de1fff7c..aa649dd3 100644
--- a/cryptography/hazmat/backends/multibackend.py
+++ b/cryptography/hazmat/backends/multibackend.py
@@ -14,9 +14,9 @@
from __future__ import absolute_import, division, print_function
from cryptography import utils
-from cryptography.exceptions import UnsupportedAlgorithm
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
from cryptography.hazmat.backends.interfaces import (
- CipherBackend, HashBackend, HMACBackend, PBKDF2HMACBackend, RSABackend
+ CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend
)
@@ -48,7 +48,11 @@ class MultiBackend(object):
return b.create_symmetric_encryption_ctx(algorithm, mode)
except UnsupportedAlgorithm:
pass
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm(
+ "cipher {0} in {1} mode is not supported by this backend".format(
+ algorithm.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
+ )
def create_symmetric_decryption_ctx(self, algorithm, mode):
for b in self._filtered_backends(CipherBackend):
@@ -56,7 +60,11 @@ class MultiBackend(object):
return b.create_symmetric_decryption_ctx(algorithm, mode)
except UnsupportedAlgorithm:
pass
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm(
+ "cipher {0} in {1} mode is not supported by this backend".format(
+ algorithm.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
+ )
def hash_supported(self, algorithm):
return any(
@@ -70,7 +78,11 @@ class MultiBackend(object):
return b.create_hash_ctx(algorithm)
except UnsupportedAlgorithm:
pass
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm(
+ "{0} is not a supported hash on this backend".format(
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
+ )
def hmac_supported(self, algorithm):
return any(
@@ -84,7 +96,11 @@ class MultiBackend(object):
return b.create_hmac_ctx(key, algorithm)
except UnsupportedAlgorithm:
pass
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm(
+ "{0} is not a supported hash on this backend".format(
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
+ )
def pbkdf2_hmac_supported(self, algorithm):
return any(
@@ -101,21 +117,28 @@ class MultiBackend(object):
)
except UnsupportedAlgorithm:
pass
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm(
+ "{0} is not a supported hash on this backend".format(
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
+ )
def generate_rsa_private_key(self, public_exponent, key_size):
for b in self._filtered_backends(RSABackend):
return b.generate_rsa_private_key(public_exponent, key_size)
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
def create_rsa_signature_ctx(self, private_key, padding, algorithm):
for b in self._filtered_backends(RSABackend):
return b.create_rsa_signature_ctx(private_key, padding, algorithm)
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
def create_rsa_verification_ctx(self, public_key, signature, padding,
algorithm):
for b in self._filtered_backends(RSABackend):
return b.create_rsa_verification_ctx(public_key, signature,
padding, algorithm)
- raise UnsupportedAlgorithm
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
diff --git a/cryptography/hazmat/backends/openssl/__init__.py b/cryptography/hazmat/backends/openssl/__init__.py
index a8dfad06..25885e18 100644
--- a/cryptography/hazmat/backends/openssl/__init__.py
+++ b/cryptography/hazmat/backends/openssl/__init__.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
from cryptography.hazmat.backends.openssl.backend import backend
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index f05ee3d6..3293741c 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -15,23 +15,29 @@ from __future__ import absolute_import, division, print_function
import collections
import itertools
+import math
+
+import six
from cryptography import utils
from cryptography.exceptions import (
- UnsupportedAlgorithm, InvalidTag, InternalError, AlreadyFinalized,
- UnsupportedPadding, InvalidSignature
+ AlreadyFinalized, InternalError, InvalidSignature, InvalidTag,
+ UnsupportedAlgorithm, _Reasons
)
from cryptography.hazmat.backends.interfaces import (
- CipherBackend, HashBackend, HMACBackend, PBKDF2HMACBackend, RSABackend
+ CipherBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, RSABackend
)
from cryptography.hazmat.bindings.openssl.binding import Binding
-from cryptography.hazmat.primitives import interfaces, hashes
+from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import rsa
+from cryptography.hazmat.primitives.asymmetric.padding import (
+ MGF1, PKCS1v15, PSS
+)
from cryptography.hazmat.primitives.ciphers.algorithms import (
- AES, Blowfish, Camellia, TripleDES, ARC4, CAST5
+ AES, ARC4, Blowfish, CAST5, Camellia, IDEA, TripleDES
)
from cryptography.hazmat.primitives.ciphers.modes import (
- CBC, CTR, ECB, OFB, CFB, GCM,
+ CBC, CFB, CTR, ECB, GCM, OFB
)
@@ -159,11 +165,14 @@ class Backend(object):
mode_cls,
GetCipherByName("bf-{mode.name}")
)
- for mode_cls in [CBC, CFB, OFB, ECB]:
+ for cipher_cls, mode_cls in itertools.product(
+ [CAST5, IDEA],
+ [CBC, OFB, CFB, ECB],
+ ):
self.register_cipher_adapter(
- CAST5,
+ cipher_cls,
mode_cls,
- GetCipherByName("cast5-{mode.name}")
+ GetCipherByName("{cipher.name}-{mode.name}")
)
self.register_cipher_adapter(
ARC4,
@@ -213,7 +222,8 @@ class Backend(object):
if not isinstance(algorithm, hashes.SHA1):
raise UnsupportedAlgorithm(
"This version of OpenSSL only supports PBKDF2HMAC with "
- "SHA1"
+ "SHA1",
+ _Reasons.UNSUPPORTED_HASH
)
res = self._lib.PKCS5_PBKDF2_HMAC_SHA1(
key_material,
@@ -256,11 +266,24 @@ class Backend(object):
)
def _bn_to_int(self, bn):
- hex_cdata = self._lib.BN_bn2hex(bn)
- assert hex_cdata != self._ffi.NULL
- hex_str = self._ffi.string(hex_cdata)
- self._lib.OPENSSL_free(hex_cdata)
- return int(hex_str, 16)
+ if six.PY3:
+ # Python 3 has constant time from_bytes, so use that.
+
+ bn_num_bytes = (self._lib.BN_num_bits(bn) + 7) // 8
+ bin_ptr = self._ffi.new("unsigned char[]", bn_num_bytes)
+ bin_len = self._lib.BN_bn2bin(bn, bin_ptr)
+ assert bin_len > 0
+ assert bin_ptr != self._ffi.NULL
+ return int.from_bytes(self._ffi.buffer(bin_ptr)[:bin_len], "big")
+
+ else:
+ # Under Python 2 the best we can do is hex()
+
+ hex_cdata = self._lib.BN_bn2hex(bn)
+ assert hex_cdata != self._ffi.NULL
+ hex_str = self._ffi.string(hex_cdata)
+ self._lib.OPENSSL_free(hex_cdata)
+ return int(hex_str, 16)
def _int_to_bn(self, num):
"""
@@ -269,12 +292,24 @@ class Backend(object):
ownership of the object). Be sure to register it for GC if it will
be discarded after use.
"""
- hex_num = hex(num).rstrip("L").lstrip("0x").encode("ascii") or b"0"
- bn_ptr = self._ffi.new("BIGNUM **")
- res = self._lib.BN_hex2bn(bn_ptr, hex_num)
- assert res != 0
- assert bn_ptr[0] != self._ffi.NULL
- return bn_ptr[0]
+
+ if six.PY3:
+ # Python 3 has constant time to_bytes, so use that.
+
+ binary = num.to_bytes(int(num.bit_length() / 8.0 + 1), "big")
+ bn_ptr = self._lib.BN_bin2bn(binary, len(binary), self._ffi.NULL)
+ assert bn_ptr != self._ffi.NULL
+ return bn_ptr
+
+ else:
+ # Under Python 2 the best we can do is hex()
+
+ hex_num = hex(num).rstrip("L").lstrip("0x").encode("ascii") or b"0"
+ bn_ptr = self._ffi.new("BIGNUM **")
+ res = self._lib.BN_hex2bn(bn_ptr, hex_num)
+ assert res != 0
+ assert bn_ptr[0] != self._ffi.NULL
+ return bn_ptr[0]
def generate_rsa_private_key(self, public_exponent, key_size):
if public_exponent < 3:
@@ -298,21 +333,54 @@ class Backend(object):
)
assert res == 1
+ return self._rsa_cdata_to_private_key(ctx)
+
+ def _new_evp_pkey(self):
+ evp_pkey = self._lib.EVP_PKEY_new()
+ assert evp_pkey != self._ffi.NULL
+ return self._ffi.gc(evp_pkey, backend._lib.EVP_PKEY_free)
+
+ def _rsa_private_key_to_evp_pkey(self, private_key):
+ evp_pkey = self._new_evp_pkey()
+ rsa_cdata = self._rsa_cdata_from_private_key(private_key)
+
+ res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL)
+ assert res == 1
+
+ res = self._lib.EVP_PKEY_assign_RSA(evp_pkey, rsa_cdata)
+ assert res == 1
+
+ return evp_pkey
+
+ def _rsa_public_key_to_evp_pkey(self, public_key):
+ evp_pkey = self._new_evp_pkey()
+ rsa_cdata = self._rsa_cdata_from_public_key(public_key)
+
+ res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL)
+ assert res == 1
+
+ res = self._lib.EVP_PKEY_assign_RSA(evp_pkey, rsa_cdata)
+ assert res == 1
+
+ return evp_pkey
+
+ def _rsa_cdata_to_private_key(self, cdata):
return rsa.RSAPrivateKey(
- p=self._bn_to_int(ctx.p),
- q=self._bn_to_int(ctx.q),
- dmp1=self._bn_to_int(ctx.dmp1),
- dmq1=self._bn_to_int(ctx.dmq1),
- iqmp=self._bn_to_int(ctx.iqmp),
- private_exponent=self._bn_to_int(ctx.d),
- public_exponent=self._bn_to_int(ctx.e),
- modulus=self._bn_to_int(ctx.n),
+ p=self._bn_to_int(cdata.p),
+ q=self._bn_to_int(cdata.q),
+ dmp1=self._bn_to_int(cdata.dmp1),
+ dmq1=self._bn_to_int(cdata.dmq1),
+ iqmp=self._bn_to_int(cdata.iqmp),
+ private_exponent=self._bn_to_int(cdata.d),
+ public_exponent=self._bn_to_int(cdata.e),
+ modulus=self._bn_to_int(cdata.n),
)
def _rsa_cdata_from_private_key(self, private_key):
+ # Does not GC the RSA cdata. You *must* make sure it's freed
+ # correctly yourself!
ctx = self._lib.RSA_new()
assert ctx != self._ffi.NULL
- ctx = self._ffi.gc(ctx, self._lib.RSA_free)
ctx.p = self._int_to_bn(private_key.p)
ctx.q = self._int_to_bn(private_key.q)
ctx.d = self._int_to_bn(private_key.d)
@@ -324,9 +392,11 @@ class Backend(object):
return ctx
def _rsa_cdata_from_public_key(self, public_key):
+ # Does not GC the RSA cdata. You *must* make sure it's freed
+ # correctly yourself!
+
ctx = self._lib.RSA_new()
assert ctx != self._ffi.NULL
- ctx = self._ffi.gc(ctx, self._lib.RSA_free)
ctx.e = self._int_to_bn(public_key.e)
ctx.n = self._int_to_bn(public_key.n)
return ctx
@@ -339,6 +409,12 @@ class Backend(object):
return _RSAVerificationContext(self, public_key, signature, padding,
algorithm)
+ def mgf1_hash_supported(self, algorithm):
+ if self._lib.Cryptography_HAS_MGF1_MD:
+ return self.hash_supported(algorithm)
+ else:
+ return isinstance(algorithm, hashes.SHA1)
+
class GetCipherByName(object):
def __init__(self, fmt):
@@ -380,7 +456,8 @@ class _CipherContext(object):
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported "
"by this backend".format(
- cipher.name, mode.name if mode else mode)
+ cipher.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
)
evp_cipher = adapter(self._backend, cipher, mode)
@@ -388,7 +465,8 @@ class _CipherContext(object):
raise UnsupportedAlgorithm(
"cipher {0} in {1} mode is not supported "
"by this backend".format(
- cipher.name, mode.name if mode else mode)
+ cipher.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
)
if isinstance(mode, interfaces.ModeWithInitializationVector):
@@ -438,6 +516,15 @@ class _CipherContext(object):
self._ctx = ctx
def update(self, data):
+ # OpenSSL 0.9.8e has an assertion in its EVP code that causes it
+ # to SIGABRT if you call update with an empty byte string. This can be
+ # removed when we drop support for 0.9.8e (CentOS/RHEL 5). This branch
+ # should be taken only when length is zero and mode is not GCM because
+ # AES GCM can return improper tag values if you don't call update
+ # with empty plaintext when authenticating AAD for ...reasons.
+ if len(data) == 0 and not isinstance(self._mode, GCM):
+ return b""
+
buf = self._backend._ffi.new("unsigned char[]",
len(data) + self._block_size - 1)
outlen = self._backend._ffi.new("int *")
@@ -519,7 +606,8 @@ class _HashContext(object):
if evp_md == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"{0} is not a supported hash on this backend".format(
- algorithm.name)
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
)
res = self._backend._lib.EVP_DigestInit_ex(ctx, evp_md,
self._backend._ffi.NULL)
@@ -569,7 +657,8 @@ class _HMACContext(object):
if evp_md == self._backend._ffi.NULL:
raise UnsupportedAlgorithm(
"{0} is not a supported hash on this backend".format(
- algorithm.name)
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
)
res = self._backend._lib.Cryptography_HMAC_Init_ex(
ctx, key, len(key), evp_md, self._backend._ffi.NULL
@@ -612,24 +701,63 @@ class _HMACContext(object):
return self._backend._ffi.buffer(buf)[:outlen[0]]
+def _get_rsa_pss_salt_length(mgf, key_size, digest_size):
+ if mgf._salt_length is MGF1.MAX_LENGTH:
+ # bit length - 1 per RFC 3447
+ emlen = int(math.ceil((key_size - 1) / 8.0))
+ salt_length = emlen - digest_size - 2
+ assert salt_length >= 0
+ return salt_length
+ else:
+ return mgf._salt_length
+
+
@utils.register_interface(interfaces.AsymmetricSignatureContext)
class _RSASignatureContext(object):
def __init__(self, backend, private_key, padding, algorithm):
self._backend = backend
self._private_key = private_key
+
if not isinstance(padding, interfaces.AsymmetricPadding):
raise TypeError(
"Expected provider of interfaces.AsymmetricPadding")
- if padding.name == "EMSA-PKCS1-v1_5":
+ if isinstance(padding, PKCS1v15):
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
self._finalize_method = self._finalize_pkey_ctx
self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING
else:
self._finalize_method = self._finalize_pkcs1
+ elif isinstance(padding, PSS):
+ if not isinstance(padding._mgf, MGF1):
+ raise UnsupportedAlgorithm(
+ "Only MGF1 is supported by this backend",
+ _Reasons.UNSUPPORTED_MGF
+ )
+
+ # Size of key in bytes - 2 is the maximum
+ # PSS signature length (salt length is checked later)
+ key_size_bytes = int(math.ceil(private_key.key_size / 8.0))
+ if key_size_bytes - algorithm.digest_size - 2 < 0:
+ raise ValueError("Digest too large for key size. Use a larger "
+ "key.")
+
+ if not self._backend.mgf1_hash_supported(padding._mgf._algorithm):
+ raise UnsupportedAlgorithm(
+ "When OpenSSL is older than 1.0.1 then only SHA1 is "
+ "supported with MGF1.",
+ _Reasons.UNSUPPORTED_HASH
+ )
+
+ if self._backend._lib.Cryptography_HAS_PKEY_CTX:
+ self._finalize_method = self._finalize_pkey_ctx
+ self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING
+ else:
+ self._finalize_method = self._finalize_pss
else:
- raise UnsupportedPadding(
- "{0} is not supported by this backend".format(padding.name)
+ raise UnsupportedAlgorithm(
+ "{0} is not supported by this backend".format(padding.name),
+ _Reasons.UNSUPPORTED_PADDING
)
self._padding = padding
@@ -645,24 +773,19 @@ class _RSASignatureContext(object):
def finalize(self):
if self._hash_ctx is None:
raise AlreadyFinalized("Context has already been finalized")
- evp_pkey = self._backend._lib.EVP_PKEY_new()
- assert evp_pkey != self._backend._ffi.NULL
- evp_pkey = backend._ffi.gc(evp_pkey, backend._lib.EVP_PKEY_free)
- rsa_cdata = backend._rsa_cdata_from_private_key(self._private_key)
- res = self._backend._lib.RSA_blinding_on(
- rsa_cdata, self._backend._ffi.NULL)
- assert res == 1
- res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata)
- assert res == 1
+
+ evp_pkey = self._backend._rsa_private_key_to_evp_pkey(
+ self._private_key)
+
evp_md = self._backend._lib.EVP_get_digestbyname(
self._algorithm.name.encode("ascii"))
assert evp_md != self._backend._ffi.NULL
pkey_size = self._backend._lib.EVP_PKEY_size(evp_pkey)
assert pkey_size > 0
- return self._finalize_method(evp_pkey, pkey_size, rsa_cdata, evp_md)
+ return self._finalize_method(evp_pkey, pkey_size, evp_md)
- def _finalize_pkey_ctx(self, evp_pkey, pkey_size, rsa_cdata, evp_md):
+ def _finalize_pkey_ctx(self, evp_pkey, pkey_size, evp_md):
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
evp_pkey, self._backend._ffi.NULL
)
@@ -676,6 +799,26 @@ class _RSASignatureContext(object):
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
pkey_ctx, self._padding_enum)
assert res > 0
+ if isinstance(self._padding, PSS):
+ res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
+ pkey_ctx,
+ _get_rsa_pss_salt_length(
+ self._padding._mgf,
+ self._private_key.key_size,
+ self._hash_ctx.algorithm.digest_size
+ )
+ )
+ assert res > 0
+
+ if self._backend._lib.Cryptography_HAS_MGF1_MD:
+ # MGF1 MD is configurable in OpenSSL 1.0.1+
+ mgf1_md = self._backend._lib.EVP_get_digestbyname(
+ self._padding._mgf._algorithm.name.encode("ascii"))
+ assert mgf1_md != self._backend._ffi.NULL
+ res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
+ pkey_ctx, mgf1_md
+ )
+ assert res > 0
data_to_sign = self._hash_ctx.finalize()
self._hash_ctx = None
buflen = self._backend._ffi.new("size_t *")
@@ -690,10 +833,17 @@ class _RSASignatureContext(object):
buf = self._backend._ffi.new("unsigned char[]", buflen[0])
res = self._backend._lib.EVP_PKEY_sign(
pkey_ctx, buf, buflen, data_to_sign, len(data_to_sign))
- assert res == 1
+ if res != 1:
+ errors = self._backend._consume_errors()
+ assert errors[0].lib == self._backend._lib.ERR_LIB_RSA
+ assert (errors[0].reason ==
+ self._backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE)
+ raise ValueError("Salt length too long for key size. Try using "
+ "MAX_LENGTH instead.")
+
return self._backend._ffi.buffer(buf)[:]
- def _finalize_pkcs1(self, evp_pkey, pkey_size, rsa_cdata, evp_md):
+ def _finalize_pkcs1(self, evp_pkey, pkey_size, evp_md):
sig_buf = self._backend._ffi.new("char[]", pkey_size)
sig_len = self._backend._ffi.new("unsigned int *")
res = self._backend._lib.EVP_SignFinal(
@@ -707,6 +857,44 @@ class _RSASignatureContext(object):
assert res == 1
return self._backend._ffi.buffer(sig_buf)[:sig_len[0]]
+ def _finalize_pss(self, evp_pkey, pkey_size, evp_md):
+ data_to_sign = self._hash_ctx.finalize()
+ self._hash_ctx = None
+ padded = self._backend._ffi.new("unsigned char[]", pkey_size)
+ rsa_cdata = self._backend._lib.EVP_PKEY_get1_RSA(evp_pkey)
+ assert rsa_cdata != self._backend._ffi.NULL
+ rsa_cdata = self._backend._ffi.gc(rsa_cdata,
+ self._backend._lib.RSA_free)
+ res = self._backend._lib.RSA_padding_add_PKCS1_PSS(
+ rsa_cdata,
+ padded,
+ data_to_sign,
+ evp_md,
+ _get_rsa_pss_salt_length(
+ self._padding._mgf,
+ self._private_key.key_size,
+ len(data_to_sign)
+ )
+ )
+ if res != 1:
+ errors = self._backend._consume_errors()
+ assert errors[0].lib == self._backend._lib.ERR_LIB_RSA
+ assert (errors[0].reason ==
+ self._backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE)
+ raise ValueError("Salt length too long for key size. Try using "
+ "MAX_LENGTH instead.")
+
+ sig_buf = self._backend._ffi.new("char[]", pkey_size)
+ sig_len = self._backend._lib.RSA_private_encrypt(
+ pkey_size,
+ padded,
+ sig_buf,
+ rsa_cdata,
+ self._backend._lib.RSA_NO_PADDING
+ )
+ assert sig_len != -1
+ return self._backend._ffi.buffer(sig_buf)[:sig_len]
+
@utils.register_interface(interfaces.AsymmetricVerificationContext)
class _RSAVerificationContext(object):
@@ -714,18 +902,50 @@ class _RSAVerificationContext(object):
self._backend = backend
self._public_key = public_key
self._signature = signature
+
if not isinstance(padding, interfaces.AsymmetricPadding):
raise TypeError(
"Expected provider of interfaces.AsymmetricPadding")
- if padding.name == "EMSA-PKCS1-v1_5":
+ if isinstance(padding, PKCS1v15):
if self._backend._lib.Cryptography_HAS_PKEY_CTX:
self._verify_method = self._verify_pkey_ctx
self._padding_enum = self._backend._lib.RSA_PKCS1_PADDING
else:
self._verify_method = self._verify_pkcs1
+ elif isinstance(padding, PSS):
+ if not isinstance(padding._mgf, MGF1):
+ raise UnsupportedAlgorithm(
+ "Only MGF1 is supported by this backend",
+ _Reasons.UNSUPPORTED_MGF
+ )
+
+ # Size of key in bytes - 2 is the maximum
+ # PSS signature length (salt length is checked later)
+ key_size_bytes = int(math.ceil(public_key.key_size / 8.0))
+ if key_size_bytes - algorithm.digest_size - 2 < 0:
+ raise ValueError(
+ "Digest too large for key size. Check that you have the "
+ "correct key and digest algorithm."
+ )
+
+ if not self._backend.mgf1_hash_supported(padding._mgf._algorithm):
+ raise UnsupportedAlgorithm(
+ "When OpenSSL is older than 1.0.1 then only SHA1 is "
+ "supported with MGF1.",
+ _Reasons.UNSUPPORTED_HASH
+ )
+
+ if self._backend._lib.Cryptography_HAS_PKEY_CTX:
+ self._verify_method = self._verify_pkey_ctx
+ self._padding_enum = self._backend._lib.RSA_PKCS1_PSS_PADDING
+ else:
+ self._verify_method = self._verify_pss
else:
- raise UnsupportedPadding
+ raise UnsupportedAlgorithm(
+ "{0} is not supported by this backend".format(padding.name),
+ _Reasons.UNSUPPORTED_PADDING
+ )
self._padding = padding
self._algorithm = algorithm
@@ -741,22 +961,16 @@ class _RSAVerificationContext(object):
if self._hash_ctx is None:
raise AlreadyFinalized("Context has already been finalized")
- evp_pkey = self._backend._lib.EVP_PKEY_new()
- assert evp_pkey != self._backend._ffi.NULL
- evp_pkey = backend._ffi.gc(evp_pkey, backend._lib.EVP_PKEY_free)
- rsa_cdata = backend._rsa_cdata_from_public_key(self._public_key)
- res = self._backend._lib.RSA_blinding_on(
- rsa_cdata, self._backend._ffi.NULL)
- assert res == 1
- res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata)
- assert res == 1
+ evp_pkey = self._backend._rsa_public_key_to_evp_pkey(
+ self._public_key)
+
evp_md = self._backend._lib.EVP_get_digestbyname(
self._algorithm.name.encode("ascii"))
assert evp_md != self._backend._ffi.NULL
- self._verify_method(rsa_cdata, evp_pkey, evp_md)
+ self._verify_method(evp_pkey, evp_md)
- def _verify_pkey_ctx(self, rsa_cdata, evp_pkey, evp_md):
+ def _verify_pkey_ctx(self, evp_pkey, evp_md):
pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
evp_pkey, self._backend._ffi.NULL
)
@@ -770,6 +984,26 @@ class _RSAVerificationContext(object):
res = self._backend._lib.EVP_PKEY_CTX_set_rsa_padding(
pkey_ctx, self._padding_enum)
assert res > 0
+ if isinstance(self._padding, PSS):
+ res = self._backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen(
+ pkey_ctx,
+ _get_rsa_pss_salt_length(
+ self._padding._mgf,
+ self._public_key.key_size,
+ self._hash_ctx.algorithm.digest_size
+ )
+ )
+ assert res > 0
+ if self._backend._lib.Cryptography_HAS_MGF1_MD:
+ # MGF1 MD is configurable in OpenSSL 1.0.1+
+ mgf1_md = self._backend._lib.EVP_get_digestbyname(
+ self._padding._mgf._algorithm.name.encode("ascii"))
+ assert mgf1_md != self._backend._ffi.NULL
+ res = self._backend._lib.EVP_PKEY_CTX_set_rsa_mgf1_md(
+ pkey_ctx, mgf1_md
+ )
+ assert res > 0
+
data_to_verify = self._hash_ctx.finalize()
self._hash_ctx = None
res = self._backend._lib.EVP_PKEY_verify(
@@ -784,10 +1018,11 @@ class _RSAVerificationContext(object):
# occurs.
assert res >= 0
if res == 0:
- assert self._backend._consume_errors()
+ errors = self._backend._consume_errors()
+ assert errors
raise InvalidSignature
- def _verify_pkcs1(self, rsa_cdata, evp_pkey, evp_md):
+ def _verify_pkcs1(self, evp_pkey, evp_md):
res = self._backend._lib.EVP_VerifyFinal(
self._hash_ctx._ctx,
self._signature,
@@ -801,7 +1036,46 @@ class _RSAVerificationContext(object):
# occurs.
assert res >= 0
if res == 0:
- assert self._backend._consume_errors()
+ errors = self._backend._consume_errors()
+ assert errors
+ raise InvalidSignature
+
+ def _verify_pss(self, evp_pkey, evp_md):
+ pkey_size = self._backend._lib.EVP_PKEY_size(evp_pkey)
+ assert pkey_size > 0
+ rsa_cdata = self._backend._lib.EVP_PKEY_get1_RSA(evp_pkey)
+ assert rsa_cdata != self._backend._ffi.NULL
+ rsa_cdata = self._backend._ffi.gc(rsa_cdata,
+ self._backend._lib.RSA_free)
+ buf = self._backend._ffi.new("unsigned char[]", pkey_size)
+ res = self._backend._lib.RSA_public_decrypt(
+ len(self._signature),
+ self._signature,
+ buf,
+ rsa_cdata,
+ self._backend._lib.RSA_NO_PADDING
+ )
+ if res != pkey_size:
+ errors = self._backend._consume_errors()
+ assert errors
+ raise InvalidSignature
+
+ data_to_verify = self._hash_ctx.finalize()
+ self._hash_ctx = None
+ res = self._backend._lib.RSA_verify_PKCS1_PSS(
+ rsa_cdata,
+ data_to_verify,
+ evp_md,
+ buf,
+ _get_rsa_pss_salt_length(
+ self._padding._mgf,
+ self._public_key.key_size,
+ len(data_to_verify)
+ )
+ )
+ if res != 1:
+ errors = self._backend._consume_errors()
+ assert errors
raise InvalidSignature
diff --git a/cryptography/hazmat/bindings/__init__.py b/cryptography/hazmat/bindings/__init__.py
index 55c925c6..2f420574 100644
--- a/cryptography/hazmat/bindings/__init__.py
+++ b/cryptography/hazmat/bindings/__init__.py
@@ -10,3 +10,5 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/bindings/commoncrypto/__init__.py b/cryptography/hazmat/bindings/commoncrypto/__init__.py
index 55c925c6..2f420574 100644
--- a/cryptography/hazmat/bindings/commoncrypto/__init__.py
+++ b/cryptography/hazmat/bindings/commoncrypto/__init__.py
@@ -10,3 +10,5 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/bindings/commoncrypto/binding.py b/cryptography/hazmat/bindings/commoncrypto/binding.py
index 45c0eaad..3673ea36 100644
--- a/cryptography/hazmat/bindings/commoncrypto/binding.py
+++ b/cryptography/hazmat/bindings/commoncrypto/binding.py
@@ -13,6 +13,7 @@
from __future__ import absolute_import, division, print_function
+import platform
import sys
from cryptography.hazmat.bindings.utils import build_ffi
@@ -46,4 +47,5 @@ class Binding(object):
@classmethod
def is_available(cls):
- return sys.platform == "darwin"
+ return sys.platform == "darwin" and list(map(
+ int, platform.mac_ver()[0].split("."))) >= [10, 8, 0]
diff --git a/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py b/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
index 8f03bc3f..9bd03a7c 100644
--- a/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
+++ b/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <CommonCrypto/CommonCryptor.h>
"""
diff --git a/cryptography/hazmat/bindings/commoncrypto/common_digest.py b/cryptography/hazmat/bindings/commoncrypto/common_digest.py
index ec0fcc92..c59200cb 100644
--- a/cryptography/hazmat/bindings/commoncrypto/common_digest.py
+++ b/cryptography/hazmat/bindings/commoncrypto/common_digest.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <CommonCrypto/CommonDigest.h>
"""
diff --git a/cryptography/hazmat/bindings/commoncrypto/common_hmac.py b/cryptography/hazmat/bindings/commoncrypto/common_hmac.py
index a4bf9009..4f54b62b 100644
--- a/cryptography/hazmat/bindings/commoncrypto/common_hmac.py
+++ b/cryptography/hazmat/bindings/commoncrypto/common_hmac.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <CommonCrypto/CommonHMAC.h>
"""
diff --git a/cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py b/cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
index 85def1e9..e8cc03ef 100644
--- a/cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
+++ b/cryptography/hazmat/bindings/commoncrypto/common_key_derivation.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <CommonCrypto/CommonKeyDerivation.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/__init__.py b/cryptography/hazmat/bindings/openssl/__init__.py
index 55c925c6..2f420574 100644
--- a/cryptography/hazmat/bindings/openssl/__init__.py
+++ b/cryptography/hazmat/bindings/openssl/__init__.py
@@ -10,3 +10,5 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/bindings/openssl/aes.py b/cryptography/hazmat/bindings/openssl/aes.py
index 6cbcd577..17c154cf 100644
--- a/cryptography/hazmat/bindings/openssl/aes.py
+++ b/cryptography/hazmat/bindings/openssl/aes.py
@@ -11,11 +11,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/aes.h>
"""
TYPES = """
+static const int Cryptography_HAS_AES_WRAP;
+
struct aes_key_st {
...;
};
@@ -25,16 +29,34 @@ 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 *);
+"""
+
+MACROS = """
+/* these can be moved back to FUNCTIONS once we drop support for 0.9.8h.
+ This should be when we drop RHEL/CentOS 5, which is on 0.9.8e. */
int AES_wrap_key(AES_KEY *, const unsigned char *, unsigned char *,
const unsigned char *, unsigned int);
int AES_unwrap_key(AES_KEY *, const unsigned char *, unsigned char *,
const unsigned char *, unsigned int);
"""
-MACROS = """
-"""
-
CUSTOMIZATIONS = """
+// OpenSSL 0.9.8h+
+#if OPENSSL_VERSION_NUMBER >= 0x0090808fL
+static const long Cryptography_HAS_AES_WRAP = 1;
+#else
+static const long Cryptography_HAS_AES_WRAP = 0;
+int (*AES_wrap_key)(AES_KEY *, const unsigned char *, unsigned char *,
+ const unsigned char *, unsigned int) = NULL;
+int (*AES_unwrap_key)(AES_KEY *, const unsigned char *, unsigned char *,
+ const unsigned char *, unsigned int) = NULL;
+#endif
+
"""
-CONDITIONAL_NAMES = {}
+CONDITIONAL_NAMES = {
+ "Cryptography_HAS_AES_WRAP": [
+ "AES_wrap_key",
+ "AES_unwrap_key",
+ ],
+}
diff --git a/cryptography/hazmat/bindings/openssl/asn1.py b/cryptography/hazmat/bindings/openssl/asn1.py
index aeaf316e..dfdf1bf5 100644
--- a/cryptography/hazmat/bindings/openssl/asn1.py
+++ b/cryptography/hazmat/bindings/openssl/asn1.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/asn1.h>
"""
@@ -97,6 +99,7 @@ int i2a_ASN1_INTEGER(BIO *, ASN1_INTEGER *);
/* ASN1 TIME */
ASN1_TIME *ASN1_TIME_new(void);
+void ASN1_TIME_free(ASN1_TIME *);
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *,
ASN1_GENERALIZEDTIME **);
@@ -106,7 +109,6 @@ int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *, time_t);
/* ASN1 GENERALIZEDTIME */
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *, const char *);
void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *);
-int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *);
/* ASN1 ENUMERATED */
ASN1_ENUMERATED *ASN1_ENUMERATED_new(void);
@@ -136,6 +138,9 @@ long ASN1_INTEGER_get(ASN1_INTEGER *);
BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *, BIGNUM *);
ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *, ASN1_INTEGER *);
+
+/* These isn't a macro the arg is const on openssl 1.0.2+ */
+int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *);
"""
CUSTOMIZATIONS = """
diff --git a/cryptography/hazmat/bindings/openssl/bignum.py b/cryptography/hazmat/bindings/openssl/bignum.py
index e843099e..a40397db 100644
--- a/cryptography/hazmat/bindings/openssl/bignum.py
+++ b/cryptography/hazmat/bindings/openssl/bignum.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/bn.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/binding.py b/cryptography/hazmat/bindings/openssl/binding.py
index 0469a1ea..927406c6 100644
--- a/cryptography/hazmat/bindings/openssl/binding.py
+++ b/cryptography/hazmat/bindings/openssl/binding.py
@@ -53,6 +53,7 @@ class Binding(object):
"dh",
"dsa",
"ec",
+ "ecdsa",
"engine",
"err",
"evp",
diff --git a/cryptography/hazmat/bindings/openssl/bio.py b/cryptography/hazmat/bindings/openssl/bio.py
index 279ad223..0c521b4d 100644
--- a/cryptography/hazmat/bindings/openssl/bio.py
+++ b/cryptography/hazmat/bindings/openssl/bio.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/bio.h>
"""
@@ -105,7 +107,6 @@ BIO *BIO_push(BIO *, BIO *);
BIO *BIO_pop(BIO *);
BIO *BIO_next(BIO *);
BIO *BIO_find_type(BIO *, int);
-int BIO_method_type(const BIO *);
BIO_METHOD *BIO_s_mem(void);
BIO *BIO_new_mem_buf(void *, int);
BIO_METHOD *BIO_s_file(void);
@@ -168,6 +169,10 @@ long BIO_set_read_buffer_size(BIO *, long);
long BIO_set_write_buffer_size(BIO *, long);
long BIO_set_buffer_size(BIO *, long);
long BIO_set_buffer_read_data(BIO *, void *, long);
+
+/* The following was a macro in 0.9.8e. Once we drop support for RHEL/CentOS 5
+ we should move this back to FUNCTIONS. */
+int BIO_method_type(const BIO *);
"""
CUSTOMIZATIONS = """
diff --git a/cryptography/hazmat/bindings/openssl/conf.py b/cryptography/hazmat/bindings/openssl/conf.py
index 6d818cf1..dda35e86 100644
--- a/cryptography/hazmat/bindings/openssl/conf.py
+++ b/cryptography/hazmat/bindings/openssl/conf.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/conf.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/crypto.py b/cryptography/hazmat/bindings/openssl/crypto.py
index 81d13b73..99e1a61d 100644
--- a/cryptography/hazmat/bindings/openssl/crypto.py
+++ b/cryptography/hazmat/bindings/openssl/crypto.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/crypto.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/dh.py b/cryptography/hazmat/bindings/openssl/dh.py
index ecc62e98..1791a670 100644
--- a/cryptography/hazmat/bindings/openssl/dh.py
+++ b/cryptography/hazmat/bindings/openssl/dh.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/dh.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/dsa.py b/cryptography/hazmat/bindings/openssl/dsa.py
index 609a33bf..40d3b8ee 100644
--- a/cryptography/hazmat/bindings/openssl/dsa.py
+++ b/cryptography/hazmat/bindings/openssl/dsa.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/dsa.h>
"""
@@ -35,10 +37,13 @@ FUNCTIONS = """
DSA *DSA_generate_parameters(int, unsigned char *, int, int *, unsigned long *,
void (*)(int, int, void *), void *);
int DSA_generate_key(DSA *);
+DSA *DSA_new(void);
void DSA_free(DSA *);
"""
MACROS = """
+int DSA_generate_parameters_ex(DSA *, int, unsigned char *, int,
+ int *, unsigned long *, BN_GENCB *);
"""
CUSTOMIZATIONS = """
diff --git a/cryptography/hazmat/bindings/openssl/ec.py b/cryptography/hazmat/bindings/openssl/ec.py
index 39403ff2..2617fe2a 100644
--- a/cryptography/hazmat/bindings/openssl/ec.py
+++ b/cryptography/hazmat/bindings/openssl/ec.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#ifndef OPENSSL_NO_EC
#include <openssl/ec.h>
@@ -23,14 +25,10 @@ TYPES = """
static const int Cryptography_HAS_EC;
typedef ... EC_KEY;
-
-static const int NID_X9_62_prime192v1;
-static const int NID_X9_62_prime192v2;
-static const int NID_X9_62_prime192v3;
-static const int NID_X9_62_prime239v1;
-static const int NID_X9_62_prime239v2;
-static const int NID_X9_62_prime239v3;
-static const int NID_X9_62_prime256v1;
+typedef struct {
+ int nid;
+ const char *comment;
+} EC_builtin_curve;
"""
FUNCTIONS = """
@@ -39,14 +37,22 @@ FUNCTIONS = """
MACROS = """
EC_KEY *EC_KEY_new_by_curve_name(int);
void EC_KEY_free(EC_KEY *);
+
+size_t EC_get_builtin_curves(EC_builtin_curve *, size_t);
+
"""
CUSTOMIZATIONS = """
#ifdef OPENSSL_NO_EC
static const long Cryptography_HAS_EC = 0;
typedef void EC_KEY;
+typedef struct {
+ int nid;
+ const char *comment;
+} EC_builtin_curve;
EC_KEY* (*EC_KEY_new_by_curve_name)(int) = NULL;
void (*EC_KEY_free)(EC_KEY *) = NULL;
+size_t (*EC_get_builtin_curves)(EC_builtin_curve *, size_t) = NULL;
#else
static const long Cryptography_HAS_EC = 1;
#endif
@@ -56,5 +62,6 @@ CONDITIONAL_NAMES = {
"Cryptography_HAS_EC": [
"EC_KEY_new_by_curve_name",
"EC_KEY_free",
+ "EC_get_builtin_curves",
],
}
diff --git a/cryptography/hazmat/bindings/openssl/ecdsa.py b/cryptography/hazmat/bindings/openssl/ecdsa.py
new file mode 100644
index 00000000..bfa67206
--- /dev/null
+++ b/cryptography/hazmat/bindings/openssl/ecdsa.py
@@ -0,0 +1,130 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+INCLUDES = """
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+"""
+
+TYPES = """
+static const int Cryptography_HAS_ECDSA;
+
+typedef struct {
+ BIGNUM *r;
+ BIGNUM *s;
+} ECDSA_SIG;
+
+typedef ... CRYPTO_EX_new;
+typedef ... CRYPTO_EX_dup;
+typedef ... CRYPTO_EX_free;
+"""
+
+FUNCTIONS = """
+"""
+
+MACROS = """
+ECDSA_SIG *ECDSA_SIG_new();
+void ECDSA_SIG_free(ECDSA_SIG *);
+int i2d_ECDSA_SIG(const ECDSA_SIG *, unsigned char **);
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **s, const unsigned char **, long);
+ECDSA_SIG *ECDSA_do_sign(const unsigned char *, int, EC_KEY *);
+ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *, int, const BIGNUM *,
+ const BIGNUM *, EC_KEY *);
+int ECDSA_do_verify(const unsigned char *, int, const ECDSA_SIG *, EC_KEY*);
+int ECDSA_sign_setup(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **);
+int ECDSA_sign(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, EC_KEY *);
+int ECDSA_sign_ex(int, const unsigned char *, int dgstlen, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *);
+int ECDSA_verify(int, const unsigned char *, int, const unsigned char *, int,
+ EC_KEY *);
+int ECDSA_size(const EC_KEY *);
+
+const ECDSA_METHOD* ECDSA_OpenSSL();
+void ECDSA_set_default_method(const ECDSA_METHOD *);
+const ECDSA_METHOD* ECDSA_get_default_method();
+int ECDSA_get_ex_new_index(long, void *, CRYPTO_EX_new *,
+ CRYPTO_EX_dup *, CRYPTO_EX_free *);
+int ECDSA_set_method(EC_KEY *, const ECDSA_METHOD *);
+int ECDSA_set_ex_data(EC_KEY *, int, void *);
+void *ECDSA_get_ex_data(EC_KEY *, int);
+"""
+
+CUSTOMIZATIONS = """
+#ifdef OPENSSL_NO_ECDSA
+static const long Cryptography_HAS_ECDSA = 0;
+
+typedef struct {
+ BIGNUM *r;
+ BIGNUM *s;
+} ECDSA_SIG;
+
+ECDSA_SIG* (*ECDSA_SIG_new)() = NULL;
+void (*ECDSA_SIG_free)(ECDSA_SIG *) = NULL;
+int (*i2d_ECDSA_SIG)(const ECDSA_SIG *, unsigned char **) = NULL;
+ECDSA_SIG* (*d2i_ECDSA_SIG)(ECDSA_SIG **s, const unsigned char **,
+ long) = NULL;
+ECDSA_SIG* (*ECDSA_do_sign)(const unsigned char *, int, EC_KEY *eckey) = NULL;
+ECDSA_SIG* (*ECDSA_do_sign_ex)(const unsigned char *, int, const BIGNUM *,
+ const BIGNUM *, EC_KEY *) = NULL;
+int (*ECDSA_do_verify)(const unsigned char *, int, const ECDSA_SIG *,
+ EC_KEY*) = NULL;
+int (*ECDSA_sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **) = NULL;
+int (*ECDSA_sign)(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, EC_KEY *) = NULL;
+int (*ECDSA_sign_ex)(int, const unsigned char *, int dgstlen, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *,
+ EC_KEY *) = NULL;
+int (*ECDSA_verify)(int, const unsigned char *, int, const unsigned char *,
+ int, EC_KEY *) = NULL;
+int (*ECDSA_size)(const EC_KEY *) = NULL;
+
+const ECDSA_METHOD* (*ECDSA_OpenSSL)() = NULL;
+void (*ECDSA_set_default_method)(const ECDSA_METHOD *) = NULL;
+const ECDSA_METHOD* (*ECDSA_get_default_method)() = NULL;
+int (*ECDSA_set_method)(EC_KEY *, const ECDSA_METHOD *) = NULL;
+int (*ECDSA_get_ex_new_index)(long, void *, CRYPTO_EX_new *,
+ CRYPTO_EX_dup *, CRYPTO_EX_free *) = NULL;
+int (*ECDSA_set_ex_data)(EC_KEY *, int, void *) = NULL;
+void* (*ECDSA_get_ex_data)(EC_KEY *, int) = NULL;
+#else
+static const long Cryptography_HAS_ECDSA = 1;
+#endif
+"""
+
+CONDITIONAL_NAMES = {
+ "Cryptography_HAS_ECDSA": [
+ "ECDSA_SIG_new",
+ "ECDSA_SIG_free",
+ "i2d_ECDSA_SIG",
+ "d2i_ECDSA_SIG",
+ "ECDSA_do_sign",
+ "ECDSA_do_sign_ex",
+ "ECDSA_do_verify",
+ "ECDSA_sign_setup",
+ "ECDSA_sign",
+ "ECDSA_sign_ex",
+ "ECDSA_verify",
+ "ECDSA_size",
+ "ECDSA_OpenSSL",
+ "ECDSA_set_default_method",
+ "ECDSA_get_default_method",
+ "ECDSA_set_method",
+ "ECDSA_get_ex_new_index",
+ "ECDSA_set_ex_data",
+ "ECDSA_get_ex_data",
+ ],
+}
diff --git a/cryptography/hazmat/bindings/openssl/engine.py b/cryptography/hazmat/bindings/openssl/engine.py
index 77118e81..364232e0 100644
--- a/cryptography/hazmat/bindings/openssl/engine.py
+++ b/cryptography/hazmat/bindings/openssl/engine.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/engine.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py
index ddb60ef7..551d8217 100644
--- a/cryptography/hazmat/bindings/openssl/err.py
+++ b/cryptography/hazmat/bindings/openssl/err.py
@@ -11,12 +11,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/err.h>
"""
TYPES = """
static const int Cryptography_HAS_REMOVE_THREAD_STATE;
+static const int Cryptography_HAS_098H_ERROR_CODES;
+static const int Cryptography_HAS_098C_CAMELLIA_CODES;
struct ERR_string_data_st {
unsigned long error;
@@ -28,6 +32,7 @@ typedef struct ERR_string_data_st ERR_STRING_DATA;
static const int ERR_LIB_EVP;
static const int ERR_LIB_PEM;
static const int ERR_LIB_ASN1;
+static const int ERR_LIB_RSA;
static const int ASN1_F_ASN1_ENUMERATED_TO_BN;
static const int ASN1_F_ASN1_EX_C2I;
@@ -50,8 +55,6 @@ static const int ASN1_F_ASN1_TYPE_GET_OCTETSTRING;
static const int ASN1_F_ASN1_UNPACK_STRING;
static const int ASN1_F_ASN1_UTCTIME_SET;
static const int ASN1_F_ASN1_VERIFY;
-static const int ASN1_F_B64_READ_ASN1;
-static const int ASN1_F_B64_WRITE_ASN1;
static const int ASN1_F_BITSTR_CB;
static const int ASN1_F_BN_TO_ASN1_ENUMERATED;
static const int ASN1_F_BN_TO_ASN1_INTEGER;
@@ -71,8 +74,6 @@ static const int ASN1_F_LONG_C2I;
static const int ASN1_F_OID_MODULE_INIT;
static const int ASN1_F_PARSE_TAGGING;
static const int ASN1_F_PKCS5_PBE_SET;
-static const int ASN1_F_SMIME_READ_ASN1;
-static const int ASN1_F_SMIME_TEXT;
static const int ASN1_F_X509_CINF_NEW;
static const int ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
static const int ASN1_R_BUFFER_TOO_SMALL;
@@ -86,10 +87,7 @@ static const int ASN1_R_ERROR_GETTING_TIME;
static const int ASN1_R_ERROR_LOADING_SECTION;
static const int ASN1_R_MSTRING_WRONG_TAG;
static const int ASN1_R_NESTED_ASN1_STRING;
-static const int ASN1_R_NO_CONTENT_TYPE;
static const int ASN1_R_NO_MATCHING_CHOICE_TYPE;
-static const int ASN1_R_NO_MULTIPART_BODY_FAILURE;
-static const int ASN1_R_NO_MULTIPART_BOUNDARY;
static const int ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM;
static const int ASN1_R_UNKNOWN_OBJECT_TYPE;
static const int ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE;
@@ -103,7 +101,6 @@ static const int ASN1_R_WRONG_TAG;
static const int ASN1_R_WRONG_TYPE;
static const int EVP_F_AES_INIT_KEY;
-static const int EVP_F_CAMELLIA_INIT_KEY;
static const int EVP_F_D2I_PKEY;
static const int EVP_F_DSA_PKEY2PKCS8;
static const int EVP_F_DSAPKEY2PKCS8;
@@ -144,14 +141,12 @@ static const int EVP_R_BAD_BLOCK_LENGTH;
static const int EVP_R_BAD_KEY_LENGTH;
static const int EVP_R_BN_DECODE_ERROR;
static const int EVP_R_BN_PUBKEY_ERROR;
-static const int EVP_R_CAMELLIA_KEY_SETUP_FAILED;
static const int EVP_R_CIPHER_PARAMETER_ERROR;
static const int EVP_R_CTRL_NOT_IMPLEMENTED;
static const int EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED;
static const int EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH;
static const int EVP_R_DECODE_ERROR;
static const int EVP_R_DIFFERENT_KEY_TYPES;
-static const int EVP_R_DISABLED_FOR_FIPS;
static const int EVP_R_ENCODE_ERROR;
static const int EVP_R_INITIALIZATION_ERROR;
static const int EVP_R_INPUT_NOT_INITIALIZED;
@@ -218,6 +213,8 @@ static const int PEM_R_READ_KEY;
static const int PEM_R_SHORT_HEADER;
static const int PEM_R_UNSUPPORTED_CIPHER;
static const int PEM_R_UNSUPPORTED_ENCRYPTION;
+
+static const int RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE;
"""
FUNCTIONS = """
@@ -258,6 +255,19 @@ int ERR_FATAL_ERROR(unsigned long);
* supporting 0.9.8
*/
void ERR_remove_thread_state(const CRYPTO_THREADID *);
+
+/* These were added in OpenSSL 0.9.8h. When we drop support for RHEL/CentOS 5
+ we should be able to move these back to TYPES. */
+static const int ASN1_F_B64_READ_ASN1;
+static const int ASN1_F_B64_WRITE_ASN1;
+static const int ASN1_F_SMIME_READ_ASN1;
+static const int ASN1_F_SMIME_TEXT;
+static const int ASN1_R_NO_CONTENT_TYPE;
+static const int ASN1_R_NO_MULTIPART_BODY_FAILURE;
+static const int ASN1_R_NO_MULTIPART_BOUNDARY;
+/* These were added in OpenSSL 0.9.8c. */
+static const int EVP_F_CAMELLIA_INIT_KEY;
+static const int EVP_R_CAMELLIA_KEY_SETUP_FAILED;
"""
CUSTOMIZATIONS = """
@@ -266,12 +276,49 @@ static const long Cryptography_HAS_REMOVE_THREAD_STATE = 1;
#else
static const long Cryptography_HAS_REMOVE_THREAD_STATE = 0;
typedef uint32_t CRYPTO_THREADID;
-void (*ERR_remove_thread_state)(const CRYPTO_THREADID *);
+void (*ERR_remove_thread_state)(const CRYPTO_THREADID *) = NULL;
+#endif
+
+// OpenSSL 0.9.8h+
+#if OPENSSL_VERSION_NUMBER >= 0x0090808fL
+static const long Cryptography_HAS_098H_ERROR_CODES = 1;
+#else
+static const long Cryptography_HAS_098H_ERROR_CODES = 0;
+static const int ASN1_F_B64_READ_ASN1 = 0;
+static const int ASN1_F_B64_WRITE_ASN1 = 0;
+static const int ASN1_F_SMIME_READ_ASN1 = 0;
+static const int ASN1_F_SMIME_TEXT = 0;
+static const int ASN1_R_NO_CONTENT_TYPE = 0;
+static const int ASN1_R_NO_MULTIPART_BODY_FAILURE = 0;
+static const int ASN1_R_NO_MULTIPART_BOUNDARY = 0;
#endif
+
+// OpenSSL 0.9.8c+
+#ifdef EVP_F_CAMELLIA_INIT_KEY
+static const long Cryptography_HAS_098C_CAMELLIA_CODES = 1;
+#else
+static const long Cryptography_HAS_098C_CAMELLIA_CODES = 0;
+static const int EVP_F_CAMELLIA_INIT_KEY = 0;
+static const int EVP_R_CAMELLIA_KEY_SETUP_FAILED = 0;
+#endif
+
"""
CONDITIONAL_NAMES = {
"Cryptography_HAS_REMOVE_THREAD_STATE": [
"ERR_remove_thread_state"
],
+ "Cryptography_HAS_098H_ERROR_CODES": [
+ "ASN1_F_B64_READ_ASN1",
+ "ASN1_F_B64_WRITE_ASN1",
+ "ASN1_F_SMIME_READ_ASN1",
+ "ASN1_F_SMIME_TEXT",
+ "ASN1_R_NO_CONTENT_TYPE",
+ "ASN1_R_NO_MULTIPART_BODY_FAILURE",
+ "ASN1_R_NO_MULTIPART_BOUNDARY",
+ ],
+ "Cryptography_HAS_098C_CAMELLIA_CODES": [
+ "EVP_F_CAMELLIA_INIT_KEY",
+ "EVP_R_CAMELLIA_KEY_SETUP_FAILED"
+ ]
}
diff --git a/cryptography/hazmat/bindings/openssl/evp.py b/cryptography/hazmat/bindings/openssl/evp.py
index a5e19c3a..88cf5c34 100644
--- a/cryptography/hazmat/bindings/openssl/evp.py
+++ b/cryptography/hazmat/bindings/openssl/evp.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/evp.h>
"""
@@ -64,8 +66,6 @@ int EVP_CipherUpdate(EVP_CIPHER_CTX *, unsigned char *, int *,
const unsigned char *, int);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *, unsigned char *, int *);
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
-const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *);
-int EVP_CIPHER_block_size(const EVP_CIPHER *);
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *);
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *);
@@ -79,8 +79,6 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
int EVP_MD_CTX_cleanup(EVP_MD_CTX *);
void EVP_MD_CTX_destroy(EVP_MD_CTX *);
const EVP_MD *EVP_get_digestbyname(const char *);
-const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *);
-int EVP_MD_size(const EVP_MD *);
EVP_PKEY *EVP_PKEY_new(void);
void EVP_PKEY_free(EVP_PKEY *);
@@ -143,6 +141,23 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *, unsigned char *, size_t *,
int EVP_PKEY_verify_init(EVP_PKEY_CTX *);
int EVP_PKEY_verify(EVP_PKEY_CTX *, const unsigned char *, size_t,
const unsigned char *, size_t);
+int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *);
+int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *);
+
+/* The following were macros in 0.9.8e. Once we drop support for RHEL/CentOS 5
+ we should move these back to FUNCTIONS. */
+const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *);
+int EVP_CIPHER_block_size(const EVP_CIPHER *);
+const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *);
+int EVP_MD_size(const EVP_MD *);
+
+/* Must be in macros because EVP_PKEY_CTX is undefined in 0.9.8 */
+int Cryptography_EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen);
+int Cryptography_EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen);
"""
CUSTOMIZATIONS = """
@@ -154,9 +169,24 @@ const long EVP_CTRL_GCM_GET_TAG = -1;
const long EVP_CTRL_GCM_SET_TAG = -1;
const long EVP_CTRL_GCM_SET_IVLEN = -1;
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10000000
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
const long Cryptography_HAS_PBKDF2_HMAC = 1;
const long Cryptography_HAS_PKEY_CTX = 1;
+
+/* OpenSSL 0.9.8 defines EVP_PKEY_encrypt and EVP_PKEY_decrypt functions,
+ but they are a completely different signature from the ones in 1.0.0+.
+ These wrapper functions allows us to safely declare them on any version and
+ conditionally remove them on 0.9.8. */
+int Cryptography_EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen) {
+ return EVP_PKEY_encrypt(ctx, out, outlen, in, inlen);
+}
+int Cryptography_EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
+ size_t *outlen, const unsigned char *in,
+ size_t inlen) {
+ return EVP_PKEY_decrypt(ctx, out, outlen, in, inlen);
+}
#else
const long Cryptography_HAS_PBKDF2_HMAC = 0;
int (*PKCS5_PBKDF2_HMAC)(const char *, int, const unsigned char *, int, int,
@@ -174,6 +204,12 @@ EVP_PKEY_CTX *(*EVP_PKEY_CTX_new)(EVP_PKEY *, ENGINE *) = NULL;
EVP_PKEY_CTX *(*EVP_PKEY_CTX_new_id)(int, ENGINE *) = NULL;
EVP_PKEY_CTX *(*EVP_PKEY_CTX_dup)(EVP_PKEY_CTX *) = NULL;
void (*EVP_PKEY_CTX_free)(EVP_PKEY_CTX *) = NULL;
+int (*EVP_PKEY_encrypt_init)(EVP_PKEY_CTX *) = NULL;
+int (*EVP_PKEY_decrypt_init)(EVP_PKEY_CTX *) = NULL;
+int (*Cryptography_EVP_PKEY_encrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *,
+ const unsigned char *, size_t) = NULL;
+int (*Cryptography_EVP_PKEY_decrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *,
+ const unsigned char *, size_t) = NULL;
#endif
"""
@@ -195,6 +231,10 @@ CONDITIONAL_NAMES = {
"EVP_PKEY_sign_init",
"EVP_PKEY_verify",
"EVP_PKEY_verify_init",
+ "Cryptography_EVP_PKEY_encrypt",
+ "EVP_PKEY_encrypt_init",
+ "Cryptography_EVP_PKEY_decrypt",
+ "EVP_PKEY_decrypt_init",
"EVP_PKEY_CTX_set_signature_md",
]
}
diff --git a/cryptography/hazmat/bindings/openssl/hmac.py b/cryptography/hazmat/bindings/openssl/hmac.py
index 4b81c9df..6a64b92c 100644
--- a/cryptography/hazmat/bindings/openssl/hmac.py
+++ b/cryptography/hazmat/bindings/openssl/hmac.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/hmac.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/nid.py b/cryptography/hazmat/bindings/openssl/nid.py
index 40aed19f..ea6fd4d6 100644
--- a/cryptography/hazmat/bindings/openssl/nid.py
+++ b/cryptography/hazmat/bindings/openssl/nid.py
@@ -11,9 +11,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = ""
TYPES = """
+static const int Cryptography_HAS_ECDSA_SHA2_NIDS;
+
static const int NID_undef;
static const int NID_dsa;
static const int NID_dsaWithSHA;
@@ -38,6 +42,148 @@ static const int NID_ecdsa_with_SHA512;
static const int NID_crl_reason;
static const int NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
static const int NID_subject_alt_name;
+static const int NID_X9_62_c2pnb163v1;
+static const int NID_X9_62_c2pnb163v2;
+static const int NID_X9_62_c2pnb163v3;
+static const int NID_X9_62_c2pnb176v1;
+static const int NID_X9_62_c2tnb191v1;
+static const int NID_X9_62_c2tnb191v2;
+static const int NID_X9_62_c2tnb191v3;
+static const int NID_X9_62_c2onb191v4;
+static const int NID_X9_62_c2onb191v5;
+static const int NID_X9_62_c2pnb208w1;
+static const int NID_X9_62_c2tnb239v1;
+static const int NID_X9_62_c2tnb239v2;
+static const int NID_X9_62_c2tnb239v3;
+static const int NID_X9_62_c2onb239v4;
+static const int NID_X9_62_c2onb239v5;
+static const int NID_X9_62_c2pnb272w1;
+static const int NID_X9_62_c2pnb304w1;
+static const int NID_X9_62_c2tnb359v1;
+static const int NID_X9_62_c2pnb368w1;
+static const int NID_X9_62_c2tnb431r1;
+static const int NID_X9_62_prime192v1;
+static const int NID_X9_62_prime192v2;
+static const int NID_X9_62_prime192v3;
+static const int NID_X9_62_prime239v1;
+static const int NID_X9_62_prime239v2;
+static const int NID_X9_62_prime239v3;
+static const int NID_X9_62_prime256v1;
+static const int NID_secp112r1;
+static const int NID_secp112r2;
+static const int NID_secp128r1;
+static const int NID_secp128r2;
+static const int NID_secp160k1;
+static const int NID_secp160r1;
+static const int NID_secp160r2;
+static const int NID_sect163k1;
+static const int NID_sect163r1;
+static const int NID_sect163r2;
+static const int NID_secp192k1;
+static const int NID_secp224k1;
+static const int NID_secp224r1;
+static const int NID_secp256k1;
+static const int NID_secp384r1;
+static const int NID_secp521r1;
+static const int NID_sect113r1;
+static const int NID_sect113r2;
+static const int NID_sect131r1;
+static const int NID_sect131r2;
+static const int NID_sect193r1;
+static const int NID_sect193r2;
+static const int NID_sect233k1;
+static const int NID_sect233r1;
+static const int NID_sect239k1;
+static const int NID_sect283k1;
+static const int NID_sect283r1;
+static const int NID_sect409k1;
+static const int NID_sect409r1;
+static const int NID_sect571k1;
+static const int NID_sect571r1;
+static const int NID_wap_wsg_idm_ecid_wtls1;
+static const int NID_wap_wsg_idm_ecid_wtls3;
+static const int NID_wap_wsg_idm_ecid_wtls4;
+static const int NID_wap_wsg_idm_ecid_wtls5;
+static const int NID_wap_wsg_idm_ecid_wtls6;
+static const int NID_wap_wsg_idm_ecid_wtls7;
+static const int NID_wap_wsg_idm_ecid_wtls8;
+static const int NID_wap_wsg_idm_ecid_wtls9;
+static const int NID_wap_wsg_idm_ecid_wtls10;
+static const int NID_wap_wsg_idm_ecid_wtls11;
+static const int NID_wap_wsg_idm_ecid_wtls12;
+static const int NID_ipsec3;
+static const int NID_ipsec4;
+static const char *const SN_X9_62_c2pnb163v1;
+static const char *const SN_X9_62_c2pnb163v2;
+static const char *const SN_X9_62_c2pnb163v3;
+static const char *const SN_X9_62_c2pnb176v1;
+static const char *const SN_X9_62_c2tnb191v1;
+static const char *const SN_X9_62_c2tnb191v2;
+static const char *const SN_X9_62_c2tnb191v3;
+static const char *const SN_X9_62_c2onb191v4;
+static const char *const SN_X9_62_c2onb191v5;
+static const char *const SN_X9_62_c2pnb208w1;
+static const char *const SN_X9_62_c2tnb239v1;
+static const char *const SN_X9_62_c2tnb239v2;
+static const char *const SN_X9_62_c2tnb239v3;
+static const char *const SN_X9_62_c2onb239v4;
+static const char *const SN_X9_62_c2onb239v5;
+static const char *const SN_X9_62_c2pnb272w1;
+static const char *const SN_X9_62_c2pnb304w1;
+static const char *const SN_X9_62_c2tnb359v1;
+static const char *const SN_X9_62_c2pnb368w1;
+static const char *const SN_X9_62_c2tnb431r1;
+static const char *const SN_X9_62_prime192v1;
+static const char *const SN_X9_62_prime192v2;
+static const char *const SN_X9_62_prime192v3;
+static const char *const SN_X9_62_prime239v1;
+static const char *const SN_X9_62_prime239v2;
+static const char *const SN_X9_62_prime239v3;
+static const char *const SN_X9_62_prime256v1;
+static const char *const SN_secp112r1;
+static const char *const SN_secp112r2;
+static const char *const SN_secp128r1;
+static const char *const SN_secp128r2;
+static const char *const SN_secp160k1;
+static const char *const SN_secp160r1;
+static const char *const SN_secp160r2;
+static const char *const SN_sect163k1;
+static const char *const SN_sect163r1;
+static const char *const SN_sect163r2;
+static const char *const SN_secp192k1;
+static const char *const SN_secp224k1;
+static const char *const SN_secp224r1;
+static const char *const SN_secp256k1;
+static const char *const SN_secp384r1;
+static const char *const SN_secp521r1;
+static const char *const SN_sect113r1;
+static const char *const SN_sect113r2;
+static const char *const SN_sect131r1;
+static const char *const SN_sect131r2;
+static const char *const SN_sect193r1;
+static const char *const SN_sect193r2;
+static const char *const SN_sect233k1;
+static const char *const SN_sect233r1;
+static const char *const SN_sect239k1;
+static const char *const SN_sect283k1;
+static const char *const SN_sect283r1;
+static const char *const SN_sect409k1;
+static const char *const SN_sect409r1;
+static const char *const SN_sect571k1;
+static const char *const SN_sect571r1;
+static const char *const SN_wap_wsg_idm_ecid_wtls1;
+static const char *const SN_wap_wsg_idm_ecid_wtls3;
+static const char *const SN_wap_wsg_idm_ecid_wtls4;
+static const char *const SN_wap_wsg_idm_ecid_wtls5;
+static const char *const SN_wap_wsg_idm_ecid_wtls6;
+static const char *const SN_wap_wsg_idm_ecid_wtls7;
+static const char *const SN_wap_wsg_idm_ecid_wtls8;
+static const char *const SN_wap_wsg_idm_ecid_wtls9;
+static const char *const SN_wap_wsg_idm_ecid_wtls10;
+static const char *const SN_wap_wsg_idm_ecid_wtls11;
+static const char *const SN_wap_wsg_idm_ecid_wtls12;
+static const char *const SN_ipsec3;
+static const char *const SN_ipsec4;
"""
FUNCTIONS = """
@@ -47,6 +193,23 @@ MACROS = """
"""
CUSTOMIZATIONS = """
+// OpenSSL 0.9.8g+
+#if OPENSSL_VERSION_NUMBER >= 0x0090807fL
+static const long Cryptography_HAS_ECDSA_SHA2_NIDS = 1;
+#else
+static const long Cryptography_HAS_ECDSA_SHA2_NIDS = 0;
+static const int NID_ecdsa_with_SHA224 = 0;
+static const int NID_ecdsa_with_SHA256 = 0;
+static const int NID_ecdsa_with_SHA384 = 0;
+static const int NID_ecdsa_with_SHA512 = 0;
+#endif
"""
-CONDITIONAL_NAMES = {}
+CONDITIONAL_NAMES = {
+ "Cryptography_HAS_ECDSA_SHA2_NIDS": [
+ "NID_ecdsa_with_SHA224",
+ "NID_ecdsa_with_SHA256",
+ "NID_ecdsa_with_SHA384",
+ "NID_ecdsa_with_SHA512",
+ ],
+}
diff --git a/cryptography/hazmat/bindings/openssl/objects.py b/cryptography/hazmat/bindings/openssl/objects.py
index 0abc42d6..557c0158 100644
--- a/cryptography/hazmat/bindings/openssl/objects.py
+++ b/cryptography/hazmat/bindings/openssl/objects.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/objects.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/opensslv.py b/cryptography/hazmat/bindings/openssl/opensslv.py
index 397f4ca2..e4aa6212 100644
--- a/cryptography/hazmat/bindings/openssl/opensslv.py
+++ b/cryptography/hazmat/bindings/openssl/opensslv.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/opensslv.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/osrandom_engine.py b/cryptography/hazmat/bindings/openssl/osrandom_engine.py
index 0903a4bf..462997cc 100644
--- a/cryptography/hazmat/bindings/openssl/osrandom_engine.py
+++ b/cryptography/hazmat/bindings/openssl/osrandom_engine.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#ifdef _WIN32
#include <Wincrypt.h>
diff --git a/cryptography/hazmat/bindings/openssl/pem.py b/cryptography/hazmat/bindings/openssl/pem.py
index 942cba34..e42fc6fe 100644
--- a/cryptography/hazmat/bindings/openssl/pem.py
+++ b/cryptography/hazmat/bindings/openssl/pem.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/pem.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/pkcs12.py b/cryptography/hazmat/bindings/openssl/pkcs12.py
index bd01e756..a8f106f6 100644
--- a/cryptography/hazmat/bindings/openssl/pkcs12.py
+++ b/cryptography/hazmat/bindings/openssl/pkcs12.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/pkcs12.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/pkcs7.py b/cryptography/hazmat/bindings/openssl/pkcs7.py
index 43f9540b..1343e566 100644
--- a/cryptography/hazmat/bindings/openssl/pkcs7.py
+++ b/cryptography/hazmat/bindings/openssl/pkcs7.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/pkcs7.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/rand.py b/cryptography/hazmat/bindings/openssl/rand.py
index 0e645fbc..7b1be9df 100644
--- a/cryptography/hazmat/bindings/openssl/rand.py
+++ b/cryptography/hazmat/bindings/openssl/rand.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/rand.h>
"""
diff --git a/cryptography/hazmat/bindings/openssl/rsa.py b/cryptography/hazmat/bindings/openssl/rsa.py
index 359305c6..c6356101 100644
--- a/cryptography/hazmat/bindings/openssl/rsa.py
+++ b/cryptography/hazmat/bindings/openssl/rsa.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/rsa.h>
"""
@@ -37,6 +39,7 @@ static const int RSA_PKCS1_PSS_PADDING;
static const int RSA_F4;
static const int Cryptography_HAS_PSS_PADDING;
+static const int Cryptography_HAS_MGF1_MD;
"""
FUNCTIONS = """
@@ -70,6 +73,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *, int, const unsigned char *,
MACROS = """
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *, int);
int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *, int);
+int EVP_PKEY_CTX_set_rsa_mgf1_md(EVP_PKEY_CTX *, EVP_MD *);
"""
CUSTOMIZATIONS = """
@@ -82,6 +86,12 @@ int (*EVP_PKEY_CTX_set_rsa_padding)(EVP_PKEY_CTX *, int) = NULL;
int (*EVP_PKEY_CTX_set_rsa_pss_saltlen)(EVP_PKEY_CTX *, int) = NULL;
static const long RSA_PKCS1_PSS_PADDING = 0;
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x1000100f
+static const long Cryptography_HAS_MGF1_MD = 1;
+#else
+static const long Cryptography_HAS_MGF1_MD = 0;
+int (*EVP_PKEY_CTX_set_rsa_mgf1_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL;
+#endif
"""
CONDITIONAL_NAMES = {
@@ -92,4 +102,7 @@ CONDITIONAL_NAMES = {
"Cryptography_HAS_PSS_PADDING": [
"RSA_PKCS1_PSS_PADDING",
],
+ "Cryptography_HAS_MGF1_MD": [
+ "EVP_PKEY_CTX_set_rsa_mgf1_md",
+ ],
}
diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py
index c0a6f016..094310f3 100644
--- a/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/cryptography/hazmat/bindings/openssl/ssl.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/ssl.h>
"""
@@ -19,107 +21,115 @@ TYPES = """
/*
* Internally invented symbols to tell which versions of SSL/TLS are supported.
*/
-static const int Cryptography_HAS_SSL2;
-static const int Cryptography_HAS_TLSv1_1;
-static const int Cryptography_HAS_TLSv1_2;
+static const long Cryptography_HAS_SSL2;
+static const long Cryptography_HAS_TLSv1_1;
+static const long Cryptography_HAS_TLSv1_2;
/* Internally invented symbol to tell us if SNI is supported */
-static const int Cryptography_HAS_TLSEXT_HOSTNAME;
+static const long Cryptography_HAS_TLSEXT_HOSTNAME;
/* Internally invented symbol to tell us if SSL_MODE_RELEASE_BUFFERS is
* supported
*/
-static const int Cryptography_HAS_RELEASE_BUFFERS;
+static const long Cryptography_HAS_RELEASE_BUFFERS;
/* Internally invented symbol to tell us if SSL_OP_NO_COMPRESSION is
* supported
*/
-static const int Cryptography_HAS_OP_NO_COMPRESSION;
-
-static const int Cryptography_HAS_SSL_OP_MSIE_SSLV2_RSA_PADDING;
-
-static const int SSL_FILETYPE_PEM;
-static const int SSL_FILETYPE_ASN1;
-static const int SSL_ERROR_NONE;
-static const int SSL_ERROR_ZERO_RETURN;
-static const int SSL_ERROR_WANT_READ;
-static const int SSL_ERROR_WANT_WRITE;
-static const int SSL_ERROR_WANT_X509_LOOKUP;
-static const int SSL_ERROR_SYSCALL;
-static const int SSL_ERROR_SSL;
-static const int SSL_SENT_SHUTDOWN;
-static const int SSL_RECEIVED_SHUTDOWN;
-static const int SSL_OP_NO_SSLv2;
-static const int SSL_OP_NO_SSLv3;
-static const int SSL_OP_NO_TLSv1;
-static const int SSL_OP_NO_TLSv1_1;
-static const int SSL_OP_NO_TLSv1_2;
-static const int SSL_OP_NO_COMPRESSION;
-static const int SSL_OP_SINGLE_DH_USE;
-static const int SSL_OP_EPHEMERAL_RSA;
-static const int SSL_OP_MICROSOFT_SESS_ID_BUG;
-static const int SSL_OP_NETSCAPE_CHALLENGE_BUG;
-static const int SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
-static const int SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
-static const int SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
-static const int SSL_OP_MSIE_SSLV2_RSA_PADDING;
-static const int SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
-static const int SSL_OP_TLS_D5_BUG;
-static const int SSL_OP_TLS_BLOCK_PADDING_BUG;
-static const int SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
-static const int SSL_OP_CIPHER_SERVER_PREFERENCE;
-static const int SSL_OP_TLS_ROLLBACK_BUG;
-static const int SSL_OP_PKCS1_CHECK_1;
-static const int SSL_OP_PKCS1_CHECK_2;
-static const int SSL_OP_NETSCAPE_CA_DN_BUG;
-static const int SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
-static const int SSL_OP_NO_QUERY_MTU;
-static const int SSL_OP_COOKIE_EXCHANGE;
-static const int SSL_OP_NO_TICKET;
-static const int SSL_OP_ALL;
-static const int SSL_OP_SINGLE_ECDH_USE;
-static const int SSL_VERIFY_PEER;
-static const int SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-static const int SSL_VERIFY_CLIENT_ONCE;
-static const int SSL_VERIFY_NONE;
-static const int SSL_SESS_CACHE_OFF;
-static const int SSL_SESS_CACHE_CLIENT;
-static const int SSL_SESS_CACHE_SERVER;
-static const int SSL_SESS_CACHE_BOTH;
-static const int SSL_SESS_CACHE_NO_AUTO_CLEAR;
-static const int SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
-static const int SSL_SESS_CACHE_NO_INTERNAL_STORE;
-static const int SSL_SESS_CACHE_NO_INTERNAL;
-static const int SSL_ST_CONNECT;
-static const int SSL_ST_ACCEPT;
-static const int SSL_ST_MASK;
-static const int SSL_ST_INIT;
-static const int SSL_ST_BEFORE;
-static const int SSL_ST_OK;
-static const int SSL_ST_RENEGOTIATE;
-static const int SSL_CB_LOOP;
-static const int SSL_CB_EXIT;
-static const int SSL_CB_READ;
-static const int SSL_CB_WRITE;
-static const int SSL_CB_ALERT;
-static const int SSL_CB_READ_ALERT;
-static const int SSL_CB_WRITE_ALERT;
-static const int SSL_CB_ACCEPT_LOOP;
-static const int SSL_CB_ACCEPT_EXIT;
-static const int SSL_CB_CONNECT_LOOP;
-static const int SSL_CB_CONNECT_EXIT;
-static const int SSL_CB_HANDSHAKE_START;
-static const int SSL_CB_HANDSHAKE_DONE;
-static const int SSL_MODE_RELEASE_BUFFERS;
-static const int SSL_MODE_ENABLE_PARTIAL_WRITE;
-static const int SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
-static const int SSL_MODE_AUTO_RETRY;
-static const int SSL3_RANDOM_SIZE;
+static const long Cryptography_HAS_OP_NO_COMPRESSION;
+
+static const long Cryptography_HAS_SSL_OP_MSIE_SSLV2_RSA_PADDING;
+static const long Cryptography_HAS_SSL_SET_SSL_CTX;
+static const long Cryptography_HAS_SSL_OP_NO_TICKET;
+static const long Cryptography_HAS_NETBSD_D1_METH;
+static const long Cryptography_HAS_NEXTPROTONEG;
+
+static const long SSL_FILETYPE_PEM;
+static const long SSL_FILETYPE_ASN1;
+static const long SSL_ERROR_NONE;
+static const long SSL_ERROR_ZERO_RETURN;
+static const long SSL_ERROR_WANT_READ;
+static const long SSL_ERROR_WANT_WRITE;
+static const long SSL_ERROR_WANT_X509_LOOKUP;
+static const long SSL_ERROR_SYSCALL;
+static const long SSL_ERROR_SSL;
+static const long SSL_SENT_SHUTDOWN;
+static const long SSL_RECEIVED_SHUTDOWN;
+static const long SSL_OP_NO_SSLv2;
+static const long SSL_OP_NO_SSLv3;
+static const long SSL_OP_NO_TLSv1;
+static const long SSL_OP_NO_TLSv1_1;
+static const long SSL_OP_NO_TLSv1_2;
+static const long SSL_OP_NO_COMPRESSION;
+static const long SSL_OP_SINGLE_DH_USE;
+static const long SSL_OP_EPHEMERAL_RSA;
+static const long SSL_OP_MICROSOFT_SESS_ID_BUG;
+static const long SSL_OP_NETSCAPE_CHALLENGE_BUG;
+static const long SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
+static const long SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG;
+static const long SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER;
+static const long SSL_OP_MSIE_SSLV2_RSA_PADDING;
+static const long SSL_OP_SSLEAY_080_CLIENT_DH_BUG;
+static const long SSL_OP_TLS_D5_BUG;
+static const long SSL_OP_TLS_BLOCK_PADDING_BUG;
+static const long SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+static const long SSL_OP_CIPHER_SERVER_PREFERENCE;
+static const long SSL_OP_TLS_ROLLBACK_BUG;
+static const long SSL_OP_PKCS1_CHECK_1;
+static const long SSL_OP_PKCS1_CHECK_2;
+static const long SSL_OP_NETSCAPE_CA_DN_BUG;
+static const long SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG;
+static const long SSL_OP_NO_QUERY_MTU;
+static const long SSL_OP_COOKIE_EXCHANGE;
+static const long SSL_OP_NO_TICKET;
+static const long SSL_OP_ALL;
+static const long SSL_OP_SINGLE_ECDH_USE;
+static const long SSL_VERIFY_PEER;
+static const long SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+static const long SSL_VERIFY_CLIENT_ONCE;
+static const long SSL_VERIFY_NONE;
+static const long SSL_SESS_CACHE_OFF;
+static const long SSL_SESS_CACHE_CLIENT;
+static const long SSL_SESS_CACHE_SERVER;
+static const long SSL_SESS_CACHE_BOTH;
+static const long SSL_SESS_CACHE_NO_AUTO_CLEAR;
+static const long SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
+static const long SSL_SESS_CACHE_NO_INTERNAL_STORE;
+static const long SSL_SESS_CACHE_NO_INTERNAL;
+static const long SSL_ST_CONNECT;
+static const long SSL_ST_ACCEPT;
+static const long SSL_ST_MASK;
+static const long SSL_ST_INIT;
+static const long SSL_ST_BEFORE;
+static const long SSL_ST_OK;
+static const long SSL_ST_RENEGOTIATE;
+static const long SSL_CB_LOOP;
+static const long SSL_CB_EXIT;
+static const long SSL_CB_READ;
+static const long SSL_CB_WRITE;
+static const long SSL_CB_ALERT;
+static const long SSL_CB_READ_ALERT;
+static const long SSL_CB_WRITE_ALERT;
+static const long SSL_CB_ACCEPT_LOOP;
+static const long SSL_CB_ACCEPT_EXIT;
+static const long SSL_CB_CONNECT_LOOP;
+static const long SSL_CB_CONNECT_EXIT;
+static const long SSL_CB_HANDSHAKE_START;
+static const long SSL_CB_HANDSHAKE_DONE;
+static const long SSL_MODE_RELEASE_BUFFERS;
+static const long SSL_MODE_ENABLE_PARTIAL_WRITE;
+static const long SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
+static const long SSL_MODE_AUTO_RETRY;
+static const long SSL3_RANDOM_SIZE;
typedef ... X509_STORE_CTX;
-static const int X509_V_OK;
-static const int X509_V_ERR_APPLICATION_VERIFICATION;
+static const long X509_V_OK;
+static const long X509_V_ERR_APPLICATION_VERIFICATION;
typedef ... SSL_METHOD;
-typedef ... SSL_CTX;
+typedef struct ssl_st {
+ int version;
+ int type;
+ ...;
+} SSL_CTX;
typedef struct {
int master_key_length;
@@ -140,7 +150,7 @@ typedef struct {
...;
} SSL;
-static const int TLSEXT_NAMETYPE_host_name;
+static const long TLSEXT_NAMETYPE_host_name;
typedef ... SSL_CIPHER;
"""
@@ -150,7 +160,6 @@ void SSL_load_error_strings(void);
int SSL_library_init(void);
/* SSL */
-SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *);
SSL_SESSION *SSL_get1_session(SSL *);
int SSL_set_session(SSL *, SSL_SESSION *);
int SSL_get_verify_mode(const SSL *);
@@ -188,8 +197,6 @@ int SSL_CTX_set_default_verify_paths(SSL_CTX *);
void SSL_CTX_set_verify(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *));
void SSL_CTX_set_verify_depth(SSL_CTX *, int);
int (*SSL_CTX_get_verify_callback(const SSL_CTX *))(int, X509_STORE_CTX *);
-void SSL_CTX_set_info_callback(SSL_CTX *, void (*)(const SSL *, int, int));
-void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int);
int SSL_CTX_get_verify_mode(const SSL_CTX *);
int SSL_CTX_get_verify_depth(const SSL_CTX *);
int SSL_CTX_set_cipher_list(SSL_CTX *, const char *);
@@ -308,6 +315,39 @@ void SSL_CTX_set_tlsext_servername_callback(
int (*)(const SSL *, int *, void *));
long SSL_session_reused(SSL *);
+
+/* The following were macros in 0.9.8e. Once we drop support for RHEL/CentOS 5
+ we should move these back to FUNCTIONS. */
+void SSL_CTX_set_info_callback(SSL_CTX *, void (*)(const SSL *, int, int));
+void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int);
+/* This function does not exist in 0.9.8e. Once we drop support for
+ RHEL/CentOS 5 this can be moved back to FUNCTIONS. */
+SSL_CTX *SSL_set_SSL_CTX(SSL *, SSL_CTX *);
+
+const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX*);
+
+/* NPN APIs were introduced in OpenSSL 1.0.1. To continue to support earlier
+ * versions some special handling of these is necessary.
+ */
+void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *,
+ int (*)(SSL *,
+ const unsigned char **,
+ unsigned int *,
+ void *),
+ void *);
+void SSL_CTX_set_next_proto_select_cb(SSL_CTX *,
+ int (*)(SSL *,
+ unsigned char **,
+ unsigned char *,
+ const unsigned char *,
+ unsigned int,
+ void *),
+ void *);
+int SSL_select_next_proto(unsigned char **, unsigned char *,
+ const unsigned char *, unsigned int,
+ const unsigned char *, unsigned int);
+void SSL_get0_next_proto_negotiated(const SSL *,
+ const unsigned char **, unsigned *);
"""
CUSTOMIZATIONS = """
@@ -375,6 +415,76 @@ const long SSL_OP_MSIE_SSLV2_RSA_PADDING = 0;
#ifdef OPENSSL_NO_EC
long (*SSL_CTX_set_tmp_ecdh)(SSL_CTX *, EC_KEY *) = NULL;
#endif
+
+#ifdef SSL_OP_NO_TICKET
+static const long Cryptography_HAS_SSL_OP_NO_TICKET = 1;
+#else
+static const long Cryptography_HAS_SSL_OP_NO_TICKET = 0;
+const long SSL_OP_NO_TICKET = 0;
+#endif
+
+// OpenSSL 0.9.8f+
+#if OPENSSL_VERSION_NUMBER >= 0x00908070L
+static const long Cryptography_HAS_SSL_SET_SSL_CTX = 1;
+#else
+static const long Cryptography_HAS_SSL_SET_SSL_CTX = 0;
+static const long TLSEXT_NAMETYPE_host_name = 0;
+SSL_CTX *(*SSL_set_SSL_CTX)(SSL *, SSL_CTX *) = NULL;
+#endif
+
+/* NetBSD shipped without including d1_meth.c. This workaround checks to see
+ if the version of NetBSD we're currently running on is old enough to
+ have the bug and provides an empty implementation so we can link and
+ then remove the function from the ffi object. */
+#ifdef __NetBSD__
+# include <sys/param.h>
+# if (__NetBSD_Version__ < 699003800)
+static const long Cryptography_HAS_NETBSD_D1_METH = 0;
+const SSL_METHOD *DTLSv1_method(void) {
+ return NULL;
+}
+# else
+static const long Cryptography_HAS_NETBSD_D1_METH = 1;
+# endif
+#else
+static const long Cryptography_HAS_NETBSD_D1_METH = 1;
+#endif
+
+// Workaround for #794 caused by cffi const** bug.
+const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX* ctx) {
+ return ctx->method;
+}
+
+/* Because OPENSSL defines macros that claim lack of support for things, rather
+ * than macros that claim support for things, we need to do a version check in
+ * addition to a definition check. NPN was added in 1.0.1: for any version
+ * before that, there is no compatibility.
+ */
+#if defined(OPENSSL_NO_NEXTPROTONEG) || OPENSSL_VERSION_NUMBER < 0x1000100fL
+static const long Cryptography_HAS_NEXTPROTONEG = 0;
+void (*SSL_CTX_set_next_protos_advertised_cb)(SSL_CTX *,
+ int (*)(SSL *,
+ const unsigned char **,
+ unsigned int *,
+ void *),
+ void *) = NULL;
+void (*SSL_CTX_set_next_proto_select_cb)(SSL_CTX *,
+ int (*)(SSL *,
+ unsigned char **,
+ unsigned char *,
+ const unsigned char *,
+ unsigned int,
+ void *),
+ void *) = NULL;
+int (*SSL_select_next_proto)(unsigned char **, unsigned char *,
+ const unsigned char *, unsigned int,
+ const unsigned char *, unsigned int) = NULL;
+void (*SSL_get0_next_proto_negotiated)(const SSL *,
+ const unsigned char **,
+ unsigned *) = NULL;
+#else
+static const long Cryptography_HAS_NEXTPROTONEG = 1;
+#endif
"""
CONDITIONAL_NAMES = {
@@ -418,5 +528,25 @@ CONDITIONAL_NAMES = {
"Cryptography_HAS_EC": [
"SSL_CTX_set_tmp_ecdh",
+ ],
+
+ "Cryptography_HAS_SSL_OP_NO_TICKET": [
+ "SSL_OP_NO_TICKET",
+ ],
+
+ "Cryptography_HAS_SSL_SET_SSL_CTX": [
+ "SSL_set_SSL_CTX",
+ "TLSEXT_NAMETYPE_host_name",
+ ],
+
+ "Cryptography_HAS_NETBSD_D1_METH": [
+ "DTLSv1_method",
+ ],
+
+ "Cryptography_HAS_NEXTPROTONEG": [
+ "SSL_CTX_set_next_protos_advertised_cb",
+ "SSL_CTX_set_next_proto_select_cb",
+ "SSL_select_next_proto",
+ "SSL_get0_next_proto_negotiated",
]
}
diff --git a/cryptography/hazmat/bindings/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py
index 95c88b3a..e800d272 100644
--- a/cryptography/hazmat/bindings/openssl/x509.py
+++ b/cryptography/hazmat/bindings/openssl/x509.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/ssl.h>
@@ -120,8 +122,6 @@ int X509_REQ_set_pubkey(X509_REQ *, EVP_PKEY *);
int X509_REQ_sign(X509_REQ *, EVP_PKEY *, const EVP_MD *);
int X509_REQ_verify(X509_REQ *, EVP_PKEY *);
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *);
-int X509_REQ_add_extensions(X509_REQ *, X509_EXTENSIONS *);
-X509_EXTENSIONS *X509_REQ_get_extensions(X509_REQ *);
int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long);
int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int);
@@ -208,9 +208,18 @@ X509_REVOKED *sk_X509_REVOKED_value(Cryptography_STACK_OF_X509_REVOKED *, int);
/* These aren't macros these arguments are all const X on openssl > 1.0.x */
int X509_CRL_set_lastUpdate(X509_CRL *, ASN1_TIME *);
int X509_CRL_set_nextUpdate(X509_CRL *, ASN1_TIME *);
+
+/* these use STACK_OF(X509_EXTENSION) in 0.9.8e. Once we drop support for
+ 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 *);
"""
CUSTOMIZATIONS = """
+// OpenSSL 0.9.8e does not have this definition
+#if OPENSSL_VERSION_NUMBER <= 0x0090805fL
+typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
+#endif
"""
CONDITIONAL_NAMES = {}
diff --git a/cryptography/hazmat/bindings/openssl/x509name.py b/cryptography/hazmat/bindings/openssl/x509name.py
index bf627d61..50abee2a 100644
--- a/cryptography/hazmat/bindings/openssl/x509name.py
+++ b/cryptography/hazmat/bindings/openssl/x509name.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/x509.h>
diff --git a/cryptography/hazmat/bindings/openssl/x509v3.py b/cryptography/hazmat/bindings/openssl/x509v3.py
index 6d2d2361..02ec250a 100644
--- a/cryptography/hazmat/bindings/openssl/x509v3.py
+++ b/cryptography/hazmat/bindings/openssl/x509v3.py
@@ -11,6 +11,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
INCLUDES = """
#include <openssl/x509v3.h>
"""
diff --git a/cryptography/hazmat/bindings/utils.py b/cryptography/hazmat/bindings/utils.py
index b8253483..318b82bb 100644
--- a/cryptography/hazmat/bindings/utils.py
+++ b/cryptography/hazmat/bindings/utils.py
@@ -13,6 +13,8 @@
from __future__ import absolute_import, division, print_function
+import binascii
+
import sys
import cffi
@@ -50,7 +52,8 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
includes.append(module.INCLUDES)
customizations.append(module.CUSTOMIZATIONS)
- ffi.cdef("\n".join(types + functions + macros))
+ cdef_sources = types + functions + macros
+ ffi.cdef("\n".join(cdef_sources))
# We include functions here so that if we got any of their definitions
# wrong, the underlying C compiler will explode. In C you are allowed
@@ -60,14 +63,16 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
# is legal, but the following will fail to compile:
# int foo(int);
# int foo(short);
+ source = "\n".join(
+ [pre_include] +
+ includes +
+ [post_include] +
+ functions +
+ customizations
+ )
lib = ffi.verify(
- source="\n".join(
- [pre_include] +
- includes +
- [post_include] +
- functions +
- customizations
- ),
+ source=source,
+ modulename=_create_modulename(cdef_sources, source, sys.version),
libraries=libraries,
ext_package="cryptography",
)
@@ -81,3 +86,20 @@ def build_ffi(module_prefix, modules, pre_include, post_include, libraries):
delattr(lib, name)
return ffi, lib
+
+
+def _create_modulename(cdef_sources, source, sys_version):
+ """
+ cffi creates a modulename internally that incorporates the cffi version.
+ This will cause cryptography's wheels to break when the version of cffi
+ the user has does not match what was used when building the wheel. To
+ resolve this we build our own modulename that uses most of the same code
+ from cffi but elides the version key.
+ """
+ key = '\x00'.join([sys_version[:3], source] + cdef_sources)
+ key = key.encode('utf-8')
+ k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
+ k1 = k1.lstrip('0x').rstrip('L')
+ k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
+ k2 = k2.lstrip('0').rstrip('L')
+ return '_Cryptography_cffi_{0}{1}'.format(k1, k2)
diff --git a/cryptography/hazmat/primitives/__init__.py b/cryptography/hazmat/primitives/__init__.py
index e69de29b..2f420574 100644
--- a/cryptography/hazmat/primitives/__init__.py
+++ b/cryptography/hazmat/primitives/__init__.py
@@ -0,0 +1,14 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/primitives/asymmetric/__init__.py b/cryptography/hazmat/primitives/asymmetric/__init__.py
index e69de29b..2f420574 100644
--- a/cryptography/hazmat/primitives/asymmetric/__init__.py
+++ b/cryptography/hazmat/primitives/asymmetric/__init__.py
@@ -0,0 +1,14 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
new file mode 100644
index 00000000..974db0a6
--- /dev/null
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -0,0 +1,142 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+import six
+
+from cryptography import utils
+from cryptography.hazmat.primitives import interfaces
+
+
+def _check_dsa_parameters(modulus, subgroup_order, generator):
+ if (
+ not isinstance(modulus, six.integer_types) or
+ not isinstance(subgroup_order, six.integer_types) or
+ not isinstance(generator, six.integer_types)
+ ):
+ raise TypeError("DSA parameters must be integers")
+
+ if (utils.bit_length(modulus),
+ utils.bit_length(subgroup_order)) not in (
+ (1024, 160),
+ (2048, 256),
+ (3072, 256)):
+ raise ValueError("modulus and subgroup_order lengths must be "
+ "one of these pairs (1024, 160) or (2048, 256) "
+ "or (3072, 256)")
+
+ if generator <= 1 or generator >= modulus:
+ raise ValueError("generator must be > 1 and < modulus")
+
+
+@utils.register_interface(interfaces.DSAParameters)
+class DSAParameters(object):
+ def __init__(self, modulus, subgroup_order, generator):
+ _check_dsa_parameters(modulus, subgroup_order, generator)
+
+ self._modulus = modulus
+ self._subgroup_order = subgroup_order
+ self._generator = generator
+
+ @property
+ def modulus(self):
+ return self._modulus
+
+ @property
+ def subgroup_order(self):
+ return self._subgroup_order
+
+ @property
+ def generator(self):
+ return self._generator
+
+ @property
+ def p(self):
+ return self.modulus
+
+ @property
+ def q(self):
+ return self.subgroup_order
+
+ @property
+ def g(self):
+ return self.generator
+
+
+@utils.register_interface(interfaces.DSAPrivateKey)
+class DSAPrivateKey(object):
+ def __init__(self, modulus, subgroup_order, generator, x, y):
+ _check_dsa_parameters(modulus, subgroup_order, generator)
+ if (
+ not isinstance(x, six.integer_types) or
+ not isinstance(y, six.integer_types)
+ ):
+ raise TypeError("DSAPrivateKey arguments must be integers")
+
+ if x <= 0 or x >= subgroup_order:
+ raise ValueError("x must be > 0 and < subgroup_order")
+
+ if y != pow(generator, x, modulus):
+ raise ValueError("y must be equal to (generator ** x % modulus)")
+
+ self._modulus = modulus
+ self._subgroup_order = subgroup_order
+ self._generator = generator
+ self._x = x
+ self._y = y
+
+ @property
+ def key_size(self):
+ return utils.bit_length(self._modulus)
+
+ def public_key(self):
+ return DSAPublicKey(self._modulus, self._subgroup_order,
+ self._generator, self.y)
+
+ @property
+ def x(self):
+ return self._x
+
+ @property
+ def y(self):
+ return self._y
+
+ def parameters(self):
+ return DSAParameters(self._modulus, self._subgroup_order,
+ self._generator)
+
+
+@utils.register_interface(interfaces.DSAPublicKey)
+class DSAPublicKey(object):
+ def __init__(self, modulus, subgroup_order, generator, y):
+ _check_dsa_parameters(modulus, subgroup_order, generator)
+ if not isinstance(y, six.integer_types):
+ raise TypeError("y must be an integer")
+
+ self._modulus = modulus
+ self._subgroup_order = subgroup_order
+ self._generator = generator
+ self._y = y
+
+ @property
+ def key_size(self):
+ return utils.bit_length(self._modulus)
+
+ @property
+ def y(self):
+ return self._y
+
+ def parameters(self):
+ return DSAParameters(self._modulus, self._subgroup_order,
+ self._generator)
diff --git a/cryptography/hazmat/primitives/asymmetric/padding.py b/cryptography/hazmat/primitives/asymmetric/padding.py
index 6bafe314..02aff280 100644
--- a/cryptography/hazmat/primitives/asymmetric/padding.py
+++ b/cryptography/hazmat/primitives/asymmetric/padding.py
@@ -13,6 +13,8 @@
from __future__ import absolute_import, division, print_function
+import six
+
from cryptography import utils
from cryptography.hazmat.primitives import interfaces
@@ -20,3 +22,30 @@ from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.AsymmetricPadding)
class PKCS1v15(object):
name = "EMSA-PKCS1-v1_5"
+
+
+@utils.register_interface(interfaces.AsymmetricPadding)
+class PSS(object):
+ name = "EMSA-PSS"
+
+ def __init__(self, mgf):
+ self._mgf = mgf
+
+
+class MGF1(object):
+ MAX_LENGTH = object()
+
+ def __init__(self, algorithm, salt_length):
+ if not isinstance(algorithm, interfaces.HashAlgorithm):
+ raise TypeError("Expected instance of interfaces.HashAlgorithm.")
+
+ self._algorithm = algorithm
+
+ if (not isinstance(salt_length, six.integer_types) and
+ salt_length is not self.MAX_LENGTH):
+ raise TypeError("salt_length must be an integer")
+
+ if salt_length is not self.MAX_LENGTH and salt_length < 0:
+ raise ValueError("salt_length must be zero or greater")
+
+ self._salt_length = salt_length
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
index d8254046..94cc4645 100644
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -13,21 +13,14 @@
from __future__ import absolute_import, division, print_function
-import sys
-
import six
from cryptography import utils
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat.backends.interfaces import RSABackend
from cryptography.hazmat.primitives import interfaces
-def _bit_length(x):
- if sys.version_info >= (2, 7):
- return x.bit_length()
- else:
- return len(bin(x)) - (2 + (x <= 0))
-
-
@utils.register_interface(interfaces.RSAPublicKey)
class RSAPublicKey(object):
def __init__(self, public_exponent, modulus):
@@ -50,12 +43,18 @@ class RSAPublicKey(object):
self._modulus = modulus
def verifier(self, signature, padding, algorithm, backend):
+ if not isinstance(backend, RSABackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement RSABackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
return backend.create_rsa_verification_ctx(self, signature, padding,
algorithm)
@property
def key_size(self):
- return _bit_length(self.modulus)
+ return utils.bit_length(self.modulus)
@property
def public_exponent(self):
@@ -137,14 +136,26 @@ class RSAPrivateKey(object):
@classmethod
def generate(cls, public_exponent, key_size, backend):
+ if not isinstance(backend, RSABackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement RSABackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
return backend.generate_rsa_private_key(public_exponent, key_size)
def signer(self, padding, algorithm, backend):
+ if not isinstance(backend, RSABackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement RSABackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
return backend.create_rsa_signature_ctx(self, padding, algorithm)
@property
def key_size(self):
- return _bit_length(self.modulus)
+ return utils.bit_length(self.modulus)
def public_key(self):
return RSAPublicKey(self.public_exponent, self.modulus)
diff --git a/cryptography/hazmat/primitives/ciphers/algorithms.py b/cryptography/hazmat/primitives/ciphers/algorithms.py
index a5cfce92..2d37e0cf 100644
--- a/cryptography/hazmat/primitives/ciphers/algorithms.py
+++ b/cryptography/hazmat/primitives/ciphers/algorithms.py
@@ -116,3 +116,17 @@ class ARC4(object):
@property
def key_size(self):
return len(self.key) * 8
+
+
+@utils.register_interface(interfaces.CipherAlgorithm)
+class IDEA(object):
+ name = "IDEA"
+ block_size = 64
+ key_sizes = frozenset([128])
+
+ def __init__(self, key):
+ self.key = _verify_key_size(self, key)
+
+ @property
+ def key_size(self):
+ return len(self.key) * 8
diff --git a/cryptography/hazmat/primitives/ciphers/base.py b/cryptography/hazmat/primitives/ciphers/base.py
index d366e4cf..2274e945 100644
--- a/cryptography/hazmat/primitives/ciphers/base.py
+++ b/cryptography/hazmat/primitives/ciphers/base.py
@@ -15,13 +15,21 @@ from __future__ import absolute_import, division, print_function
from cryptography import utils
from cryptography.exceptions import (
- AlreadyFinalized, NotYetFinalized, AlreadyUpdated,
+ AlreadyFinalized, AlreadyUpdated, NotYetFinalized, UnsupportedAlgorithm,
+ _Reasons
)
+from cryptography.hazmat.backends.interfaces import CipherBackend
from cryptography.hazmat.primitives import interfaces
class Cipher(object):
def __init__(self, algorithm, mode, backend):
+ if not isinstance(backend, CipherBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement CipherBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
if not isinstance(algorithm, interfaces.CipherAlgorithm):
raise TypeError("Expected interface of interfaces.CipherAlgorithm")
diff --git a/cryptography/hazmat/primitives/constant_time.py b/cryptography/hazmat/primitives/constant_time.py
index e88a0d95..e0e9aa37 100644
--- a/cryptography/hazmat/primitives/constant_time.py
+++ b/cryptography/hazmat/primitives/constant_time.py
@@ -13,18 +13,20 @@
from __future__ import absolute_import, division, print_function
+import sys
+
import cffi
import six
+from cryptography.hazmat.bindings.utils import _create_modulename
-_ffi = cffi.FFI()
-_ffi.cdef("""
+TYPES = """
uint8_t Cryptography_constant_time_bytes_eq(uint8_t *, size_t, uint8_t *,
size_t);
-""")
-_lib = _ffi.verify(
- """
+"""
+
+FUNCTIONS = """
uint8_t Cryptography_constant_time_bytes_eq(uint8_t *a, size_t len_a,
uint8_t *b, size_t len_b) {
size_t i = 0;
@@ -43,7 +45,13 @@ uint8_t Cryptography_constant_time_bytes_eq(uint8_t *a, size_t len_a,
/* Now check the low bit to see if it's set */
return (mismatch & 1) == 0;
}
-""",
+"""
+
+_ffi = cffi.FFI()
+_ffi.cdef(TYPES)
+_lib = _ffi.verify(
+ source=FUNCTIONS,
+ modulename=_create_modulename([TYPES], FUNCTIONS, sys.version),
ext_package="cryptography",
)
diff --git a/cryptography/hazmat/primitives/hashes.py b/cryptography/hazmat/primitives/hashes.py
index bee188b3..35b677b0 100644
--- a/cryptography/hazmat/primitives/hashes.py
+++ b/cryptography/hazmat/primitives/hashes.py
@@ -16,13 +16,22 @@ from __future__ import absolute_import, division, print_function
import six
from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized
+from cryptography.exceptions import (
+ AlreadyFinalized, UnsupportedAlgorithm, _Reasons
+)
+from cryptography.hazmat.backends.interfaces import HashBackend
from cryptography.hazmat.primitives import interfaces
@utils.register_interface(interfaces.HashContext)
class Hash(object):
def __init__(self, algorithm, backend, ctx=None):
+ if not isinstance(backend, HashBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement HashBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
if not isinstance(algorithm, interfaces.HashAlgorithm):
raise TypeError("Expected instance of interfaces.HashAlgorithm.")
self.algorithm = algorithm
diff --git a/cryptography/hazmat/primitives/hmac.py b/cryptography/hazmat/primitives/hmac.py
index 76d658aa..afbb2f75 100644
--- a/cryptography/hazmat/primitives/hmac.py
+++ b/cryptography/hazmat/primitives/hmac.py
@@ -16,13 +16,22 @@ from __future__ import absolute_import, division, print_function
import six
from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, InvalidSignature
+from cryptography.exceptions import (
+ AlreadyFinalized, InvalidSignature, UnsupportedAlgorithm, _Reasons
+)
+from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, interfaces
@utils.register_interface(interfaces.HashContext)
class HMAC(object):
def __init__(self, key, algorithm, backend, ctx=None):
+ if not isinstance(backend, HMACBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement HMACBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
if not isinstance(algorithm, interfaces.HashAlgorithm):
raise TypeError("Expected instance of interfaces.HashAlgorithm.")
self.algorithm = algorithm
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index 11696160..eab48b4d 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -287,6 +287,104 @@ class RSAPublicKey(six.with_metaclass(abc.ABCMeta)):
"""
+class DSAParameters(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def modulus(self):
+ """
+ The prime modulus that's used in generating the DSA keypair and used
+ in the DSA signing and verification processes.
+ """
+
+ @abc.abstractproperty
+ def subgroup_order(self):
+ """
+ The subgroup order that's used in generating the DSA keypair
+ by the generator and used in the DSA signing and verification
+ processes.
+ """
+
+ @abc.abstractproperty
+ def generator(self):
+ """
+ The generator that is used in generating the DSA keypair and used
+ in the DSA signing and verification processes.
+ """
+
+ @abc.abstractproperty
+ def p(self):
+ """
+ The prime modulus that's used in generating the DSA keypair and used
+ in the DSA signing and verification processes. Alias for modulus.
+ """
+
+ @abc.abstractproperty
+ def q(self):
+ """
+ The subgroup order that's used in generating the DSA keypair
+ by the generator and used in the DSA signing and verification
+ processes. Alias for subgroup_order.
+ """
+
+ @abc.abstractproperty
+ def g(self):
+ """
+ The generator that is used in generating the DSA keypair and used
+ in the DSA signing and verification processes. Alias for generator.
+ """
+
+
+class DSAPrivateKey(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def key_size(self):
+ """
+ The bit length of the prime modulus.
+ """
+
+ @abc.abstractmethod
+ def public_key(self):
+ """
+ The DSAPublicKey associated with this private key.
+ """
+
+ @abc.abstractproperty
+ def x(self):
+ """
+ The private key "x" in the DSA structure.
+ """
+
+ @abc.abstractproperty
+ def y(self):
+ """
+ The public key.
+ """
+
+ @abc.abstractmethod
+ def parameters(self):
+ """
+ The DSAParameters object associated with this private key.
+ """
+
+
+class DSAPublicKey(six.with_metaclass(abc.ABCMeta)):
+ @abc.abstractproperty
+ def key_size(self):
+ """
+ The bit length of the prime modulus.
+ """
+
+ @abc.abstractproperty
+ def y(self):
+ """
+ The public key.
+ """
+
+ @abc.abstractmethod
+ def parameters(self):
+ """
+ The DSAParameters object associated with this public key.
+ """
+
+
class AsymmetricSignatureContext(six.with_metaclass(abc.ABCMeta)):
@abc.abstractmethod
def update(self, data):
diff --git a/cryptography/hazmat/primitives/kdf/__init__.py b/cryptography/hazmat/primitives/kdf/__init__.py
index e69de29b..2f420574 100644
--- a/cryptography/hazmat/primitives/kdf/__init__.py
+++ b/cryptography/hazmat/primitives/kdf/__init__.py
@@ -0,0 +1,14 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/primitives/kdf/hkdf.py b/cryptography/hazmat/primitives/kdf/hkdf.py
index af15b64d..03500aaa 100644
--- a/cryptography/hazmat/primitives/kdf/hkdf.py
+++ b/cryptography/hazmat/primitives/kdf/hkdf.py
@@ -11,16 +11,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
import six
from cryptography import utils
-from cryptography.exceptions import AlreadyFinalized, InvalidKey
+from cryptography.exceptions import (
+ AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
+)
+from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, hmac, interfaces
@utils.register_interface(interfaces.KeyDerivationFunction)
class HKDF(object):
def __init__(self, algorithm, length, salt, info, backend):
+ if not isinstance(backend, HMACBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement HMACBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
self._algorithm = algorithm
max_length = 255 * (algorithm.digest_size // 8)
diff --git a/cryptography/hazmat/primitives/kdf/pbkdf2.py b/cryptography/hazmat/primitives/kdf/pbkdf2.py
index 71b88211..bec35bb2 100644
--- a/cryptography/hazmat/primitives/kdf/pbkdf2.py
+++ b/cryptography/hazmat/primitives/kdf/pbkdf2.py
@@ -17,18 +17,26 @@ import six
from cryptography import utils
from cryptography.exceptions import (
- InvalidKey, UnsupportedAlgorithm, AlreadyFinalized
+ AlreadyFinalized, InvalidKey, UnsupportedAlgorithm, _Reasons
)
+from cryptography.hazmat.backends.interfaces import PBKDF2HMACBackend
from cryptography.hazmat.primitives import constant_time, interfaces
@utils.register_interface(interfaces.KeyDerivationFunction)
class PBKDF2HMAC(object):
def __init__(self, algorithm, length, salt, iterations, backend):
+ if not isinstance(backend, PBKDF2HMACBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement PBKDF2HMACBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
if not backend.pbkdf2_hmac_supported(algorithm):
raise UnsupportedAlgorithm(
"{0} is not supported for PBKDF2 by this backend".format(
- algorithm.name)
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
)
self._used = False
self._algorithm = algorithm
diff --git a/cryptography/hazmat/primitives/padding.py b/cryptography/hazmat/primitives/padding.py
index 1717262c..d78c6a5b 100644
--- a/cryptography/hazmat/primitives/padding.py
+++ b/cryptography/hazmat/primitives/padding.py
@@ -11,20 +11,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from __future__ import absolute_import, division, print_function
+
+import sys
+
import cffi
import six
from cryptography import utils
+from cryptography.hazmat.bindings.utils import _create_modulename
from cryptography.hazmat.primitives import interfaces
-_ffi = cffi.FFI()
-_ffi.cdef("""
+TYPES = """
uint8_t Cryptography_check_pkcs7_padding(const uint8_t *, uint8_t);
-""")
-_lib = _ffi.verify(
- """
+"""
+
+FUNCTIONS = """
/* Returns the value of the input with the most-significant-bit copied to all
of the bits. */
static uint8_t Cryptography_DUPLICATE_MSB_TO_ALL(uint8_t a) {
@@ -60,7 +64,13 @@ uint8_t Cryptography_check_pkcs7_padding(const uint8_t *data,
/* Now check the low bit to see if it's set */
return (mismatch & 1) == 0;
}
-""",
+"""
+
+_ffi = cffi.FFI()
+_ffi.cdef(TYPES)
+_lib = _ffi.verify(
+ source=FUNCTIONS,
+ modulename=_create_modulename([TYPES], FUNCTIONS, sys.version),
ext_package="cryptography",
)
diff --git a/cryptography/hazmat/primitives/twofactor/__init__.py b/cryptography/hazmat/primitives/twofactor/__init__.py
index e69de29b..2f420574 100644
--- a/cryptography/hazmat/primitives/twofactor/__init__.py
+++ b/cryptography/hazmat/primitives/twofactor/__init__.py
@@ -0,0 +1,14 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
diff --git a/cryptography/hazmat/primitives/twofactor/hotp.py b/cryptography/hazmat/primitives/twofactor/hotp.py
index 24f5f465..41c467c8 100644
--- a/cryptography/hazmat/primitives/twofactor/hotp.py
+++ b/cryptography/hazmat/primitives/twofactor/hotp.py
@@ -17,22 +17,33 @@ import struct
import six
-from cryptography.exceptions import InvalidToken, UnsupportedAlgorithm
+from cryptography.exceptions import (
+ InvalidToken, UnsupportedAlgorithm, _Reasons
+)
+from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time, hmac
from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512
class HOTP(object):
def __init__(self, key, length, algorithm, backend):
+ if not isinstance(backend, HMACBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement HMACBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
if len(key) < 16:
raise ValueError("Key length has to be at least 128 bits.")
+ if not isinstance(length, six.integer_types):
+ raise TypeError("Length parameter must be an integer type")
+
if length < 6 or length > 8:
raise ValueError("Length of HOTP has to be between 6 to 8.")
if not isinstance(algorithm, (SHA1, SHA256, SHA512)):
- raise UnsupportedAlgorithm(
- "Algorithm must be SHA1, SHA256 or SHA512")
+ raise TypeError("Algorithm must be SHA1, SHA256 or SHA512")
self._key = key
self._length = length
diff --git a/cryptography/hazmat/primitives/twofactor/totp.py b/cryptography/hazmat/primitives/twofactor/totp.py
index 0630de69..e55ba00d 100644
--- a/cryptography/hazmat/primitives/twofactor/totp.py
+++ b/cryptography/hazmat/primitives/twofactor/totp.py
@@ -13,13 +13,22 @@
from __future__ import absolute_import, division, print_function
-from cryptography.exceptions import InvalidToken
+from cryptography.exceptions import (
+ InvalidToken, UnsupportedAlgorithm, _Reasons
+)
+from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import constant_time
from cryptography.hazmat.primitives.twofactor.hotp import HOTP
class TOTP(object):
def __init__(self, key, length, algorithm, time_step, backend):
+ if not isinstance(backend, HMACBackend):
+ raise UnsupportedAlgorithm(
+ "Backend object does not implement HMACBackend",
+ _Reasons.BACKEND_MISSING_INTERFACE
+ )
+
self._time_step = time_step
self._hotp = HOTP(key, length, algorithm, backend)