    {-# LANGUAGE DeriveDataTypeable       #-}
    {-# LANGUAGE ForeignFunctionInterface #-}
    {-# LANGUAGE CApiFFI #-}
    -- |Message verification using asymmetric cipher and message digest
    -- algorithm. This is an opposite of "OpenSSL.EVP.Sign".
    module OpenSSL.EVP.Verify
        ( VerifyStatus(..)
        , verify
        , verifyBS
        , verifyLBS
        )
        where
    import qualified Data.ByteString.Char8 as B8
    import qualified Data.ByteString.Lazy.Char8 as L8
    import qualified Data.ByteString.Unsafe as B8
    import           Data.Typeable
    import           Foreign
    import           Foreign.C
    import           OpenSSL.EVP.Digest
    import           OpenSSL.EVP.PKey
    import           OpenSSL.EVP.Internal
    import           OpenSSL.Utils

    -- |@'VerifyStatus'@ represents a result of verification.
    data VerifyStatus = VerifySuccess
                      | VerifyFailure
                        deriving (Int -> VerifyStatus -> ShowS
    [VerifyStatus] -> ShowS
    VerifyStatus -> String
    (Int -> VerifyStatus -> ShowS)
    -> (VerifyStatus -> String)
    -> ([VerifyStatus] -> ShowS)
    -> Show VerifyStatus
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> VerifyStatus -> ShowS
    showsPrec :: Int -> VerifyStatus -> ShowS
    $cshow :: VerifyStatus -> String
    show :: VerifyStatus -> String
    $cshowList :: [VerifyStatus] -> ShowS
    showList :: [VerifyStatus] -> ShowS
    Show, VerifyStatus -> VerifyStatus -> Bool
    (VerifyStatus -> VerifyStatus -> Bool)
    -> (VerifyStatus -> VerifyStatus -> Bool) -> Eq VerifyStatus
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: VerifyStatus -> VerifyStatus -> Bool
    == :: VerifyStatus -> VerifyStatus -> Bool
    $c/= :: VerifyStatus -> VerifyStatus -> Bool
    /= :: VerifyStatus -> VerifyStatus -> Bool
    Eq, Typeable)

    foreign import capi unsafe "openssl/evp.h EVP_VerifyFinal"
            _VerifyFinal :: Ptr EVP_MD_CTX -> Ptr CChar -> CUInt -> Ptr EVP_PKEY -> IO CInt

    verifyFinalBS :: PublicKey k =>
                     DigestCtx
                  -> B8.ByteString
                  -> k
                  -> IO VerifyStatus
    verifyFinalBS :: forall k.
    PublicKey k =>
    DigestCtx -> ByteString -> k -> IO VerifyStatus
    verifyFinalBS DigestCtx
    ctx ByteString
    sig k
    k
        = DigestCtx -> (Ptr EVP_MD_CTX -> IO VerifyStatus) -> IO VerifyStatus
    forall a. DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a
    withDigestCtxPtr DigestCtx
    ctx ((Ptr EVP_MD_CTX -> IO VerifyStatus) -> IO VerifyStatus)
    -> (Ptr EVP_MD_CTX -> IO VerifyStatus) -> IO VerifyStatus
    forall a b. (a -> b) -> a -> b
    $ \ Ptr EVP_MD_CTX
    ctxPtr ->
          ByteString -> (CStringLen -> IO VerifyStatus) -> IO VerifyStatus
    forall a. ByteString -> (CStringLen -> IO a) -> IO a
    B8.unsafeUseAsCStringLen ByteString
    sig ((CStringLen -> IO VerifyStatus) -> IO VerifyStatus)
    -> (CStringLen -> IO VerifyStatus) -> IO VerifyStatus
    forall a b. (a -> b) -> a -> b
    $ \ (Ptr CChar
    buf, Int
    len) ->
          k -> (Ptr EVP_PKEY -> IO VerifyStatus) -> IO VerifyStatus
    forall k a. PKey k => k -> (Ptr EVP_PKEY -> IO a) -> IO a
    withPKeyPtr' k
    k ((Ptr EVP_PKEY -> IO VerifyStatus) -> IO VerifyStatus)
    -> (Ptr EVP_PKEY -> IO VerifyStatus) -> IO VerifyStatus
    forall a b. (a -> b) -> a -> b
    $ \ Ptr EVP_PKEY
    pkeyPtr ->
          Ptr EVP_MD_CTX -> Ptr CChar -> CUInt -> Ptr EVP_PKEY -> IO CInt
    _VerifyFinal Ptr EVP_MD_CTX
    ctxPtr Ptr CChar
    buf (Int -> CUInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    len) Ptr EVP_PKEY
    pkeyPtr IO CInt -> (CInt -> IO VerifyStatus) -> IO VerifyStatus
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= CInt -> IO VerifyStatus
    interpret
        where
          interpret :: CInt -> IO VerifyStatus
          interpret :: CInt -> IO VerifyStatus
    interpret CInt
    1 = VerifyStatus -> IO VerifyStatus
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return VerifyStatus
    VerifySuccess
          interpret CInt
    0 = VerifyStatus -> IO VerifyStatus
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return VerifyStatus
    VerifyFailure
          interpret CInt
    _ = IO VerifyStatus
    forall a. IO a
    raiseOpenSSLError

    -- |@'verify'@ verifies a signature and a stream of data. The string
    -- must not contain any letters which aren't in the range of U+0000 -
    -- U+00FF.
    verify :: PublicKey key =>
              Digest          -- ^ message digest algorithm to use
           -> String          -- ^ message signature
           -> key             -- ^ public key to verify the signature
           -> String          -- ^ input string to verify
           -> IO VerifyStatus -- ^ the result of verification
    {-# DEPRECATED verify "Use verifyBS or verifyLBS instead." #-}
    verify :: forall key.
    PublicKey key =>
    Digest -> String -> key -> String -> IO VerifyStatus
    verify Digest
    md String
    sig key
    pkey String
    input
        = Digest -> ByteString -> key -> ByteString -> IO VerifyStatus
    forall key.
    PublicKey key =>
    Digest -> ByteString -> key -> ByteString -> IO VerifyStatus
    verifyLBS Digest
    md (String -> ByteString
    B8.pack String
    sig) key
    pkey (String -> ByteString
    L8.pack String
    input)

    -- |@'verifyBS'@ verifies a signature and a chunk of data.
    verifyBS :: PublicKey key =>
                Digest          -- ^ message digest algorithm to use
             -> B8.ByteString   -- ^ message signature
             -> key             -- ^ public key to verify the signature
             -> B8.ByteString   -- ^ input string to verify
             -> IO VerifyStatus -- ^ the result of verification
    verifyBS :: forall key.
    PublicKey key =>
    Digest -> ByteString -> key -> ByteString -> IO VerifyStatus
    verifyBS Digest
    md ByteString
    sig key
    pkey ByteString
    input
        = do ctx <- Digest -> ByteString -> IO DigestCtx
    digestStrictly Digest
    md ByteString
    input
             verifyFinalBS ctx sig pkey

    -- |@'verifyLBS'@ verifies a signature of a stream of data.
    verifyLBS :: PublicKey key =>
                 Digest          -- ^ message digest algorithm to use
              -> B8.ByteString   -- ^ message signature
              -> key             -- ^ public key to verify the signature
              -> L8.ByteString   -- ^ input string to verify
              -> IO VerifyStatus -- ^ the result of verification
    verifyLBS :: forall key.
    PublicKey key =>
    Digest -> ByteString -> key -> ByteString -> IO VerifyStatus
    verifyLBS Digest
    md ByteString
    sig key
    pkey ByteString
    input
        = do ctx <- Digest -> ByteString -> IO DigestCtx
    digestLazily Digest
    md ByteString
    input
             verifyFinalBS ctx sig pkey