aboutsummaryrefslogtreecommitdiffstats
path: root/src/cryptography/hazmat/backends/multibackend.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptography/hazmat/backends/multibackend.py')
-rw-r--r--src/cryptography/hazmat/backends/multibackend.py358
1 files changed, 358 insertions, 0 deletions
diff --git a/src/cryptography/hazmat/backends/multibackend.py b/src/cryptography/hazmat/backends/multibackend.py
new file mode 100644
index 00000000..c62b790c
--- /dev/null
+++ b/src/cryptography/hazmat/backends/multibackend.py
@@ -0,0 +1,358 @@
+# 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 warnings
+
+from cryptography import utils
+from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
+from cryptography.hazmat.backends.interfaces import (
+ CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend,
+ HashBackend, PBKDF2HMACBackend, PEMSerializationBackend,
+ PKCS8SerializationBackend, RSABackend,
+ TraditionalOpenSSLSerializationBackend
+)
+
+
+@utils.register_interface(CMACBackend)
+@utils.register_interface(CipherBackend)
+@utils.register_interface(HashBackend)
+@utils.register_interface(HMACBackend)
+@utils.register_interface(PBKDF2HMACBackend)
+@utils.register_interface(PKCS8SerializationBackend)
+@utils.register_interface(RSABackend)
+@utils.register_interface(TraditionalOpenSSLSerializationBackend)
+@utils.register_interface(DSABackend)
+@utils.register_interface(EllipticCurveBackend)
+@utils.register_interface(PEMSerializationBackend)
+class MultiBackend(object):
+ name = "multibackend"
+
+ def __init__(self, backends):
+ self._backends = backends
+
+ def _filtered_backends(self, interface):
+ for b in self._backends:
+ if isinstance(b, interface):
+ yield b
+
+ def cipher_supported(self, cipher, mode):
+ return any(
+ b.cipher_supported(cipher, mode)
+ for b in self._filtered_backends(CipherBackend)
+ )
+
+ def create_symmetric_encryption_ctx(self, cipher, mode):
+ for b in self._filtered_backends(CipherBackend):
+ try:
+ return b.create_symmetric_encryption_ctx(cipher, mode)
+ except UnsupportedAlgorithm:
+ pass
+ raise UnsupportedAlgorithm(
+ "cipher {0} in {1} mode is not supported by this backend.".format(
+ cipher.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
+ )
+
+ def create_symmetric_decryption_ctx(self, cipher, mode):
+ for b in self._filtered_backends(CipherBackend):
+ try:
+ return b.create_symmetric_decryption_ctx(cipher, mode)
+ except UnsupportedAlgorithm:
+ pass
+ raise UnsupportedAlgorithm(
+ "cipher {0} in {1} mode is not supported by this backend.".format(
+ cipher.name, mode.name if mode else mode),
+ _Reasons.UNSUPPORTED_CIPHER
+ )
+
+ def hash_supported(self, algorithm):
+ return any(
+ b.hash_supported(algorithm)
+ for b in self._filtered_backends(HashBackend)
+ )
+
+ def create_hash_ctx(self, algorithm):
+ for b in self._filtered_backends(HashBackend):
+ try:
+ return b.create_hash_ctx(algorithm)
+ except UnsupportedAlgorithm:
+ pass
+ raise UnsupportedAlgorithm(
+ "{0} is not a supported hash on this backend.".format(
+ algorithm.name),
+ _Reasons.UNSUPPORTED_HASH
+ )
+
+ def hmac_supported(self, algorithm):
+ return any(
+ b.hmac_supported(algorithm)
+ for b in self._filtered_backends(HMACBackend)
+ )
+
+ def create_hmac_ctx(self, key, algorithm):
+ for b in self._filtered_backends(HMACBackend):
+ try:
+ return b.create_hmac_ctx(key, algorithm)
+ except UnsupportedAlgorithm:
+ pass
+ 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(
+ b.pbkdf2_hmac_supported(algorithm)
+ for b in self._filtered_backends(PBKDF2HMACBackend)
+ )
+
+ def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations,
+ key_material):
+ for b in self._filtered_backends(PBKDF2HMACBackend):
+ try:
+ return b.derive_pbkdf2_hmac(
+ algorithm, length, salt, iterations, key_material
+ )
+ except UnsupportedAlgorithm:
+ pass
+ 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("RSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def generate_rsa_parameters_supported(self, public_exponent, key_size):
+ for b in self._filtered_backends(RSABackend):
+ return b.generate_rsa_parameters_supported(
+ public_exponent, key_size
+ )
+ raise UnsupportedAlgorithm("RSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def rsa_padding_supported(self, padding):
+ for b in self._filtered_backends(RSABackend):
+ return b.rsa_padding_supported(padding)
+ raise UnsupportedAlgorithm("RSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def load_rsa_private_numbers(self, numbers):
+ for b in self._filtered_backends(RSABackend):
+ return b.load_rsa_private_numbers(numbers)
+
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def load_rsa_public_numbers(self, numbers):
+ for b in self._filtered_backends(RSABackend):
+ return b.load_rsa_public_numbers(numbers)
+
+ raise UnsupportedAlgorithm("RSA is not supported by the backend",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def generate_dsa_parameters(self, key_size):
+ for b in self._filtered_backends(DSABackend):
+ return b.generate_dsa_parameters(key_size)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def generate_dsa_private_key(self, parameters):
+ for b in self._filtered_backends(DSABackend):
+ return b.generate_dsa_private_key(parameters)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def generate_dsa_private_key_and_parameters(self, key_size):
+ for b in self._filtered_backends(DSABackend):
+ return b.generate_dsa_private_key_and_parameters(key_size)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def dsa_hash_supported(self, algorithm):
+ for b in self._filtered_backends(DSABackend):
+ return b.dsa_hash_supported(algorithm)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def dsa_parameters_supported(self, p, q, g):
+ for b in self._filtered_backends(DSABackend):
+ return b.dsa_parameters_supported(p, q, g)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def load_dsa_public_numbers(self, numbers):
+ for b in self._filtered_backends(DSABackend):
+ return b.load_dsa_public_numbers(numbers)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def load_dsa_private_numbers(self, numbers):
+ for b in self._filtered_backends(DSABackend):
+ return b.load_dsa_private_numbers(numbers)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def load_dsa_parameter_numbers(self, numbers):
+ for b in self._filtered_backends(DSABackend):
+ return b.load_dsa_parameter_numbers(numbers)
+ raise UnsupportedAlgorithm("DSA is not supported by the backend.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
+
+ def cmac_algorithm_supported(self, algorithm):
+ return any(
+ b.cmac_algorithm_supported(algorithm)
+ for b in self._filtered_backends(CMACBackend)
+ )
+
+ def create_cmac_ctx(self, algorithm):
+ for b in self._filtered_backends(CMACBackend):
+ try:
+ return b.create_cmac_ctx(algorithm)
+ except UnsupportedAlgorithm:
+ pass
+ raise UnsupportedAlgorithm("This backend does not support CMAC.",
+ _Reasons.UNSUPPORTED_CIPHER)
+
+ def elliptic_curve_supported(self, curve):
+ return any(
+ b.elliptic_curve_supported(curve)
+ for b in self._filtered_backends(EllipticCurveBackend)
+ )
+
+ def elliptic_curve_signature_algorithm_supported(
+ self, signature_algorithm, curve
+ ):
+ return any(
+ b.elliptic_curve_signature_algorithm_supported(
+ signature_algorithm, curve
+ )
+ for b in self._filtered_backends(EllipticCurveBackend)
+ )
+
+ def generate_elliptic_curve_private_key(self, curve):
+ for b in self._filtered_backends(EllipticCurveBackend):
+ try:
+ return b.generate_elliptic_curve_private_key(curve)
+ except UnsupportedAlgorithm:
+ continue
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this elliptic curve.",
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ )
+
+ def elliptic_curve_private_key_from_numbers(self, numbers):
+ warnings.warn(
+ "elliptic_curve_private_key_from_numbers is deprecated and will "
+ "be removed in a future version.",
+ utils.DeprecatedIn06,
+ stacklevel=2
+ )
+ for b in self._filtered_backends(EllipticCurveBackend):
+ try:
+ return b.elliptic_curve_private_key_from_numbers(numbers)
+ except UnsupportedAlgorithm:
+ continue
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this elliptic curve.",
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ )
+
+ def load_elliptic_curve_private_numbers(self, numbers):
+ for b in self._filtered_backends(EllipticCurveBackend):
+ try:
+ return b.load_elliptic_curve_private_numbers(numbers)
+ except UnsupportedAlgorithm:
+ continue
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this elliptic curve.",
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ )
+
+ def elliptic_curve_public_key_from_numbers(self, numbers):
+ warnings.warn(
+ "elliptic_curve_public_key_from_numbers is deprecated and will "
+ "be removed in a future version.",
+ utils.DeprecatedIn06,
+ stacklevel=2
+ )
+ for b in self._filtered_backends(EllipticCurveBackend):
+ try:
+ return b.elliptic_curve_public_key_from_numbers(numbers)
+ except UnsupportedAlgorithm:
+ continue
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this elliptic curve.",
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ )
+
+ def load_elliptic_curve_public_numbers(self, numbers):
+ for b in self._filtered_backends(EllipticCurveBackend):
+ try:
+ return b.load_elliptic_curve_public_numbers(numbers)
+ except UnsupportedAlgorithm:
+ continue
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this elliptic curve.",
+ _Reasons.UNSUPPORTED_ELLIPTIC_CURVE
+ )
+
+ def load_pem_private_key(self, data, password):
+ for b in self._filtered_backends(PEMSerializationBackend):
+ return b.load_pem_private_key(data, password)
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this key serialization.",
+ _Reasons.UNSUPPORTED_SERIALIZATION
+ )
+
+ def load_pem_public_key(self, data):
+ for b in self._filtered_backends(PEMSerializationBackend):
+ return b.load_pem_public_key(data)
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this key serialization.",
+ _Reasons.UNSUPPORTED_SERIALIZATION
+ )
+
+ def load_pkcs8_pem_private_key(self, data, password):
+ for b in self._filtered_backends(PKCS8SerializationBackend):
+ return b.load_pkcs8_pem_private_key(data, password)
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this key serialization.",
+ _Reasons.UNSUPPORTED_SERIALIZATION
+ )
+
+ def load_traditional_openssl_pem_private_key(self, data, password):
+ for b in self._filtered_backends(
+ TraditionalOpenSSLSerializationBackend
+ ):
+ return b.load_traditional_openssl_pem_private_key(data, password)
+
+ raise UnsupportedAlgorithm(
+ "This backend does not support this key serialization.",
+ _Reasons.UNSUPPORTED_SERIALIZATION
+ )