def __init__(self, backend, cipher, mode, operation): self._backend = backend self._cipher = cipher self._mode = mode self._operation = operation self._tag = None if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): self._block_size_bytes = self._cipher.block_size // 8 else: self._block_size_bytes = 1 ctx = self._backend._lib_EVP_CIPHER_CTX_new() ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_CIPHER_CTX_free) registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: raise UnsupportedAlgorithm( "cipher {} in {} mode is not supported" "by this backend.".format(cipher.name, mode.name if mode else mode), _Reasons.UNSUPPORTED_CIPHER) evp_cipher = adapter(self._backend, cipher, mode) if evp_cipher == self._backend._ffi.NULL: msg = "".format() if mode is not None: msg += "" msg += ().format() raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER) if isintance(): iv_nonce = self._backend._ffi.from_from_buffer( mode.initialization_vector) elif isintance(mode, modes.ModeWithTweak): iv_nonce = self._backend._ffi.from_buffer(mode.tweak) elif isintance(): iv_nonce = self._backend._ffi.from_buffer(cipher.nonce) else: iv_nonce = self._backend._ffi.NULL res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, operation) self._backend.openssl_assert(res != 0) res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( ctx, len(cipher.key)) self._backend.openssl_assert(res != 0) if isintance(mode, modes.GCM): res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(iv_nonce), self._backend._ffi.NULL) self._backend.openssl_assert(res != 0) if mode.tag is not None: res = self._backend._lib.EVP_CIPHER_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(mode.tag), mode.tag) self._backend.openssl_assert(res != 0) self._tag = mode.tag elif (self._operation == self._DECRYPT and self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL): raise NotImplementedError( "delayed passing of GCM tag reqires OpenSSL >= 1.0.2" " To use this feature please update OpenSSL") res = self._backend._lib.EVP_CipherInit_ex( ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.from_buffer(cipher.key), iv_nonce, operation) self._backend.openssl_assert_assert(res != 0) self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx
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 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_ssh_private_key(data, password, backend=None): """Load private key from OpenSSH custom encoding. """ utils._check_byteslike("data", data) backend = _get_backend(backend) if password is not None: utils._check_bytes("password", password) m = _PEM_RC.search(data) if not m: raise ValueError("Not OpenSSH private key format") p1 = m.start(1) p2 = m.end(1) data = binascii.a2b_base64(memoryview(data)[p1:p2]) if not data.startswith(_SK_MAGIC): raise ValueError("Not OpenSSH private key format") data = memoryview(data)[len(_SK_MAGIC):] # parse header ciphername, data = _get_sshstr(data) kdfname, data = _get_sshstr(data) kdfoptions, data = _get_sshstr(data) nkeys, data = _get_u32(data) if nkeys != 1: raise ValueError("Only one key supported") # load public key data pubdata, data = _get_sshstr(data) pub_key_type, pubdata = _get_sshstr(pubdata) kformat = _lookup_kformat(pub_key_type) pubfields, pubdata = kformat.get_public(pubdata) _check_empty(pubdata) # load secret data edata, data = _get_sshstr(data) _check_empty(data) if (ciphername, kdfname) != (_NONE, _NONE): ciphername = ciphername.tobytes() if ciphername not in _SSH_CIPHERS: raise UnsupportedAlgorithm("Unsupported cipher: %r" % ciphername) if kdfname != _BCRYPT: raise UnsupportedAlgorithm("Unsupported KDF: %r" % kdfname) blklen = _SSH_CIPHERS[ciphername][3] _check_block_size(edata, blklen) salt, kbuf = _get_sshstr(kdfoptions) rounds, kbuf = _get_u32(kbuf) _check_empty(kbuf) ciph = _init_cipher(ciphername, password, salt.tobytes(), rounds, backend) edata = memoryview(ciph.decryptor().update(edata)) else: blklen = 8 _check_block_size(edata, blklen) ck1, edata = _get_u32(edata) ck2, edata = _get_u32(edata) if ck1 != ck2: raise ValueError("Corrupt data: broken checksum") # load per-key struct key_type, edata = _get_sshstr(edata) if key_type != pub_key_type: raise ValueError("Corrupt data: key type mismatch") private_key, edata = kformat.load_private(edata, pubfields, backend) comment, edata = _get_sshstr(edata) # yes, SSH does padding check *after* all other parsing is done. # need to follow as it writes zero-byte padding too. if edata != _PADDING[:len(edata)]: raise ValueError("Corrupt data: invalid padding") return private_key
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 create_symmetric_decryption_ctx(self, cipher, mode): if not self.cipher_supported(cipher, mode): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_CIPHER)
def derive_pbkdf2_hmac(self, algorithm, length, salt, iterations, key_material): if not self.pbkdf2_hmac_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_HASH)
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 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 __init__(self, backend, cipher, mode, operation): self._backend = backend self._cipher = cipher self._mode = mode self._operation = operation self._tag = None if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): self._block_size_bytes = self._cipher.block_size // 8 else: self._block_size_bytes = 1 ctx = self._backend._lib.EVP_CIPHER_CTX_new() ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_CIPHER_CTX_free) registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: raise UnsupportedAlgorithm( "cipher {} in {} mode is not supported " "by this api.".format(cipher.name, mode.name if mode else mode), _Reasons.UNSUPPORTED_CIPHER, ) evp_cipher = adapter(self._backend, cipher, mode) if evp_cipher == self._backend._ffi.NULL: msg = "cipher {0.name} ".format(cipher) if mode is not None: msg += "in {0.name} mode ".format(mode) msg += ("is not supported by this api (Your version of OpenSSL " "may be too old. Current version: {}.)").format( self._backend.openssl_version_text()) raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER) if isinstance(mode, modes.ModeWithInitializationVector): iv_nonce = self._backend._ffi.from_buffer( mode.initialization_vector) elif isinstance(mode, modes.ModeWithTweak): iv_nonce = self._backend._ffi.from_buffer(mode.tweak) elif isinstance(mode, modes.ModeWithNonce): iv_nonce = self._backend._ffi.from_buffer(mode.nonce) elif isinstance(cipher, modes.ModeWithNonce): iv_nonce = self._backend._ffi.from_buffer(cipher.nonce) else: iv_nonce = self._backend._ffi.NULL # begin init with cipher and operation type res = self._backend._lib.EVP_CipherInit_ex( ctx, evp_cipher, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, operation, ) self._backend.openssl_assert(res != 0) # set the key length to handle variable key ciphers res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( ctx, len(cipher.key)) self._backend.openssl_assert(res != 0) if isinstance(mode, modes.GCM): res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(iv_nonce), self._backend._ffi.NULL, ) self._backend.openssl_assert(res != 0) if mode.tag is not None: res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(mode.tag), mode.tag, ) self._backend.openssl_assert(res != 0) self._tag = mode.tag # pass key/iv res = self._backend._lib.EVP_CipherInit_ex( ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.from_buffer(cipher.key), iv_nonce, operation, ) self._backend.openssl_assert(res != 0) # We purposely disable padding here as it's handled higher up in the # API. self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx
def __init__(self, backend, cipher, mode, operation): self._backend = backend self._cipher = cipher self._mode = mode self._operation = operation self._tag = None if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): self._block_size_bytes = self._cipher.block_size // 8 else: self._block_size_bytes = 1 ctx = self._backend._lib.EVP_CIPHER_CTX_new() ctx = self._backend._ffi.gc( ctx, self._backend._lib.EVP_CIPHER_CTX_free ) registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: raise UnsupportedAlgorithm( "cipher {} in {} mode is not supported " "by this backend.".format( cipher.name, mode.name if mode else mode ), _Reasons.UNSUPPORTED_CIPHER, ) evp_cipher = adapter(self._backend, cipher, mode) if evp_cipher == self._backend._ffi.NULL: msg = "cipher {0.name} ".format(cipher) if mode is not None: msg += "in {0.name} mode ".format(mode) msg += ( "is not supported by this backend (Your version of OpenSSL " "may be too old. Current version: {}.)" ).format(self._backend.openssl_version_text()) raise UnsupportedAlgorithm(msg, _Reasons.UNSUPPORTED_CIPHER) if isinstance(mode, modes.ModeWithInitializationVector): iv_nonce = self._backend._ffi.from_buffer( mode.initialization_vector ) elif isinstance(mode, modes.ModeWithTweak): iv_nonce = self._backend._ffi.from_buffer(mode.tweak) elif isinstance(mode, modes.ModeWithNonce): iv_nonce = self._backend._ffi.from_buffer(mode.nonce) elif isinstance(cipher, modes.ModeWithNonce): iv_nonce = self._backend._ffi.from_buffer(cipher.nonce) else: iv_nonce = self._backend._ffi.NULL # begin init with cipher and operation type res = self._backend._lib.EVP_CipherInit_ex( ctx, evp_cipher, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, operation, ) self._backend.openssl_assert(res != 0) # set the key length to handle variable key ciphers res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( ctx, len(cipher.key) ) self._backend.openssl_assert(res != 0) if isinstance(mode, modes.GCM): res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(iv_nonce), self._backend._ffi.NULL, ) self._backend.openssl_assert(res != 0) if mode.tag is not None: res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(mode.tag), mode.tag, ) self._backend.openssl_assert(res != 0) self._tag = mode.tag # pass key/iv res = self._backend._lib.EVP_CipherInit_ex( ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.from_buffer(cipher.key), iv_nonce, operation, ) # Check for XTS mode duplicate keys error errors = self._backend._consume_errors() lib = self._backend._lib if res == 0 and ( ( lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER and errors[0]._lib_reason_match( lib.ERR_LIB_EVP, lib.EVP_R_XTS_DUPLICATED_KEYS ) ) or ( lib.Cryptography_HAS_PROVIDERS and errors[0]._lib_reason_match( lib.ERR_LIB_PROV, lib.PROV_R_XTS_DUPLICATED_KEYS ) ) ): raise ValueError("In XTS mode duplicated keys are not allowed") self._backend.openssl_assert(res != 0, errors=errors) # We purposely disable padding here as it's handled higher up in the # API. self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx
def _check_signature_algorithm(signature_algorithm): if not isinstance(signature_algorithm, ec.ECDSA): raise UnsupportedAlgorithm( "Unsupported elliptic curve signature algorithm.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
def test_revoke_resiliency(self): # Server return an invalid HTTP response with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, http_status_code=400): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # OCSP response in invalid with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.UNAUTHORIZED): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # OCSP response is valid, but certificate status is unknown with _ocsp_mock(ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # The OCSP response says that the certificate is revoked, but certificate # does not contain the OCSP extension. with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): with mock.patch( 'cryptography.x509.Extensions.get_extension_for_class', side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # OCSP response uses an unsupported signature. with _ocsp_mock( ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=UnsupportedAlgorithm('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # OSCP signature response is invalid. with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=InvalidSignature('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # Assertion error on OCSP response validity with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL, check_signature_side_effect=AssertionError('foo')): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # No responder cert in OCSP response with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks: mocks['mock_response'].return_value.certificates = [] revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) # Responder cert is not signed by certificate issuer with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks: cert = mocks['mock_response'].return_value.certificates[0] mocks['mock_response'].return_value.certificates[0] = mock.Mock( issuer='fake', subject=cert.subject) revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked) with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL): # This mock is necessary to avoid the first call contained in _determine_ocsp_server # of the method cryptography.x509.Extensions.get_extension_for_class. with mock.patch( 'certbot.ocsp._determine_ocsp_server') as mock_server: mock_server.return_value = ('https://example.com', 'example.com') with mock.patch( 'cryptography.x509.Extensions.get_extension_for_class', side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_obj) self.assertFalse(revoked)
def __init__( self, algorithm, mode, length, rlen, llen, location, label, context, fixed, backend=None, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not isinstance(algorithm, hashes.HashAlgorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported hash algorithm.", _Reasons.UNSUPPORTED_HASH, ) if not backend.hmac_supported(algorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported hmac algorithm.", _Reasons.UNSUPPORTED_HASH, ) if not isinstance(mode, Mode): raise TypeError("mode must be of type Mode") if not isinstance(location, CounterLocation): raise TypeError("location must be of type CounterLocation") if (label or context) and fixed: raise ValueError("When supplying fixed data, " "label and context are ignored.") if rlen is None or not self._valid_byte_length(rlen): raise ValueError("rlen must be between 1 and 4") if llen is None and fixed is None: raise ValueError("Please specify an llen") if llen is not None and not isinstance(llen, int): raise TypeError("llen must be an integer") if label is None: label = b"" if context is None: context = b"" utils._check_bytes("label", label) utils._check_bytes("context", context) self._algorithm = algorithm self._mode = mode self._length = length self._rlen = rlen self._llen = llen self._location = location self._label = label self._context = context self._backend = backend self._used = False self._fixed_data = fixed
def generate_elliptic_curve_private_key(self, curve): if not self.elliptic_curve_supported(curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE)
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 load_elliptic_curve_public_numbers(self, numbers): if not self.elliptic_curve_supported(numbers.curve): raise UnsupportedAlgorithm(_Reasons.UNSUPPORTED_ELLIPTIC_CURVE)
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)
def create_hmac_ctx(self, key, algorithm): if not self.hmac_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_HASH)
def x509_name_bytes(self, name): for b in self._filtered_backends(X509Backend): return b.x509_name_bytes(name) raise UnsupportedAlgorithm("This backend does not support X.509.", _Reasons.UNSUPPORTED_X509)
def _bcrypt_kdf(*args, **kwargs): raise UnsupportedAlgorithm("Need bcrypt module")
def derive_scrypt(self, key_material, salt, length, n, r, p): for b in self._filtered_backends(ScryptBackend): return b.derive_scrypt(key_material, salt, length, n, r, p) raise UnsupportedAlgorithm("This backend does not support scrypt.")
def __init__(self, backend, cipher, mode, operation): self._backend = backend self._cipher = cipher self._mode = mode self._operation = operation self._tag = None if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): self._block_size = self._cipher.block_size else: self._block_size = 1 ctx = self._backend._lib.EVP_CIPHER_CTX_new() ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_CIPHER_CTX_free) registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: 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) evp_cipher = adapter(self._backend, cipher, mode) if evp_cipher == self._backend._ffi.NULL: 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) if isinstance(mode, modes.ModeWithInitializationVector): iv_nonce = mode.initialization_vector elif isinstance(mode, modes.ModeWithNonce): iv_nonce = mode.nonce else: iv_nonce = self._backend._ffi.NULL # begin init with cipher and operation type res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, operation) self._backend.openssl_assert(res != 0) # set the key length to handle variable key ciphers res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( ctx, len(cipher.key)) self._backend.openssl_assert(res != 0) if isinstance(mode, modes.GCM): res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_GCM_SET_IVLEN, len(iv_nonce), self._backend._ffi.NULL) self._backend.openssl_assert(res != 0) if operation == self._DECRYPT: res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_GCM_SET_TAG, len(mode.tag), mode.tag) self._backend.openssl_assert(res != 0) # pass key/iv res = self._backend._lib.EVP_CipherInit_ex(ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, cipher.key, iv_nonce, operation) self._backend.openssl_assert(res != 0) # We purposely disable padding here as it's handled higher up in the # API. self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx
def test_revoke_resiliency(self, mock_ocsp_response, mock_post, mock_check): # Server return an invalid HTTP response mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) mock_post.return_value = mock.Mock(status_code=400) revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked) # OCSP response in invalid mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.UNAUTHORIZED) mock_post.return_value = mock.Mock(status_code=200) revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked) # OCSP response is valid, but certificate status is unknown mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) mock_post.return_value = mock.Mock(status_code=200) revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked) # The OCSP response says that the certificate is revoked, but certificate # does not contain the OCSP extension. mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.UNKNOWN, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) mock_post.return_value = mock.Mock(status_code=200) with mock.patch('cryptography.x509.Extensions.get_extension_for_class', side_effect=x509.ExtensionNotFound( 'Not found', x509.AuthorityInformationAccessOID.OCSP)): revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked) # Valid response, OCSP extension is present, # but OCSP response uses an unsupported signature. mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) mock_post.return_value = mock.Mock(status_code=200) mock_check.side_effect = UnsupportedAlgorithm('foo') revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked) # And now, the signature itself is invalid. mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) mock_post.return_value = mock.Mock(status_code=200) mock_check.side_effect = InvalidSignature('foo') revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked) # Finally, assertion error on OCSP response validity mock_ocsp_response.return_value = _construct_mock_ocsp_response( ocsp_lib.OCSPCertStatus.REVOKED, ocsp_lib.OCSPResponseStatus.SUCCESSFUL) mock_post.return_value = mock.Mock(status_code=200) mock_check.side_effect = AssertionError('foo') revoked = self.checker.ocsp_revoked(self.cert_path, self.chain_path) self.assertFalse(revoked)
def create_dsa_signature_ctx(self, private_key, algorithm): for b in self._filtered_backends(DSABackend): return b.create_dsa_signature_ctx(private_key, algorithm) raise UnsupportedAlgorithm("DSA is not supported by the backend", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
def __init__(self, backend, cipher, mode, operation): self._backend = backend self._cipher = cipher self._mode = mode self._operation = operation self._tag = None if isinstance(self._cipher, ciphers.BlockCipherAlgorithm): self._block_size_bytes = self._cipher.block_size // 8 else: self._block_size_bytes = 1 ctx = self._backend._lib.EVP_CIPHER_CTX_new() ctx = self._backend._ffi.gc(ctx, self._backend._lib.EVP_CIPHER_CTX_free) registry = self._backend._cipher_registry try: adapter = registry[type(cipher), type(mode)] except KeyError: 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) evp_cipher = adapter(self._backend, cipher, mode) if evp_cipher == self._backend._ffi.NULL: 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) if isinstance(mode, modes.ModeWithInitializationVector): iv_nonce = mode.initialization_vector elif isinstance(mode, modes.ModeWithTweak): iv_nonce = mode.tweak elif isinstance(mode, modes.ModeWithNonce): iv_nonce = mode.nonce elif isinstance(cipher, modes.ModeWithNonce): iv_nonce = cipher.nonce else: iv_nonce = self._backend._ffi.NULL # begin init with cipher and operation type res = self._backend._lib.EVP_CipherInit_ex(ctx, evp_cipher, self._backend._ffi.NULL, self._backend._ffi.NULL, self._backend._ffi.NULL, operation) self._backend.openssl_assert(res != 0) # set the key length to handle variable key ciphers res = self._backend._lib.EVP_CIPHER_CTX_set_key_length( ctx, len(cipher.key)) self._backend.openssl_assert(res != 0) if isinstance(mode, modes.GCM): res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_IVLEN, len(iv_nonce), self._backend._ffi.NULL) self._backend.openssl_assert(res != 0) if mode.tag is not None: res = self._backend._lib.EVP_CIPHER_CTX_ctrl( ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG, len(mode.tag), mode.tag) self._backend.openssl_assert(res != 0) self._tag = mode.tag elif (self._operation == self._DECRYPT and self._backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and not self._backend._lib.CRYPTOGRAPHY_IS_LIBRESSL): raise NotImplementedError( "delayed passing of GCM tag requires OpenSSL >= 1.0.2." " To use this feature please update OpenSSL") # pass key/iv res = self._backend._lib.EVP_CipherInit_ex(ctx, self._backend._ffi.NULL, self._backend._ffi.NULL, cipher.key, iv_nonce, operation) self._backend.openssl_assert(res != 0) # We purposely disable padding here as it's handled higher up in the # API. self._backend._lib.EVP_CIPHER_CTX_set_padding(ctx, 0) self._ctx = ctx
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 create_cmac_ctx(self, algorithm): if not self.cmac_algorithm_supported(algorithm): raise UnsupportedAlgorithm("", _Reasons.UNSUPPORTED_CIPHER)
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 create_dsa_verification_ctx(self, public_key, signature, algorithm): for b in self._filtered_backends(DSABackend): return b.create_dsa_verification_ctx(public_key, signature, algorithm) raise UnsupportedAlgorithm("DSA is not supported by the backend.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)