hopenssl-2.2: src/OpenSSL/EVP/Digest/Digest.hs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE EmptyDataDecls #-}
{- |
Maintainer: simons@cryp.to
Stability: provisional
Portability: portable
Low-level bindings to OpenSSL's EVP interface. Most users do not need this
code. Check out "OpenSSL.Digest" for a more comfortable interface.
-}
module OpenSSL.EVP.Digest.Digest where
import OpenSSL.EVP.Digest.Algorithm
import OpenSSL.EVP.Digest.Context
import OpenSSL.EVP.Digest.Error ( throwIfZero )
import Foreign
import Foreign.C
-- | Configure the given digest context to use the given message digest
-- algorithm. Throws an exception to signal failure, i.e. because the system is
-- out of memory.
initDigest :: Algorithm -> Context -> IO ()
initDigest algo ctx =
throwIfZero "OpenSSL.EVP.Digest.initDigest" (_initDigest ctx algo nullPtr)
-- | Hash the given block of memory and update the digest state accordingly.
-- This function can be called many times. Then use 'finalizeDigest' to
-- retrieve the actual hash value.
updateDigest :: Context -> Ptr a -> CSize -> IO ()
updateDigest ctx ptr len =
throwIfZero "OpenSSL.EVP.Digest.updateDigest" (_updateDigest ctx ptr len)
-- | Finalize the digest calculation and return the result in the 'Word8' array
-- passed as an argument. Naturally, that array is expected to be large enough
-- to contain the digest. 'digestSize' or 'maxDigestSize' are your friends.
-- This function does /not/ clean up the digest context; this has to be done
-- with an explicit call to 'freeContext' (or 'resetContext', if you want to
-- re-use it). However, it does invalidate the digest state so that no further
-- calls of 'digestUpdate' can be made without re-initializing the context
-- first.
finalizeDigest :: Context -> Ptr Word8 -> IO ()
finalizeDigest ctx ptr =
throwIfZero "OpenSSL.EVP.Digest.finalizeDigest" (_finalizeDigest ctx ptr nullPtr)
-------------------------------------------------------------------------------
-- | We don't support choosing a custom engine to implement the given
-- algorithm. This type is just a place holder, and we always pass 'nullPtr'
-- whereever it is required to let OpenSSL choose whatever engine it thinks is
-- best.
data OpaqueEngine
foreign import ccall unsafe "openssl/evp.h EVP_DigestInit_ex"
_initDigest :: Context -> Algorithm -> Ptr OpaqueEngine -> IO CInt
foreign import ccall unsafe "openssl/evp.h EVP_DigestUpdate"
_updateDigest :: Context -> Ptr a -> CSize -> IO CInt
foreign import ccall unsafe "openssl/evp.h EVP_DigestFinal_ex"
_finalizeDigest :: Context -> Ptr Word8 -> Ptr CUInt -> IO CInt