Exemple #1
0
    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
Exemple #2
0
 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)
Exemple #3
0
 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)
Exemple #4
0
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
Exemple #5
0
 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)
Exemple #8
0
 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)
Exemple #9
0
    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)
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
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)
Exemple #13
0
    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)
Exemple #14
0
    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)
Exemple #16
0
    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)
Exemple #18
0
    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)
Exemple #20
0
    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)
Exemple #21
0
 def _bcrypt_kdf(*args, **kwargs):
     raise UnsupportedAlgorithm("Need bcrypt module")
Exemple #22
0
 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.")
Exemple #23
0
    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
Exemple #24
0
    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)
Exemple #25
0
 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)
Exemple #26
0
    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
Exemple #27
0
 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)
Exemple #29
0
    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)
Exemple #30
0
 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)