{-# LINE 1 "src/Crypto/Skein/Internal.hsc" #-}
{-# CFILES
      c_impl/reference/skein.c
      c_impl/reference/skein_block.c #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Crypto.Skein.Internal
-- Copyright   :  (c) 2011 Felipe A. Lessa
-- License     :  BSD3 (see LICENSE)
--
-- Maintainer  :  felipe.lessa@gmail.com
-- Stability   :  provisional
-- Portability :  portable (needs FFI)
--
-- Basic wrappers around the C library.  You shouldn't need to
-- use these functions.  Instead, use the high-level
-- "Crypto.Skein" module.
--
-----------------------------------------------------------------------------

module Crypto.Skein.Internal
    ( -- * Return codes
      sKEIN_SUCCESS
    , sKEIN_FAIL
    , sKEIN_BAD_HASHLEN
    , check

      -- * Skein-256
    , Skein256Ctx(..)
    , skein256Init
    , skein256Update
    , skein256Final
    , skein256InitExt
    , skein256FinalPad
    , skein256Output

      -- * Skein-512
    , Skein512Ctx(..)
    , skein512Init
    , skein512Update
    , skein512Final
    , skein512InitExt
    , skein512FinalPad
    , skein512Output

      -- * Skein-1024
    , Skein1024Ctx(..)
    , skein1024Init
    , skein1024Update
    , skein1024Final
    , skein1024InitExt
    , skein1024FinalPad
    , skein1024Output

      -- * Misc constants
    , sKEIN_SEQUENTIAL
    ) where

-- from base
import Foreign
import Foreign.C

-- from bytestring
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as BI
import qualified Data.ByteString.Unsafe as BU

-- from this package


sKEIN_SUCCESS, sKEIN_FAIL, sKEIN_BAD_HASHLEN :: CInt
sKEIN_SUCCESS :: CInt
sKEIN_SUCCESS     = CInt
0
{-# LINE 73 "src/Crypto/Skein/Internal.hsc" #-}
sKEIN_FAIL        = 1
{-# LINE 74 "src/Crypto/Skein/Internal.hsc" #-}
sKEIN_BAD_HASHLEN = 2
{-# LINE 75 "src/Crypto/Skein/Internal.hsc" #-}

-- | Throws exception if the function does not return
-- successfully.
check :: IO CInt -> IO ()
check :: IO CInt -> IO ()
check IO CInt
act = do
  CInt
x <- IO CInt
act
  case () of
    () | CInt
x CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
sKEIN_SUCCESS     -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
       | CInt
x CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
sKEIN_FAIL        -> String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Skein returned FAIL."
       | CInt
x CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
sKEIN_BAD_HASHLEN -> String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Skein returned BAD_HASHLEN."
       | Bool
otherwise              -> String -> IO ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Skein returned unknown code."

newtype Skein256Ctx  = S256Ctx  {Skein256Ctx -> ByteString
unS256Ctx  :: B.ByteString}
newtype Skein512Ctx  = S512Ctx  {Skein512Ctx -> ByteString
unS512Ctx  :: B.ByteString}
newtype Skein1024Ctx = S1024Ctx {Skein1024Ctx -> ByteString
unS1024Ctx :: B.ByteString}

size256Ctx, size512Ctx, size1024Ctx :: Int
size256Ctx :: Int
size256Ctx  = (Int
96)
{-# LINE 93 "src/Crypto/Skein/Internal.hsc" #-}
size512Ctx  = (160)
{-# LINE 94 "src/Crypto/Skein/Internal.hsc" #-}
size1024Ctx = (288)
{-# LINE 95 "src/Crypto/Skein/Internal.hsc" #-}

instance Storable Skein256Ctx where
    sizeOf :: Skein256Ctx -> Int
sizeOf    Skein256Ctx
_ = Int
size256Ctx
    alignment :: Skein256Ctx -> Int
alignment Skein256Ctx
_ = Int
16
    peek :: Ptr Skein256Ctx -> IO Skein256Ctx
peek Ptr Skein256Ctx
ptr =
        (ByteString -> Skein256Ctx) -> IO ByteString -> IO Skein256Ctx
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Skein256Ctx
S256Ctx (IO ByteString -> IO Skein256Ctx)
-> IO ByteString -> IO Skein256Ctx
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr Word8 -> IO ()) -> IO ByteString
BI.create Int
size256Ctx ((Ptr Word8 -> IO ()) -> IO ByteString)
-> (Ptr Word8 -> IO ()) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
bptr ->
            Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BI.memcpy Ptr Word8
bptr (Ptr Skein256Ctx -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Skein256Ctx
ptr) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size256Ctx)
    poke :: Ptr Skein256Ctx -> Skein256Ctx -> IO ()
poke Ptr Skein256Ctx
ptr (S256Ctx ByteString
bs) =
        ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
BU.unsafeUseAsCString ByteString
bs ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
bs_ptr ->
            Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BI.memcpy (Ptr Skein256Ctx -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Skein256Ctx
ptr) (CString -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr CString
bs_ptr) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size256Ctx)

instance Storable Skein512Ctx where
    sizeOf :: Skein512Ctx -> Int
sizeOf    Skein512Ctx
_ = Int
size512Ctx
    alignment :: Skein512Ctx -> Int
alignment Skein512Ctx
_ = Int
16
    peek :: Ptr Skein512Ctx -> IO Skein512Ctx
peek Ptr Skein512Ctx
ptr =
        (ByteString -> Skein512Ctx) -> IO ByteString -> IO Skein512Ctx
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Skein512Ctx
S512Ctx (IO ByteString -> IO Skein512Ctx)
-> IO ByteString -> IO Skein512Ctx
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr Word8 -> IO ()) -> IO ByteString
BI.create Int
size512Ctx ((Ptr Word8 -> IO ()) -> IO ByteString)
-> (Ptr Word8 -> IO ()) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
bptr ->
            Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BI.memcpy Ptr Word8
bptr (Ptr Skein512Ctx -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Skein512Ctx
ptr) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size512Ctx)
    poke :: Ptr Skein512Ctx -> Skein512Ctx -> IO ()
poke Ptr Skein512Ctx
ptr (S512Ctx ByteString
bs) =
        ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
BU.unsafeUseAsCString ByteString
bs ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
bs_ptr ->
            Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BI.memcpy (Ptr Skein512Ctx -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Skein512Ctx
ptr) (CString -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr CString
bs_ptr) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size512Ctx)

instance Storable Skein1024Ctx where
    sizeOf :: Skein1024Ctx -> Int
sizeOf    Skein1024Ctx
_ = Int
size1024Ctx
    alignment :: Skein1024Ctx -> Int
alignment Skein1024Ctx
_ = Int
16
    peek :: Ptr Skein1024Ctx -> IO Skein1024Ctx
peek Ptr Skein1024Ctx
ptr =
        (ByteString -> Skein1024Ctx) -> IO ByteString -> IO Skein1024Ctx
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Skein1024Ctx
S1024Ctx (IO ByteString -> IO Skein1024Ctx)
-> IO ByteString -> IO Skein1024Ctx
forall a b. (a -> b) -> a -> b
$ Int -> (Ptr Word8 -> IO ()) -> IO ByteString
BI.create Int
size1024Ctx ((Ptr Word8 -> IO ()) -> IO ByteString)
-> (Ptr Word8 -> IO ()) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
bptr ->
            Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BI.memcpy Ptr Word8
bptr (Ptr Skein1024Ctx -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Skein1024Ctx
ptr) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size1024Ctx)
    poke :: Ptr Skein1024Ctx -> Skein1024Ctx -> IO ()
poke Ptr Skein1024Ctx
ptr (S1024Ctx ByteString
bs) =
        ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
BU.unsafeUseAsCString ByteString
bs ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
bs_ptr ->
            Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BI.memcpy (Ptr Skein1024Ctx -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr Skein1024Ctx
ptr) (CString -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr CString
bs_ptr) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
size1024Ctx)

foreign import ccall unsafe "skein.h Skein_256_Init" skein256Init  :: Ptr Skein256Ctx  -> CSize -> IO CInt
foreign import ccall unsafe "skein.h Skein_512_Init" skein512Init  :: Ptr Skein512Ctx  -> CSize -> IO CInt
foreign import ccall unsafe "skein.h Skein1024_Init" skein1024Init :: Ptr Skein1024Ctx -> CSize -> IO CInt

foreign import ccall unsafe "skein.h Skein_256_Update" skein256Update  :: Ptr Skein256Ctx  -> Ptr Word8 -> CSize -> IO CInt
foreign import ccall unsafe "skein.h Skein_512_Update" skein512Update  :: Ptr Skein512Ctx  -> Ptr Word8 -> CSize -> IO CInt
foreign import ccall unsafe "skein.h Skein1024_Update" skein1024Update :: Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt

foreign import ccall unsafe "skein.h Skein_256_Final" skein256Final  :: Ptr Skein256Ctx  -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "skein.h Skein_512_Final" skein512Final  :: Ptr Skein512Ctx  -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "skein.h Skein1024_Final" skein1024Final :: Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt

foreign import ccall unsafe "skein.h Skein_256_InitExt" skein256InitExt   :: Ptr Skein256Ctx  -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
foreign import ccall unsafe "skein.h Skein_512_InitExt" skein512InitExt   :: Ptr Skein512Ctx  -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
foreign import ccall unsafe "skein.h Skein1024_InitExt" skein1024InitExt  :: Ptr Skein1024Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt

foreign import ccall unsafe "skein.h Skein_256_Final_Pad" skein256FinalPad  :: Ptr Skein256Ctx  -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "skein.h Skein_512_Final_Pad" skein512FinalPad  :: Ptr Skein512Ctx  -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "skein.h Skein1024_Final_Pad" skein1024FinalPad :: Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt

foreign import ccall unsafe "skein.h Skein_256_Output" skein256Output  :: Ptr Skein256Ctx  -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "skein.h Skein_512_Output" skein512Output  :: Ptr Skein512Ctx  -> Ptr Word8 -> IO CInt
foreign import ccall unsafe "skein.h Skein1024_Output" skein1024Output :: Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt


-- | Pass to @InitExt@ to get sequential processing.
sKEIN_SEQUENTIAL :: Word64
sKEIN_SEQUENTIAL :: Word64
sKEIN_SEQUENTIAL = Word64
0