{-# LINE 1 "src/Crypto/Hash/GOST34112012.hsc" #-}
module Crypto.Hash.GOST34112012
( GOST34112012Context, hashGOST34112012, 
  hashGOST34112012_256, hashGOST34112012_512, getGOST34112012BufSize,
  initGOST34112012, updateGOST34112012, finishGOST34112012 ) where
import Foreign hiding (newForeignPtr)
import Foreign.Concurrent (newForeignPtr)
import Foreign.C (newCString, CString, CInt(..), CUInt(..), CSize(..))
import Data.ByteString (ByteString, useAsCStringLen, packCStringLen)



type GOST34112012Context = ForeignPtr GOST34112012Ctx

data GOST34112012Ctx = GOST34112012Ctx {
  GOST34112012Ctx -> CSize
cGOST34112012BufSize    :: CSize,
  GOST34112012Ctx -> CUInt
cGOST34112012DigestSize :: CUInt
}

instance Storable GOST34112012Ctx where
  sizeOf :: GOST34112012Ctx -> Int
sizeOf GOST34112012Ctx
_    = ((Int
336))
{-# LINE 21 "src/Crypto/Hash/GOST34112012.hsc" #-}
  alignment _ = (16)
{-# LINE 22 "src/Crypto/Hash/GOST34112012.hsc" #-}
  peek ptr    = GOST34112012Ctx
            <$> ((\hsc_ptr -> peekByteOff hsc_ptr 320)) ptr
{-# LINE 24 "src/Crypto/Hash/GOST34112012.hsc" #-}
            <*> ((\hsc_ptr -> peekByteOff hsc_ptr 328)) ptr
{-# LINE 25 "src/Crypto/Hash/GOST34112012.hsc" #-}
  poke _ _    = fail "GOST34112012Ctx is read only"

hashGOST34112012_256 :: ByteString -> IO ByteString
hashGOST34112012_256 :: ByteString -> IO ByteString
hashGOST34112012_256 = Int -> ByteString -> IO ByteString
hashGOST34112012 Int
256

hashGOST34112012_512 :: ByteString -> IO ByteString
hashGOST34112012_512 :: ByteString -> IO ByteString
hashGOST34112012_512 = Int -> ByteString -> IO ByteString
hashGOST34112012 Int
512

hashGOST34112012 :: Int -> ByteString -> IO ByteString
hashGOST34112012 :: Int -> ByteString -> IO ByteString
hashGOST34112012 Int
dsize ByteString
bytes = Int -> IO GOST34112012Context
initGOST34112012 Int
dsize
                   IO GOST34112012Context
-> (GOST34112012Context -> IO ByteString) -> IO ByteString
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \GOST34112012Context
ctx -> GOST34112012Context -> ByteString -> IO ()
updateGOST34112012 GOST34112012Context
ctx ByteString
bytes
                            IO () -> IO ByteString -> IO ByteString
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> GOST34112012Context -> IO ByteString
finishGOST34112012 GOST34112012Context
ctx

initGOST34112012 :: Int -> IO GOST34112012Context
initGOST34112012 :: Int -> IO GOST34112012Context
initGOST34112012 Int
dsize = IO (Ptr GOST34112012Ctx)
forall a. Storable a => IO (Ptr a)
malloc IO (Ptr GOST34112012Ctx)
-> (Ptr GOST34112012Ctx -> IO GOST34112012Context)
-> IO GOST34112012Context
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Ptr GOST34112012Ctx
ctx -> do
  Ptr GOST34112012Ctx -> CInt -> IO ()
cGOST34112012Init Ptr GOST34112012Ctx
ctx (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
dsize)
  Ptr GOST34112012Ctx -> IO () -> IO GOST34112012Context
forall a. Ptr a -> IO () -> IO (ForeignPtr a)
newForeignPtr Ptr GOST34112012Ctx
ctx (Ptr GOST34112012Ctx -> IO ()
cGOST34112012Cleanup Ptr GOST34112012Ctx
ctx IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr GOST34112012Ctx -> IO ()
forall a. Ptr a -> IO ()
free Ptr GOST34112012Ctx
ctx)

updateGOST34112012 :: GOST34112012Context -> ByteString -> IO ()
updateGOST34112012 :: GOST34112012Context -> ByteString -> IO ()
updateGOST34112012 GOST34112012Context
ctx ByteString
bytes = ByteString -> (CStringLen -> IO ()) -> IO ()
forall a. ByteString -> (CStringLen -> IO a) -> IO a
useAsCStringLen ByteString
bytes (\(Ptr CChar
str, Int
len) ->
  GOST34112012Context -> (Ptr GOST34112012Ctx -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr GOST34112012Context
ctx (\Ptr GOST34112012Ctx
ptr -> Ptr GOST34112012Ctx -> Ptr CChar -> CSize -> IO ()
cGOST34112012Update Ptr GOST34112012Ctx
ptr Ptr CChar
str (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)))

finishGOST34112012 :: GOST34112012Context -> IO ByteString
finishGOST34112012 :: GOST34112012Context -> IO ByteString
finishGOST34112012 GOST34112012Context
ctx = GOST34112012Context
-> (Ptr GOST34112012Ctx -> IO ByteString) -> IO ByteString
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr GOST34112012Context
ctx (\Ptr GOST34112012Ctx
ptr -> Ptr GOST34112012Ctx -> IO GOST34112012Ctx
forall a. Storable a => Ptr a -> IO a
peek Ptr GOST34112012Ctx
ptr IO GOST34112012Ctx
-> (GOST34112012Ctx -> IO ByteString) -> IO ByteString
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \GOST34112012Ctx
ct ->
  String -> IO (Ptr CChar)
newCString (Int -> Char -> String
forall a. Int -> a -> [a]
replicate (GOST34112012Ctx -> Int
forall {a}. Num a => GOST34112012Ctx -> a
hsize GOST34112012Ctx
ct) Char
' ') IO (Ptr CChar) -> (Ptr CChar -> IO ByteString) -> IO ByteString
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Ptr CChar
str -> Ptr GOST34112012Ctx -> Ptr CChar -> IO ()
cGOST34112012Final Ptr GOST34112012Ctx
ptr Ptr CChar
str
    IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ptr GOST34112012Ctx -> IO ()
cGOST34112012Cleanup Ptr GOST34112012Ctx
ptr IO () -> IO ByteString -> IO ByteString
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> CStringLen -> IO ByteString
packCStringLen (Ptr CChar
str, GOST34112012Ctx -> Int
forall {a}. Num a => GOST34112012Ctx -> a
hsize GOST34112012Ctx
ct)) where
      hsize :: GOST34112012Ctx -> a
hsize GOST34112012Ctx
ct = if CUInt
256 CUInt -> CUInt -> Bool
forall a. Eq a => a -> a -> Bool
== GOST34112012Ctx -> CUInt
cGOST34112012DigestSize GOST34112012Ctx
ct then a
32 else a
64

getGOST34112012BufSize :: GOST34112012Context -> IO Int
getGOST34112012BufSize :: GOST34112012Context -> IO Int
getGOST34112012BufSize = (GOST34112012Ctx -> Int) -> IO GOST34112012Ctx -> IO Int
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CSize -> Int)
-> (GOST34112012Ctx -> CSize) -> GOST34112012Ctx -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GOST34112012Ctx -> CSize
cGOST34112012BufSize)
                                (IO GOST34112012Ctx -> IO Int)
-> (GOST34112012Context -> IO GOST34112012Ctx)
-> GOST34112012Context
-> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((GOST34112012Context
 -> (Ptr GOST34112012Ctx -> IO GOST34112012Ctx)
 -> IO GOST34112012Ctx)
-> (Ptr GOST34112012Ctx -> IO GOST34112012Ctx)
-> GOST34112012Context
-> IO GOST34112012Ctx
forall a b c. (a -> b -> c) -> b -> a -> c
flip GOST34112012Context
-> (Ptr GOST34112012Ctx -> IO GOST34112012Ctx)
-> IO GOST34112012Ctx
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Ptr GOST34112012Ctx -> IO GOST34112012Ctx
forall a. Storable a => Ptr a -> IO a
peek)

foreign import ccall "GOST34112012Init"
  cGOST34112012Init :: Ptr GOST34112012Ctx -> CInt -> IO ()

foreign import ccall "GOST34112012Update"
  cGOST34112012Update :: Ptr GOST34112012Ctx -> CString -> CSize -> IO ()

foreign import ccall "GOST34112012Final"
  cGOST34112012Final :: Ptr GOST34112012Ctx -> CString -> IO ()

foreign import ccall "GOST34112012Cleanup"
  cGOST34112012Cleanup :: Ptr GOST34112012Ctx -> IO ()