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           Data.Typeable
import           Foreign
import           Foreign.C
import           OpenSSL.EVP.Digest
import           OpenSSL.EVP.PKey
import           OpenSSL.EVP.Internal
import           OpenSSL.Utils
data VerifyStatus = VerifySuccess
                  | VerifyFailure
                    deriving (Show, Eq, Typeable)
foreign import ccall unsafe "EVP_VerifyFinal"
        _VerifyFinal :: Ptr EVP_MD_CTX -> Ptr CChar -> CUInt -> Ptr EVP_PKEY -> IO CInt
verifyFinalBS :: PublicKey k => DigestCtx -> String -> k -> IO VerifyStatus
verifyFinalBS ctx sig k
    = withDigestCtxPtr ctx $ \ ctxPtr ->
      withCStringLen sig $ \ (buf, len) ->
      withPKeyPtr' k $ \ pkeyPtr ->
      _VerifyFinal ctxPtr buf (fromIntegral len) pkeyPtr >>= interpret
    where
      interpret :: CInt -> IO VerifyStatus
      interpret 1 = return VerifySuccess
      interpret 0 = return VerifyFailure
      interpret _ = raiseOpenSSLError
verify :: PublicKey key =>
          Digest          
       -> String          
       -> key             
       -> String          
       -> IO VerifyStatus 
verify md sig pkey input
    = verifyLBS md sig pkey (L8.pack input)
verifyBS :: PublicKey key =>
            Digest          
         -> String          
         -> key             
         -> B8.ByteString   
         -> IO VerifyStatus 
verifyBS md sig pkey input
    = do ctx <- digestStrictly md input
         verifyFinalBS ctx sig pkey
verifyLBS :: PublicKey key =>
             Digest          
          -> String          
          -> key             
          -> L8.ByteString   
          -> IO VerifyStatus 
verifyLBS md sig pkey input
    = do ctx <- digestLazily md input
         verifyFinalBS ctx sig pkey