# This file is dual licensed under the terms of the Apache License, Version # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. from __future__ import absolute_import, division, print_function from cryptography import utils from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends.interfaces import ( CMACBackend, CipherBackend, DERSerializationBackend, DSABackend, EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, PEMSerializationBackend, RSABackend, X509Backend ) @utils.register_interface(CMACBackend) @utils.register_interface(CipherBackend) @utils.register_interface(DERSerializationBackend) @utils.register_interface(HashBackend) @utils.register_interface(HMACBackend) @utils.register_interface(PBKDF2HMACBackend) @utils.register_interface(RSABackend) @utils.register_interface(DSABackend) @utils.register_interface(EllipticCurveBackend) @utils.register_interface(PEMSerializationBackend) @utils.register_interface(X509Backend) 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 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 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 elliptic_curve_exchange_algorithm_supported(self, algorithm, curve): return any( b.elliptic_curve_exchange_algorithm_supported(algorithm, curve) for b in self._filtered_backends(EllipticCurveBackend) ) 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_der_private_key(self, data, password): for b in self._filtered_backends(DERSerializationBackend): return b.load_der_private_key(data, password) raise UnsupportedAlgorithm( "This backend does not support this key serialization.", _Reasons.UNSUPPORTED_SERIALIZATION ) def load_der_public_key(self, data): for b in self._filtered_backends(DERSerializationBackend): return b.load_der_public_key(data) raise UnsupportedAlgorithm( "This backend does not support this key serialization.", _Reasons.UNSUPPORTED_SERIALIZATION ) def load_pem_x509_certificate(self, data): for b in self._filtered_backends(X509Backend): return b.load_pem_x509_certificate(data) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def load_der_x509_certificate(self, data): for b in self._filtered_backends(X509Backend): return b.load_der_x509_certificate(data) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def load_pem_x509_crl(self, data): for b in self._filtered_backends(X509Backend): return b.load_pem_x509_crl(data) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def load_der_x509_crl(self, data): for b in self._filtered_backends(X509Backend): return b.load_der_x509_crl(data) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def load_der_x509_csr(self, data): for b in self._filtered_backends(X509Backend): return b.load_der_x509_csr(data) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def load_pem_x509_csr(self, data): for b in self._filtered_backends(X509Backend): return b.load_pem_x509_csr(data) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def create_x509_csr(self, builder, private_key, algorithm): for b in self._filtered_backends(X509Backend): return b.create_x509_csr(builder, private_key, algorithm) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def create_x509_certificate(self, builder, private_key, algorithm): for b in self._filtered_backends(X509Backend): return b.create_x509_certificate(builder, private_key, algorithm) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def create_x509_crl(self, builder, private_key, algorithm): for b in self._filtered_backends(X509Backend): return b.create_x509_crl(builder, private_key, algorithm) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 ) def create_x509_revoked_certificate(self, builder): for b in self._filtered_backends(X509Backend): return b.create_x509_revoked_certificate(builder) raise UnsupportedAlgorithm( "This backend does not support X.509.", _Reasons.UNSUPPORTED_X509 )