    -- |
    -- Module      : Data.X509.Validation.Signature
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- X.509 Certificate and CRL signature verification
    --
    module Data.X509.Validation.Signature
        ( verifySignedSignature
        , verifySignature
        , SignatureVerification(..)
        , SignatureFailure(..)
        ) where

    import Crypto.Error (CryptoFailable(..))
    import qualified Crypto.PubKey.RSA.PKCS15 as RSA
    import qualified Crypto.PubKey.RSA.PSS as PSS
    import qualified Crypto.PubKey.DSA as DSA
    import qualified Crypto.PubKey.ECC.Types as ECC
    import qualified Crypto.PubKey.ECC.ECDSA as ECDSA
    import qualified Crypto.PubKey.Ed25519 as Ed25519
    import qualified Crypto.PubKey.Ed448 as Ed448
    import Crypto.Hash

    import Data.ByteString (ByteString)
    import Data.X509
    import Data.X509.EC
    import Data.ASN1.Types
    import Data.ASN1.Encoding
    import Data.ASN1.BinaryEncoding

    -- | A set of possible return from signature verification.
    --
    -- When SignatureFailed is return, the signature shouldn't be
    -- accepted.
    --
    -- Other values are only useful to differentiate the failure
    -- reason, but are all equivalent to failure.
    --
    data SignatureVerification =
          SignaturePass                    -- ^ verification succeeded
        | SignatureFailed SignatureFailure -- ^ verification failed
        deriving (Int -> SignatureVerification -> ShowS
    [SignatureVerification] -> ShowS
    SignatureVerification -> String
    (Int -> SignatureVerification -> ShowS)
    -> (SignatureVerification -> String)
    -> ([SignatureVerification] -> ShowS)
    -> Show SignatureVerification
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> SignatureVerification -> ShowS
    showsPrec :: Int -> SignatureVerification -> ShowS
    $cshow :: SignatureVerification -> String
    show :: SignatureVerification -> String
    $cshowList :: [SignatureVerification] -> ShowS
    showList :: [SignatureVerification] -> ShowS
    Show,SignatureVerification -> SignatureVerification -> Bool
    (SignatureVerification -> SignatureVerification -> Bool)
    -> (SignatureVerification -> SignatureVerification -> Bool)
    -> Eq SignatureVerification
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: SignatureVerification -> SignatureVerification -> Bool
    == :: SignatureVerification -> SignatureVerification -> Bool
    $c/= :: SignatureVerification -> SignatureVerification -> Bool
    /= :: SignatureVerification -> SignatureVerification -> Bool
    Eq)

    -- | Various failure possible during signature checking
    data SignatureFailure =
          SignatureInvalid        -- ^ signature doesn't verify
        | SignaturePubkeyMismatch -- ^ algorithm and public key mismatch, cannot proceed
        | SignatureUnimplemented  -- ^ unimplemented signature algorithm
        deriving (Int -> SignatureFailure -> ShowS
    [SignatureFailure] -> ShowS
    SignatureFailure -> String
    (Int -> SignatureFailure -> ShowS)
    -> (SignatureFailure -> String)
    -> ([SignatureFailure] -> ShowS)
    -> Show SignatureFailure
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> SignatureFailure -> ShowS
    showsPrec :: Int -> SignatureFailure -> ShowS
    $cshow :: SignatureFailure -> String
    show :: SignatureFailure -> String
    $cshowList :: [SignatureFailure] -> ShowS
    showList :: [SignatureFailure] -> ShowS
    Show,SignatureFailure -> SignatureFailure -> Bool
    (SignatureFailure -> SignatureFailure -> Bool)
    -> (SignatureFailure -> SignatureFailure -> Bool)
    -> Eq SignatureFailure
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: SignatureFailure -> SignatureFailure -> Bool
    == :: SignatureFailure -> SignatureFailure -> Bool
    $c/= :: SignatureFailure -> SignatureFailure -> Bool
    /= :: SignatureFailure -> SignatureFailure -> Bool
    Eq)

    -- | Verify a Signed object against a specified public key
    verifySignedSignature :: (Show a, Eq a, ASN1Object a)
                          => SignedExact a
                          -> PubKey
                          -> SignatureVerification
    verifySignedSignature :: forall a.
    (Show a, Eq a, ASN1Object a) =>
    SignedExact a -> PubKey -> SignatureVerification
    verifySignedSignature SignedExact a
    signedObj PubKey
    pubKey =
        SignatureALG
    -> PubKey -> ByteString -> ByteString -> SignatureVerification
    verifySignature (Signed a -> SignatureALG
    forall a. (Show a, Eq a, ASN1Object a) => Signed a -> SignatureALG
    signedAlg Signed a
    signed)
                        PubKey
    pubKey
                        (SignedExact a -> ByteString
    forall a.
    (Show a, Eq a, ASN1Object a) =>
    SignedExact a -> ByteString
    getSignedData SignedExact a
    signedObj)
                        (Signed a -> ByteString
    forall a. (Show a, Eq a, ASN1Object a) => Signed a -> ByteString
    signedSignature Signed a
    signed)
      where signed :: Signed a
    signed = SignedExact a -> Signed a
    forall a. (Show a, Eq a, ASN1Object a) => SignedExact a -> Signed a
    getSigned SignedExact a
    signedObj

    -- | verify signature using parameter
    verifySignature :: SignatureALG -- ^ Signature algorithm used
                    -> PubKey       -- ^ Public key to use for verify
                    -> ByteString   -- ^ Certificate data that need to be verified
                    -> ByteString   -- ^ Signature to verify
                    -> SignatureVerification
    verifySignature :: SignatureALG
    -> PubKey -> ByteString -> ByteString -> SignatureVerification
    verifySignature (SignatureALG_Unknown OID
    _) PubKey
    _ ByteString
    _ ByteString
    _ = SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureUnimplemented
    verifySignature (SignatureALG HashALG
    hashALG PubKeyALG
    PubKeyALG_RSAPSS) PubKey
    pubkey ByteString
    cdata ByteString
    signature = case PubKey -> Maybe (ByteString -> ByteString -> Bool)
    verifyF PubKey
    pubkey of
      Maybe (ByteString -> ByteString -> Bool)
    Nothing    -> SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureUnimplemented
      Just ByteString -> ByteString -> Bool
    f -> if ByteString -> ByteString -> Bool
    f ByteString
    cdata ByteString
    signature
                   then SignatureVerification
    SignaturePass
                   else SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureInvalid
      where
        verifyF :: PubKey -> Maybe (ByteString -> ByteString -> Bool)
    verifyF (PubKeyRSA PublicKey
    key)
          | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA256 = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ PSSParams SHA256 ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    forall hash.
    HashAlgorithm hash =>
    PSSParams hash ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    PSS.verify (SHA256 -> PSSParams SHA256 ByteString ByteString
    forall seed output hash.
    (ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
    hash -> PSSParams hash seed output
    PSS.defaultPSSParams SHA256
    SHA256) PublicKey
    key
          | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA384 = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ PSSParams SHA384 ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    forall hash.
    HashAlgorithm hash =>
    PSSParams hash ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    PSS.verify (SHA384 -> PSSParams SHA384 ByteString ByteString
    forall seed output hash.
    (ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
    hash -> PSSParams hash seed output
    PSS.defaultPSSParams SHA384
    SHA384) PublicKey
    key
          | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA512 = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ PSSParams SHA512 ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    forall hash.
    HashAlgorithm hash =>
    PSSParams hash ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    PSS.verify (SHA512 -> PSSParams SHA512 ByteString ByteString
    forall seed output hash.
    (ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
    hash -> PSSParams hash seed output
    PSS.defaultPSSParams SHA512
    SHA512) PublicKey
    key
          | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA224 = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ PSSParams SHA224 ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    forall hash.
    HashAlgorithm hash =>
    PSSParams hash ByteString ByteString
    -> PublicKey -> ByteString -> ByteString -> Bool
    PSS.verify (SHA224 -> PSSParams SHA224 ByteString ByteString
    forall seed output hash.
    (ByteArrayAccess seed, ByteArray output, HashAlgorithm hash) =>
    hash -> PSSParams hash seed output
    PSS.defaultPSSParams SHA224
    SHA224) PublicKey
    key
          | Bool
    otherwise             = Maybe (ByteString -> ByteString -> Bool)
    forall a. Maybe a
    Nothing
        verifyF PubKey
    _                 = Maybe (ByteString -> ByteString -> Bool)
    forall a. Maybe a
    Nothing
    verifySignature (SignatureALG HashALG
    hashALG PubKeyALG
    pubkeyALG) PubKey
    pubkey ByteString
    cdata ByteString
    signature
        | PubKey -> PubKeyALG
    pubkeyToAlg PubKey
    pubkey PubKeyALG -> PubKeyALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == PubKeyALG
    pubkeyALG = case PubKey -> Maybe (ByteString -> ByteString -> Bool)
    verifyF PubKey
    pubkey of
                                                Maybe (ByteString -> ByteString -> Bool)
    Nothing -> SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureUnimplemented
                                                Just ByteString -> ByteString -> Bool
    f  -> if ByteString -> ByteString -> Bool
    f ByteString
    cdata ByteString
    signature
                                                                then SignatureVerification
    SignaturePass
                                                                else SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureInvalid
        | Bool
    otherwise                       = SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignaturePubkeyMismatch
      where
            verifyF :: PubKey -> Maybe (ByteString -> ByteString -> Bool)
    verifyF (PubKeyRSA PublicKey
    key) = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ HashALG -> PublicKey -> ByteString -> ByteString -> Bool
    rsaVerify HashALG
    hashALG PublicKey
    key
            verifyF (PubKeyDSA PublicKey
    key)
                | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA1   = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ SHA1 -> PublicKey -> ByteString -> ByteString -> Bool
    forall {msg} {hash}.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> msg -> ByteString -> Bool
    dsaVerify SHA1
    SHA1   PublicKey
    key
                | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA224 = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ SHA224 -> PublicKey -> ByteString -> ByteString -> Bool
    forall {msg} {hash}.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> msg -> ByteString -> Bool
    dsaVerify SHA224
    SHA224 PublicKey
    key
                | HashALG
    hashALG HashALG -> HashALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == HashALG
    HashSHA256 = (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((ByteString -> ByteString -> Bool)
     -> Maybe (ByteString -> ByteString -> Bool))
    -> (ByteString -> ByteString -> Bool)
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ SHA256 -> PublicKey -> ByteString -> ByteString -> Bool
    forall {msg} {hash}.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> msg -> ByteString -> Bool
    dsaVerify SHA256
    SHA256 PublicKey
    key
                | Bool
    otherwise           = Maybe (ByteString -> ByteString -> Bool)
    forall a. Maybe a
    Nothing
            verifyF (PubKeyEC PubKeyEC
    key) = HashALG -> PubKeyEC -> Maybe (ByteString -> ByteString -> Bool)
    verifyECDSA HashALG
    hashALG PubKeyEC
    key
            verifyF PubKey
    _ = Maybe (ByteString -> ByteString -> Bool)
    forall a. Maybe a
    Nothing

            dsaToSignature :: ByteString -> Maybe DSA.Signature
            dsaToSignature :: ByteString -> Maybe Signature
    dsaToSignature ByteString
    b =
                case BER -> ByteString -> Either ASN1Error [ASN1]
    forall a.
    ASN1Decoding a =>
    a -> ByteString -> Either ASN1Error [ASN1]
    decodeASN1' BER
    BER ByteString
    b of
                    Left ASN1Error
    _     -> Maybe Signature
    forall a. Maybe a
    Nothing
                    Right [ASN1]
    asn1 ->
                        case [ASN1]
    asn1 of
                            Start ASN1ConstructionType
    Sequence:IntVal Integer
    r:IntVal Integer
    s:End ASN1ConstructionType
    Sequence:[ASN1]
    _ ->
                                Signature -> Maybe Signature
    forall a. a -> Maybe a
    Just (Signature -> Maybe Signature) -> Signature -> Maybe Signature
    forall a b. (a -> b) -> a -> b
    $ DSA.Signature { sign_r :: Integer
    DSA.sign_r = Integer
    r, sign_s :: Integer
    DSA.sign_s = Integer
    s }
                            [ASN1]
    _ ->
                                Maybe Signature
    forall a. Maybe a
    Nothing

            dsaVerify :: hash -> PublicKey -> msg -> ByteString -> Bool
    dsaVerify hash
    hsh PublicKey
    key msg
    b ByteString
    a =
                case ByteString -> Maybe Signature
    dsaToSignature ByteString
    a of
                    Maybe Signature
    Nothing     -> Bool
    False
                    Just Signature
    dsaSig -> hash -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    DSA.verify hash
    hsh PublicKey
    key Signature
    dsaSig msg
    b

            rsaVerify :: HashALG -> PublicKey -> ByteString -> ByteString -> Bool
    rsaVerify HashALG
    HashMD2    = Maybe MD2 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (MD2 -> Maybe MD2
    forall a. a -> Maybe a
    Just MD2
    MD2)
            rsaVerify HashALG
    HashMD5    = Maybe MD5 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (MD5 -> Maybe MD5
    forall a. a -> Maybe a
    Just MD5
    MD5)
            rsaVerify HashALG
    HashSHA1   = Maybe SHA1 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (SHA1 -> Maybe SHA1
    forall a. a -> Maybe a
    Just SHA1
    SHA1)
            rsaVerify HashALG
    HashSHA224 = Maybe SHA224 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (SHA224 -> Maybe SHA224
    forall a. a -> Maybe a
    Just SHA224
    SHA224)
            rsaVerify HashALG
    HashSHA256 = Maybe SHA256 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (SHA256 -> Maybe SHA256
    forall a. a -> Maybe a
    Just SHA256
    SHA256)
            rsaVerify HashALG
    HashSHA384 = Maybe SHA384 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (SHA384 -> Maybe SHA384
    forall a. a -> Maybe a
    Just SHA384
    SHA384)
            rsaVerify HashALG
    HashSHA512 = Maybe SHA512 -> PublicKey -> ByteString -> ByteString -> Bool
    forall hashAlg.
    HashAlgorithmASN1 hashAlg =>
    Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
    RSA.verify (SHA512 -> Maybe SHA512
    forall a. a -> Maybe a
    Just SHA512
    SHA512)

    verifySignature (SignatureALG_IntrinsicHash PubKeyALG
    pubkeyALG) PubKey
    pubkey ByteString
    cdata ByteString
    signature
        | PubKey -> PubKeyALG
    pubkeyToAlg PubKey
    pubkey PubKeyALG -> PubKeyALG -> Bool
    forall a. Eq a => a -> a -> Bool
    == PubKeyALG
    pubkeyALG = PubKey -> SignatureVerification
    doVerify PubKey
    pubkey
        | Bool
    otherwise = SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignaturePubkeyMismatch
      where
        doVerify :: PubKey -> SignatureVerification
    doVerify (PubKeyEd25519 PublicKey
    key) = (PublicKey -> ByteString -> Signature -> Bool)
    -> (ByteString -> CryptoFailable Signature)
    -> PublicKey
    -> SignatureVerification
    forall {t} {t}.
    (t -> ByteString -> t -> Bool)
    -> (ByteString -> CryptoFailable t) -> t -> SignatureVerification
    eddsa PublicKey -> ByteString -> Signature -> Bool
    forall ba.
    ByteArrayAccess ba =>
    PublicKey -> ba -> Signature -> Bool
    Ed25519.verify ByteString -> CryptoFailable Signature
    forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
    Ed25519.signature PublicKey
    key
        doVerify (PubKeyEd448 PublicKey
    key)   = (PublicKey -> ByteString -> Signature -> Bool)
    -> (ByteString -> CryptoFailable Signature)
    -> PublicKey
    -> SignatureVerification
    forall {t} {t}.
    (t -> ByteString -> t -> Bool)
    -> (ByteString -> CryptoFailable t) -> t -> SignatureVerification
    eddsa PublicKey -> ByteString -> Signature -> Bool
    forall ba.
    ByteArrayAccess ba =>
    PublicKey -> ba -> Signature -> Bool
    Ed448.verify ByteString -> CryptoFailable Signature
    forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
    Ed448.signature PublicKey
    key
        doVerify PubKey
    _                   = SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureUnimplemented

        eddsa :: (t -> ByteString -> t -> Bool)
    -> (ByteString -> CryptoFailable t) -> t -> SignatureVerification
    eddsa t -> ByteString -> t -> Bool
    verify ByteString -> CryptoFailable t
    toSig t
    key =
            case ByteString -> CryptoFailable t
    toSig ByteString
    signature of
                CryptoPassed t
    sig
                    | t -> ByteString -> t -> Bool
    verify t
    key ByteString
    cdata t
    sig -> SignatureVerification
    SignaturePass
                    | Bool
    otherwise            -> SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureInvalid
                CryptoFailed CryptoError
    _             -> SignatureFailure -> SignatureVerification
    SignatureFailed SignatureFailure
    SignatureInvalid

    verifyECDSA :: HashALG -> PubKeyEC -> Maybe (ByteString -> ByteString -> Bool)
    verifyECDSA :: HashALG -> PubKeyEC -> Maybe (ByteString -> ByteString -> Bool)
    verifyECDSA HashALG
    hashALG PubKeyEC
    key =
        PubKeyEC -> Maybe CurveName
    ecPubKeyCurveName PubKeyEC
    key Maybe CurveName
    -> (CurveName -> Maybe (ByteString -> ByteString -> Bool))
    -> Maybe (ByteString -> ByteString -> Bool)
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= SerializedPoint
    -> CurveName -> Maybe (ByteString -> ByteString -> Bool)
    forall {msg}.
    ByteArrayAccess msg =>
    SerializedPoint -> CurveName -> Maybe (msg -> ByteString -> Bool)
    verifyCurve (PubKeyEC -> SerializedPoint
    pubkeyEC_pub PubKeyEC
    key)
      where
            verifyCurve :: SerializedPoint -> CurveName -> Maybe (msg -> ByteString -> Bool)
    verifyCurve SerializedPoint
    pub CurveName
    curveName = (msg -> ByteString -> Bool) -> Maybe (msg -> ByteString -> Bool)
    forall a. a -> Maybe a
    Just ((msg -> ByteString -> Bool) -> Maybe (msg -> ByteString -> Bool))
    -> (msg -> ByteString -> Bool) -> Maybe (msg -> ByteString -> Bool)
    forall a b. (a -> b) -> a -> b
    $ \msg
    msg ByteString
    sigBS ->
                case BER -> ByteString -> Either ASN1Error [ASN1]
    forall a.
    ASN1Decoding a =>
    a -> ByteString -> Either ASN1Error [ASN1]
    decodeASN1' BER
    BER ByteString
    sigBS of
                    Left ASN1Error
    _ -> Bool
    False
                    Right [Start ASN1ConstructionType
    Sequence,IntVal Integer
    r,IntVal Integer
    s,End ASN1ConstructionType
    Sequence] ->
                        let curve :: Curve
    curve = CurveName -> Curve
    ECC.getCurveByName CurveName
    curveName
                         in case Curve -> SerializedPoint -> Maybe Point
    unserializePoint Curve
    curve SerializedPoint
    pub of
                                Maybe Point
    Nothing -> Bool
    False
                                Just Point
    p  -> let pubkey :: PublicKey
    pubkey = Curve -> Point -> PublicKey
    ECDSA.PublicKey Curve
    curve Point
    p
                                            in (HashALG -> PublicKey -> Signature -> msg -> Bool
    forall {msg}.
    ByteArrayAccess msg =>
    HashALG -> PublicKey -> Signature -> msg -> Bool
    ecdsaVerify HashALG
    hashALG) PublicKey
    pubkey (Integer -> Integer -> Signature
    ECDSA.Signature Integer
    r Integer
    s) msg
    msg
                    Right [ASN1]
    _ -> Bool
    False

            ecdsaVerify :: HashALG -> PublicKey -> Signature -> msg -> Bool
    ecdsaVerify HashALG
    HashMD2    = MD2 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify MD2
    MD2
            ecdsaVerify HashALG
    HashMD5    = MD5 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify MD5
    MD5
            ecdsaVerify HashALG
    HashSHA1   = SHA1 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify SHA1
    SHA1
            ecdsaVerify HashALG
    HashSHA224 = SHA224 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify SHA224
    SHA224
            ecdsaVerify HashALG
    HashSHA256 = SHA256 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify SHA256
    SHA256
            ecdsaVerify HashALG
    HashSHA384 = SHA384 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify SHA384
    SHA384
            ecdsaVerify HashALG
    HashSHA512 = SHA512 -> PublicKey -> Signature -> msg -> Bool
    forall msg hash.
    (ByteArrayAccess msg, HashAlgorithm hash) =>
    hash -> PublicKey -> Signature -> msg -> Bool
    ECDSA.verify SHA512
    SHA512