    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE RecordWildCards #-}

    module Network.TLS.Handshake.Server.ClientHello12 (
        processClientHello12,
    ) where

    import Network.TLS.Cipher
    import Network.TLS.Context.Internal
    import Network.TLS.Credentials
    import Network.TLS.Crypto
    import Network.TLS.ErrT
    import Network.TLS.Extension
    import Network.TLS.Handshake.Server.Common
    import Network.TLS.Handshake.Signature
    import Network.TLS.Imports
    import Network.TLS.Parameters
    import Network.TLS.State
    import Network.TLS.Struct
    import Network.TLS.Types (CipherId (..), Role (..))

    ----------------------------------------------------------------

    -- serverSupported sparams == ctxSupported ctx

    -- TLS 1.2 or earlier
    processClientHello12
        :: ServerParams
        -> Context
        -> CH
        -> IO (Cipher, Maybe Credential)
    processClientHello12 :: ServerParams -> Context -> CH -> IO (Cipher, Maybe Credential)
    processClientHello12 ServerParams
    sparams Context
    ctx CH
    ch = do
        let secureRenegotiation :: Bool
    secureRenegotiation = Supported -> Bool
    supportedSecureRenegotiation (Supported -> Bool) -> Supported -> Bool
    forall a b. (a -> b) -> a -> b
    $ ServerParams -> Supported
    serverSupported ServerParams
    sparams
        Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    secureRenegotiation (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Context -> CH -> IO ()
    checkSecureRenegotiation Context
    ctx CH
    ch
        serverName <- Context -> TLSSt (Maybe [Char]) -> IO (Maybe [Char])
    forall a. Context -> TLSSt a -> IO a
    usingState_ Context
    ctx TLSSt (Maybe [Char])
    getClientSNI
        let hooks = ServerParams -> ServerHooks
    serverHooks ServerParams
    sparams
        extraCreds <- onServerNameIndication hooks serverName
        let (creds, signatureCreds, ciphersFilteredVersion) =
                credsTriple sparams ch extraCreds
        -- The shared cipherlist can become empty after filtering for compatible
        -- creds, check now before calling onCipherChoosing, which does not handle
        -- empty lists.
        when (null ciphersFilteredVersion) $
            throwCore $
                Error_Protocol "no cipher in common with the TLS 1.2 client" HandshakeFailure
        let usedCipher = ServerHooks -> Version -> [Cipher] -> Cipher
    onCipherChoosing ServerHooks
    hooks Version
    TLS12 [Cipher]
    ciphersFilteredVersion
        mcred <- chooseCreds usedCipher creds signatureCreds
        return (usedCipher, mcred)

    checkSecureRenegotiation :: Context -> CH -> IO ()
    checkSecureRenegotiation :: Context -> CH -> IO ()
    checkSecureRenegotiation Context
    ctx CH{[CipherId]
    [ExtensionRaw]
    Session
    chSession :: Session
    chCiphers :: [CipherId]
    chExtensions :: [ExtensionRaw]
    chExtensions :: CH -> [ExtensionRaw]
    chCiphers :: CH -> [CipherId]
    chSession :: CH -> Session
    ..} = do
        -- RFC 5746: secure renegotiation
        -- TLS_EMPTY_RENEGOTIATION_INFO_SCSV: {0x00, 0xFF}
        Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Word16 -> CipherId
    CipherId Word16
    0xff CipherId -> [CipherId] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [CipherId]
    chCiphers) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
            Context -> TLSSt () -> IO ()
    forall a. Context -> TLSSt a -> IO a
    usingState_ Context
    ctx (TLSSt () -> IO ()) -> TLSSt () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                Bool -> TLSSt ()
    setSecureRenegotiation Bool
    True
        case ExtensionID -> [ExtensionRaw] -> Maybe ByteString
    extensionLookup ExtensionID
    EID_SecureRenegotiation [ExtensionRaw]
    chExtensions of
            Just ByteString
    content -> Context -> TLSSt () -> IO ()
    forall a. Context -> TLSSt a -> IO a
    usingState_ Context
    ctx (TLSSt () -> IO ()) -> TLSSt () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                VerifyData cvd <- Role -> TLSSt VerifyData
    getVerifyData Role
    ClientRole
                let bs = SecureRenegotiation -> ByteString
    forall a. Extension a => a -> ByteString
    extensionEncode (ByteString -> ByteString -> SecureRenegotiation
    SecureRenegotiation ByteString
    cvd ByteString
    "")
                unless (bs == content) $
                    throwError $
                        Error_Protocol
                            ("client verified data not matching: " ++ show cvd ++ ":" ++ show content)
                            HandshakeFailure

                setSecureRenegotiation True
            Maybe ByteString
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    ----------------------------------------------------------------

    credsTriple
        :: ServerParams
        -> CH
        -> Credentials
        -> (Credentials, Credentials, [Cipher])
    credsTriple :: ServerParams
    -> CH -> Credentials -> (Credentials, Credentials, [Cipher])
    credsTriple ServerParams
    sparams CH{[CipherId]
    [ExtensionRaw]
    Session
    chExtensions :: CH -> [ExtensionRaw]
    chCiphers :: CH -> [CipherId]
    chSession :: CH -> Session
    chSession :: Session
    chCiphers :: [CipherId]
    chExtensions :: [ExtensionRaw]
    ..} Credentials
    extraCreds
        | [Cipher] -> Bool
    cipherListCredentialFallback [Cipher]
    cltCiphers = (Credentials
    allCreds, Credentials
    sigAllCreds, [Cipher]
    allCiphers)
        | Bool
    otherwise = (Credentials
    cltCreds, Credentials
    sigCltCreds, [Cipher]
    cltCiphers)
      where
        ciphers :: [Cipher]
    ciphers = Supported -> [Cipher]
    supportedCiphers (Supported -> [Cipher]) -> Supported -> [Cipher]
    forall a b. (a -> b) -> a -> b
    $ ServerParams -> Supported
    serverSupported ServerParams
    sparams

        commonCiphers :: Credentials -> Credentials -> [Cipher]
    commonCiphers Credentials
    creds Credentials
    sigCreds = [CipherId] -> [Cipher] -> [Cipher]
    intersectCiphers [CipherId]
    chCiphers [Cipher]
    availableCiphers
          where
            availableCiphers :: [Cipher]
    availableCiphers = [Cipher] -> Credentials -> Credentials -> [Cipher]
    getCiphers [Cipher]
    ciphers Credentials
    creds Credentials
    sigCreds

        p :: Group -> Bool
    p = Version -> [ExtensionRaw] -> Group -> Bool
    makeCredentialPredicate Version
    TLS12 [ExtensionRaw]
    chExtensions
        allCreds :: Credentials
    allCreds =
            (Credential -> Bool) -> Credentials -> Credentials
    filterCredentials (Version -> (Group -> Bool) -> Credential -> Bool
    isCredentialAllowed Version
    TLS12 Group -> Bool
    p) (Credentials -> Credentials) -> Credentials -> Credentials
    forall a b. (a -> b) -> a -> b
    $
                Credentials
    extraCreds Credentials -> Credentials -> Credentials
    forall a. Monoid a => a -> a -> a
    `mappend` Shared -> Credentials
    sharedCredentials (ServerParams -> Shared
    serverShared ServerParams
    sparams)

        -- When selecting a cipher we must ensure that it is allowed for the
        -- TLS version but also that all its key-exchange requirements
        -- will be met.

        -- Some ciphers require a signature and a hash.  With TLS 1.2 the hash
        -- algorithm is selected from a combination of server configuration and
        -- the client "supported_signatures" extension.  So we cannot pick
        -- such a cipher if no hash is available for it.  It's best to skip this
        -- cipher and pick another one (with another key exchange).

        -- Cipher selection is performed in two steps: first server credentials
        -- are flagged as not suitable for signature if not compatible with
        -- negotiated signature parameters.  Then ciphers are evalutated from
        -- the resulting credentials.

        supported :: Supported
    supported = ServerParams -> Supported
    serverSupported ServerParams
    sparams
        groups :: [Group]
    groups = Supported -> [Group]
    supportedGroups Supported
    supported
        possibleGroups :: [Group]
    possibleGroups = [Group] -> [ExtensionRaw] -> [Group]
    negotiatedGroupsInCommon [Group]
    groups [ExtensionRaw]
    chExtensions
        possibleECGroups :: [Group]
    possibleECGroups = [Group]
    possibleGroups [Group] -> [Group] -> [Group]
    forall a. Eq a => [a] -> [a] -> [a]
    `intersect` [Group]
    availableECGroups
        possibleFFGroups :: [Group]
    possibleFFGroups = [Group]
    possibleGroups [Group] -> [Group] -> [Group]
    forall a. Eq a => [a] -> [a] -> [a]
    `intersect` [Group]
    availableFFGroups
        hasCommonGroupForECDHE :: Bool
    hasCommonGroupForECDHE = Bool -> Bool
    not ([Group] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Group]
    possibleECGroups)
        hasCommonGroupForFFDHE :: Bool
    hasCommonGroupForFFDHE = Bool -> Bool
    not ([Group] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Group]
    possibleFFGroups)
        hasCustomGroupForFFDHE :: Bool
    hasCustomGroupForFFDHE = Maybe DHParams -> Bool
    forall a. Maybe a -> Bool
    isJust (ServerParams -> Maybe DHParams
    serverDHEParams ServerParams
    sparams)
        canFFDHE :: Bool
    canFFDHE = Bool
    hasCustomGroupForFFDHE Bool -> Bool -> Bool
    || Bool
    hasCommonGroupForFFDHE
        hasCommonGroup :: Cipher -> Bool
    hasCommonGroup Cipher
    cipher =
            case Cipher -> CipherKeyExchangeType
    cipherKeyExchange Cipher
    cipher of
                CipherKeyExchangeType
    CipherKeyExchange_DH_Anon -> Bool
    canFFDHE
                CipherKeyExchangeType
    CipherKeyExchange_DHE_RSA -> Bool
    canFFDHE
                CipherKeyExchangeType
    CipherKeyExchange_DHE_DSA -> Bool
    canFFDHE
                CipherKeyExchangeType
    CipherKeyExchange_ECDHE_RSA -> Bool
    hasCommonGroupForECDHE
                CipherKeyExchangeType
    CipherKeyExchange_ECDHE_ECDSA -> Bool
    hasCommonGroupForECDHE
                CipherKeyExchangeType
    _ -> Bool
    True -- group not used

        -- Ciphers are selected according to TLS version, availability of
        -- (EC)DHE group and credential depending on key exchange.
        cipherAllowed :: Cipher -> Bool
    cipherAllowed Cipher
    cipher = Version -> Cipher -> Bool
    cipherAllowedForVersion Version
    TLS12 Cipher
    cipher Bool -> Bool -> Bool
    && Cipher -> Bool
    hasCommonGroup Cipher
    cipher
        selectCipher :: Credentials -> Credentials -> [Cipher]
    selectCipher Credentials
    credentials Credentials
    signatureCredentials = (Cipher -> Bool) -> [Cipher] -> [Cipher]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Cipher -> Bool
    cipherAllowed (Credentials -> Credentials -> [Cipher]
    commonCiphers Credentials
    credentials Credentials
    signatureCredentials)

        -- Build a list of all hash/signature algorithms in common between
        -- client and server.
        hashAndSignatures :: [HashAndSignatureAlgorithm]
    hashAndSignatures = Supported -> [HashAndSignatureAlgorithm]
    supportedHashSignatures Supported
    supported
        possibleHashSigAlgs :: [HashAndSignatureAlgorithm]
    possibleHashSigAlgs = [HashAndSignatureAlgorithm]
    -> [ExtensionRaw] -> [HashAndSignatureAlgorithm]
    hashAndSignaturesInCommon [HashAndSignatureAlgorithm]
    hashAndSignatures [ExtensionRaw]
    chExtensions

        -- Check that a candidate signature credential will be compatible with
        -- client & server hash/signature algorithms.  This returns Just Int
        -- in order to sort credentials according to server hash/signature
        -- preference.  When the certificate has no matching hash/signature in
        -- 'possibleHashSigAlgs' the result is Nothing, and the credential will
        -- not be used to sign.  This avoids a failure later in 'decideHashSig'.
        signingRank :: Credential -> Maybe Int
    signingRank Credential
    cred =
            case Credential -> Maybe PubKey
    credentialDigitalSignatureKey Credential
    cred of
                Just PubKey
    pub -> (HashAndSignatureAlgorithm -> Bool)
    -> [HashAndSignatureAlgorithm] -> Maybe Int
    forall a. (a -> Bool) -> [a] -> Maybe Int
    findIndex (PubKey
    pub PubKey -> HashAndSignatureAlgorithm -> Bool
    `signatureCompatible`) [HashAndSignatureAlgorithm]
    possibleHashSigAlgs
                Maybe PubKey
    Nothing -> Maybe Int
    forall a. Maybe a
    Nothing

        -- Finally compute credential lists and resulting cipher list.
        --
        -- We try to keep certificates supported by the client, but
        -- fallback to all credentials if this produces no suitable result
        -- (see RFC 5246 section 7.4.2 and RFC 8446 section 4.4.2.2).
        -- The condition is based on resulting (EC)DHE ciphers so that
        -- filtering credentials does not give advantage to a less secure
        -- key exchange like CipherKeyExchange_RSA or CipherKeyExchange_DH_Anon.
        cltCreds :: Credentials
    cltCreds = [ExtensionRaw] -> Credentials -> Credentials
    filterCredentialsWithHashSignatures [ExtensionRaw]
    chExtensions Credentials
    allCreds
        sigCltCreds :: Credentials
    sigCltCreds = (Credential -> Maybe Int) -> Credentials -> Credentials
    forall a.
    Ord a =>
    (Credential -> Maybe a) -> Credentials -> Credentials
    filterSortCredentials Credential -> Maybe Int
    signingRank Credentials
    cltCreds
        sigAllCreds :: Credentials
    sigAllCreds = (Credential -> Maybe Int) -> Credentials -> Credentials
    forall a.
    Ord a =>
    (Credential -> Maybe a) -> Credentials -> Credentials
    filterSortCredentials Credential -> Maybe Int
    signingRank Credentials
    allCreds
        cltCiphers :: [Cipher]
    cltCiphers = Credentials -> Credentials -> [Cipher]
    selectCipher Credentials
    cltCreds Credentials
    sigCltCreds
        allCiphers :: [Cipher]
    allCiphers = Credentials -> Credentials -> [Cipher]
    selectCipher Credentials
    allCreds Credentials
    sigAllCreds

    chooseCreds :: Cipher -> Credentials -> Credentials -> IO (Maybe Credential)
    chooseCreds :: Cipher -> Credentials -> Credentials -> IO (Maybe Credential)
    chooseCreds Cipher
    usedCipher Credentials
    creds Credentials
    signatureCreds = case Cipher -> CipherKeyExchangeType
    cipherKeyExchange Cipher
    usedCipher of
        CipherKeyExchangeType
    CipherKeyExchange_RSA -> Maybe Credential -> IO (Maybe Credential)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Credential -> IO (Maybe Credential))
    -> Maybe Credential -> IO (Maybe Credential)
    forall a b. (a -> b) -> a -> b
    $ Credentials -> Maybe Credential
    credentialsFindForDecrypting Credentials
    creds
        CipherKeyExchangeType
    CipherKeyExchange_DH_Anon -> Maybe Credential -> IO (Maybe Credential)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe Credential
    forall a. Maybe a
    Nothing
        CipherKeyExchangeType
    CipherKeyExchange_DHE_RSA -> Maybe Credential -> IO (Maybe Credential)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Credential -> IO (Maybe Credential))
    -> Maybe Credential -> IO (Maybe Credential)
    forall a b. (a -> b) -> a -> b
    $ KeyExchangeSignatureAlg -> Credentials -> Maybe Credential
    credentialsFindForSigning KeyExchangeSignatureAlg
    KX_RSA Credentials
    signatureCreds
        CipherKeyExchangeType
    CipherKeyExchange_DHE_DSA -> Maybe Credential -> IO (Maybe Credential)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Credential -> IO (Maybe Credential))
    -> Maybe Credential -> IO (Maybe Credential)
    forall a b. (a -> b) -> a -> b
    $ KeyExchangeSignatureAlg -> Credentials -> Maybe Credential
    credentialsFindForSigning KeyExchangeSignatureAlg
    KX_DSA Credentials
    signatureCreds
        CipherKeyExchangeType
    CipherKeyExchange_ECDHE_RSA -> Maybe Credential -> IO (Maybe Credential)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Credential -> IO (Maybe Credential))
    -> Maybe Credential -> IO (Maybe Credential)
    forall a b. (a -> b) -> a -> b
    $ KeyExchangeSignatureAlg -> Credentials -> Maybe Credential
    credentialsFindForSigning KeyExchangeSignatureAlg
    KX_RSA Credentials
    signatureCreds
        CipherKeyExchangeType
    CipherKeyExchange_ECDHE_ECDSA -> Maybe Credential -> IO (Maybe Credential)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Credential -> IO (Maybe Credential))
    -> Maybe Credential -> IO (Maybe Credential)
    forall a b. (a -> b) -> a -> b
    $ KeyExchangeSignatureAlg -> Credentials -> Maybe Credential
    credentialsFindForSigning KeyExchangeSignatureAlg
    KX_ECDSA Credentials
    signatureCreds
        CipherKeyExchangeType
    _ ->
            TLSError -> IO (Maybe Credential)
    forall (m :: * -> *) a. MonadIO m => TLSError -> m a
    throwCore (TLSError -> IO (Maybe Credential))
    -> TLSError -> IO (Maybe Credential)
    forall a b. (a -> b) -> a -> b
    $
                [Char] -> AlertDescription -> TLSError
    Error_Protocol [Char]
    "key exchange algorithm not implemented" AlertDescription
    HandshakeFailure

    ----------------------------------------------------------------

    negotiatedGroupsInCommon :: [Group] -> [ExtensionRaw] -> [Group]
    negotiatedGroupsInCommon :: [Group] -> [ExtensionRaw] -> [Group]
    negotiatedGroupsInCommon [Group]
    serverGroups [ExtensionRaw]
    exts =
        ExtensionID
    -> MessageType
    -> [ExtensionRaw]
    -> [Group]
    -> (SupportedGroups -> [Group])
    -> [Group]
    forall e a.
    Extension e =>
    ExtensionID -> MessageType -> [ExtensionRaw] -> a -> (e -> a) -> a
    lookupAndDecode
            ExtensionID
    EID_SupportedGroups
            MessageType
    MsgTClientHello
            [ExtensionRaw]
    exts
            []
            (\(SupportedGroups [Group]
    clientGroups) -> [Group]
    serverGroups [Group] -> [Group] -> [Group]
    forall a. Eq a => [a] -> [a] -> [a]
    `intersect` [Group]
    clientGroups)

    ----------------------------------------------------------------

    filterSortCredentials
        :: Ord a => (Credential -> Maybe a) -> Credentials -> Credentials
    filterSortCredentials :: forall a.
    Ord a =>
    (Credential -> Maybe a) -> Credentials -> Credentials
    filterSortCredentials Credential -> Maybe a
    rankFun (Credentials [Credential]
    creds) =
        let orderedPairs :: [(Maybe a, Credential)]
    orderedPairs = ((Maybe a, Credential) -> Maybe a)
    -> [(Maybe a, Credential)] -> [(Maybe a, Credential)]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn (Maybe a, Credential) -> Maybe a
    forall a b. (a, b) -> a
    fst [(Credential -> Maybe a
    rankFun Credential
    cred, Credential
    cred) | Credential
    cred <- [Credential]
    creds]
         in [Credential] -> Credentials
    Credentials [Credential
    cred | (Just a
    _, Credential
    cred) <- [(Maybe a, Credential)]
    orderedPairs]

    -- returns True if certificate filtering with "signature_algorithms_cert" /
    -- "signature_algorithms" produced no ephemeral D-H nor TLS13 cipher (so
    -- handshake with lower security)
    cipherListCredentialFallback :: [Cipher] -> Bool
    cipherListCredentialFallback :: [Cipher] -> Bool
    cipherListCredentialFallback = (Cipher -> Bool) -> [Cipher] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Cipher -> Bool
    nonDH
      where
        nonDH :: Cipher -> Bool
    nonDH Cipher
    x = case Cipher -> CipherKeyExchangeType
    cipherKeyExchange Cipher
    x of
            CipherKeyExchangeType
    CipherKeyExchange_DHE_RSA -> Bool
    False
            CipherKeyExchangeType
    CipherKeyExchange_DHE_DSA -> Bool
    False
            CipherKeyExchangeType
    CipherKeyExchange_ECDHE_RSA -> Bool
    False
            CipherKeyExchangeType
    CipherKeyExchange_ECDHE_ECDSA -> Bool
    False
            CipherKeyExchangeType
    CipherKeyExchange_TLS13 -> Bool
    False
            CipherKeyExchangeType
    _ -> Bool
    True

    -- We filter our allowed ciphers here according to dynamic credential lists.
    -- Credentials 'creds' come from server parameters but also SNI callback.
    -- When the key exchange requires a signature, we use a
    -- subset of this list named 'sigCreds'.  This list has been filtered in order
    -- to remove certificates that are not compatible with hash/signature
    -- restrictions (TLS 1.2).
    getCiphers :: [Cipher] -> Credentials -> Credentials -> [Cipher]
    getCiphers :: [Cipher] -> Credentials -> Credentials -> [Cipher]
    getCiphers [Cipher]
    ciphers Credentials
    creds Credentials
    sigCreds = (Cipher -> Bool) -> [Cipher] -> [Cipher]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Cipher -> Bool
    authorizedCKE [Cipher]
    ciphers
      where
        authorizedCKE :: Cipher -> Bool
    authorizedCKE Cipher
    cipher =
            case Cipher -> CipherKeyExchangeType
    cipherKeyExchange Cipher
    cipher of
                CipherKeyExchangeType
    CipherKeyExchange_RSA -> Bool
    canEncryptRSA
                CipherKeyExchangeType
    CipherKeyExchange_DH_Anon -> Bool
    True
                CipherKeyExchangeType
    CipherKeyExchange_DHE_RSA -> Bool
    canSignRSA
                CipherKeyExchangeType
    CipherKeyExchange_DHE_DSA -> Bool
    canSignDSA
                CipherKeyExchangeType
    CipherKeyExchange_ECDHE_RSA -> Bool
    canSignRSA
                CipherKeyExchangeType
    CipherKeyExchange_ECDHE_ECDSA -> Bool
    canSignECDSA
                -- unimplemented: non ephemeral DH & ECDH.
                -- Note, these *should not* be implemented, and have
                -- (for example) been removed in OpenSSL 1.1.0
                --
                CipherKeyExchangeType
    CipherKeyExchange_DH_DSA -> Bool
    False
                CipherKeyExchangeType
    CipherKeyExchange_DH_RSA -> Bool
    False
                CipherKeyExchangeType
    CipherKeyExchange_ECDH_ECDSA -> Bool
    False
                CipherKeyExchangeType
    CipherKeyExchange_ECDH_RSA -> Bool
    False
                CipherKeyExchangeType
    CipherKeyExchange_TLS13 -> Bool
    False -- not reached
        canSignDSA :: Bool
    canSignDSA = KeyExchangeSignatureAlg
    KX_DSA KeyExchangeSignatureAlg -> [KeyExchangeSignatureAlg] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [KeyExchangeSignatureAlg]
    signingAlgs
        canSignRSA :: Bool
    canSignRSA = KeyExchangeSignatureAlg
    KX_RSA KeyExchangeSignatureAlg -> [KeyExchangeSignatureAlg] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [KeyExchangeSignatureAlg]
    signingAlgs
        canSignECDSA :: Bool
    canSignECDSA = KeyExchangeSignatureAlg
    KX_ECDSA KeyExchangeSignatureAlg -> [KeyExchangeSignatureAlg] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [KeyExchangeSignatureAlg]
    signingAlgs
        canEncryptRSA :: Bool
    canEncryptRSA = Maybe Credential -> Bool
    forall a. Maybe a -> Bool
    isJust (Maybe Credential -> Bool) -> Maybe Credential -> Bool
    forall a b. (a -> b) -> a -> b
    $ Credentials -> Maybe Credential
    credentialsFindForDecrypting Credentials
    creds
        signingAlgs :: [KeyExchangeSignatureAlg]
    signingAlgs = Credentials -> [KeyExchangeSignatureAlg]
    credentialsListSigningAlgorithms Credentials
    sigCreds