module Codec.Digest.SHA.IO(
Length(..), SHACtx, newCtx, unsafeUpdateCtx, unsafeFinalizeCtx, showBSasHex
) where
import Foreign
import Foreign.C.Types
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as BI
import Control.Applicative
import Codec.Digest.SHA.Misc
data Length = SHA256 | SHA384 | SHA512
data SHACtx = Ctx256 (ForeignPtr Ctx256)
| Ctx384 (ForeignPtr Ctx384)
| Ctx512 (ForeignPtr Ctx512)
newCtx :: Length -> IO SHACtx
newCtx SHA256 = Ctx256 <$> initialize _sha256Init
newCtx SHA384 = Ctx384 <$> initialize _sha384Init
newCtx SHA512 = Ctx512 <$> initialize _sha512Init
initialize :: Storable a => (Ptr a -> IO ()) -> IO (ForeignPtr a)
initialize f = do
ctx <- mallocForeignPtr
withForeignPtr ctx f
return ctx
unsafeUpdateCtx :: SHACtx -> B.ByteString -> IO ()
unsafeUpdateCtx (Ctx256 p) = update _sha256Update p
unsafeUpdateCtx (Ctx384 p) = update _sha384Update p
unsafeUpdateCtx (Ctx512 p) = update _sha512Update p
update :: (Ptr a -> Ptr Word8 -> CSize -> IO ()) -> ForeignPtr a -> B.ByteString -> IO ()
update f ctx (BI.toForeignPtr -> (bs,offset,(fromIntegral -> len))) =
withForeignPtr ctx $ \ctxp ->
withForeignPtr bs $ \bsp ->
f ctxp (bsp `plusPtr` offset) len
unsafeFinalizeCtx :: SHACtx -> IO B.ByteString
unsafeFinalizeCtx (Ctx256 p) = finalize _sha256End p 32
unsafeFinalizeCtx (Ctx384 p) = finalize _sha384End p 48
unsafeFinalizeCtx (Ctx512 p) = finalize _sha512End p 64
finalize :: (Ptr a -> Ptr Word8 -> IO (Ptr Word8)) -> ForeignPtr a -> Int -> IO B.ByteString
finalize f ctx len =
withForeignPtr ctx $ \ctxp ->
BI.create len $ \bsp ->
f ctxp bsp >> return ()
data Ctx256
data Ctx384
data Ctx512
instance Storable Ctx256 where
sizeOf _ = (104)
alignment _ = 16
instance Storable Ctx384 where
sizeOf _ = (208)
alignment _ = 16
instance Storable Ctx512 where
sizeOf _ = (208)
alignment _ = 16
foreign import ccall unsafe "SHA256_Init" _sha256Init :: Ptr Ctx256 -> IO ()
foreign import ccall unsafe "SHA256_Update" _sha256Update :: Ptr Ctx256 -> Ptr Word8 -> CSize -> IO ()
foreign import ccall unsafe "SHA256_End" _sha256End :: Ptr Ctx256 -> Ptr Word8 -> IO (Ptr Word8)
foreign import ccall unsafe "SHA384_Init" _sha384Init :: Ptr Ctx384 -> IO ()
foreign import ccall unsafe "SHA384_Update" _sha384Update :: Ptr Ctx384 -> Ptr Word8 -> CSize -> IO ()
foreign import ccall unsafe "SHA384_End" _sha384End :: Ptr Ctx384 -> Ptr Word8 -> IO (Ptr Word8)
foreign import ccall unsafe "SHA512_Init" _sha512Init :: Ptr Ctx512 -> IO ()
foreign import ccall unsafe "SHA512_Update" _sha512Update :: Ptr Ctx512 -> Ptr Word8 -> CSize -> IO ()
foreign import ccall unsafe "SHA512_End" _sha512End :: Ptr Ctx512 -> Ptr Word8 -> IO (Ptr Word8)