From 09feb59f624847e04ac08e1d8ac50615bf749a47 Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Mon, 7 Jul 2014 14:55:55 +0100 Subject: [PATCH] merge cryptohash --- Crypto/Hash/Internal.hs | 24 + Crypto/Hash/MD2.hs | 136 +++++ Crypto/Hash/MD4.hs | 136 +++++ Crypto/Hash/MD5.hs | 136 +++++ Crypto/Hash/RIPEMD160.hs | 136 +++++ Crypto/Hash/SHA1.hs | 136 +++++ Crypto/Hash/SHA224.hs | 136 +++++ Crypto/Hash/SHA256.hs | 136 +++++ Crypto/Hash/SHA3.hs | 144 +++++ Crypto/Hash/SHA384.hs | 136 +++++ Crypto/Hash/SHA512.hs | 145 +++++ Crypto/Hash/SHA512t.hs | 52 ++ Crypto/Hash/Skein256.hs | 144 +++++ Crypto/Hash/Skein512.hs | 144 +++++ Crypto/Hash/Tiger.hs | 136 +++++ Crypto/Hash/Types.hs | 76 +++ Crypto/Hash/Utils.hs | 77 +++ Crypto/Hash/Whirlpool.hs | 136 +++++ cbits/cryptonite_md2.c | 135 +++++ cbits/cryptonite_md2.h | 44 ++ cbits/cryptonite_md4.c | 161 ++++++ cbits/cryptonite_md4.h | 43 ++ cbits/cryptonite_md5.c | 178 ++++++ cbits/cryptonite_md5.h | 43 ++ cbits/cryptonite_ripemd.c | 299 ++++++++++ cbits/cryptonite_ripemd.h | 43 ++ cbits/cryptonite_sha1.c | 209 +++++++ cbits/cryptonite_sha1.h | 43 ++ cbits/cryptonite_sha256.c | 175 ++++++ cbits/cryptonite_sha256.h | 53 ++ cbits/cryptonite_sha3.c | 159 ++++++ cbits/cryptonite_sha3.h | 45 ++ cbits/cryptonite_sha512.c | 245 ++++++++ cbits/cryptonite_sha512.h | 54 ++ cbits/cryptonite_skein.h | 46 ++ cbits/cryptonite_skein256.c | 196 +++++++ cbits/cryptonite_skein256.h | 45 ++ cbits/cryptonite_skein512.c | 214 +++++++ cbits/cryptonite_skein512.h | 45 ++ cbits/cryptonite_tiger.c | 415 ++++++++++++++ cbits/cryptonite_tiger.h | 43 ++ cbits/cryptonite_whirlpool.c | 1027 ++++++++++++++++++++++++++++++++++ cbits/cryptonite_whirlpool.h | 31 + cryptonite.cabal | 28 + tests/KATHash.hs | 221 ++++++++ tests/Tests.hs | 2 + 46 files changed, 6408 insertions(+) create mode 100644 Crypto/Hash/Internal.hs create mode 100644 Crypto/Hash/MD2.hs create mode 100644 Crypto/Hash/MD4.hs create mode 100644 Crypto/Hash/MD5.hs create mode 100644 Crypto/Hash/RIPEMD160.hs create mode 100644 Crypto/Hash/SHA1.hs create mode 100644 Crypto/Hash/SHA224.hs create mode 100644 Crypto/Hash/SHA256.hs create mode 100644 Crypto/Hash/SHA3.hs create mode 100644 Crypto/Hash/SHA384.hs create mode 100644 Crypto/Hash/SHA512.hs create mode 100644 Crypto/Hash/SHA512t.hs create mode 100644 Crypto/Hash/Skein256.hs create mode 100644 Crypto/Hash/Skein512.hs create mode 100644 Crypto/Hash/Tiger.hs create mode 100644 Crypto/Hash/Types.hs create mode 100644 Crypto/Hash/Utils.hs create mode 100644 Crypto/Hash/Whirlpool.hs create mode 100644 cbits/cryptonite_md2.c create mode 100644 cbits/cryptonite_md2.h create mode 100644 cbits/cryptonite_md4.c create mode 100644 cbits/cryptonite_md4.h create mode 100644 cbits/cryptonite_md5.c create mode 100644 cbits/cryptonite_md5.h create mode 100644 cbits/cryptonite_ripemd.c create mode 100644 cbits/cryptonite_ripemd.h create mode 100644 cbits/cryptonite_sha1.c create mode 100644 cbits/cryptonite_sha1.h create mode 100644 cbits/cryptonite_sha256.c create mode 100644 cbits/cryptonite_sha256.h create mode 100644 cbits/cryptonite_sha3.c create mode 100644 cbits/cryptonite_sha3.h create mode 100644 cbits/cryptonite_sha512.c create mode 100644 cbits/cryptonite_sha512.h create mode 100644 cbits/cryptonite_skein.h create mode 100644 cbits/cryptonite_skein256.c create mode 100644 cbits/cryptonite_skein256.h create mode 100644 cbits/cryptonite_skein512.c create mode 100644 cbits/cryptonite_skein512.h create mode 100644 cbits/cryptonite_tiger.c create mode 100644 cbits/cryptonite_tiger.h create mode 100644 cbits/cryptonite_whirlpool.c create mode 100644 cbits/cryptonite_whirlpool.h create mode 100644 tests/KATHash.hs diff --git a/Crypto/Hash/Internal.hs b/Crypto/Hash/Internal.hs new file mode 100644 index 0000000..9ba688a --- /dev/null +++ b/Crypto/Hash/Internal.hs @@ -0,0 +1,24 @@ +{-# LANGUAGE CPP #-} + +-- | +-- Module : Crypto.Hash.Internal +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +module Crypto.Hash.Internal where + +import System.IO.Unsafe + +-- | perform io for hashes that do allocation and ffi. +-- unsafeDupablePerformIO is used when possible as the +-- computation is pure and the output is directly linked +-- to the input. we also do not modify anything after it has +-- been returned to the user. +unsafeDoIO :: IO a -> a +#if __GLASGOW_HASKELL__ > 704 +unsafeDoIO = unsafeDupablePerformIO +#else +unsafeDoIO = unsafePerformIO +#endif + diff --git a/Crypto/Hash/MD2.hs b/Crypto/Hash/MD2.hs new file mode 100644 index 0000000..a03aa62 --- /dev/null +++ b/Crypto/Hash/MD2.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.MD2 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- MD2 cryptographic hash. +-- +module Crypto.Hash.MD2 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | MD2 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 16 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 96 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(12-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_md2.h cryptonite_md2_init" + c_md2_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_md2.h cryptonite_md2_update" + c_md2_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_md2.h cryptonite_md2_finalize" + c_md2_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_md2_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_md2_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_md2_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_md2_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_md2_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/MD4.hs b/Crypto/Hash/MD4.hs new file mode 100644 index 0000000..6e23785 --- /dev/null +++ b/Crypto/Hash/MD4.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.MD4 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- MD4 cryptographic hash. +-- +module Crypto.Hash.MD4 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | MD4 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 16 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 96 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(12-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_md4.h cryptonite_md4_init" + c_md4_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_md4.h cryptonite_md4_update" + c_md4_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_md4.h cryptonite_md4_finalize" + c_md4_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_md4_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_md4_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_md4_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_md4_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_md4_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/MD5.hs b/Crypto/Hash/MD5.hs new file mode 100644 index 0000000..950c4a1 --- /dev/null +++ b/Crypto/Hash/MD5.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.MD5 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- MD5 cryptographic hash. +-- +module Crypto.Hash.MD5 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | MD5 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 16 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 96 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(12-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_md5.h cryptonite_md5_init" + c_md5_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_md5.h cryptonite_md5_update" + c_md5_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_md5.h cryptonite_md5_finalize" + c_md5_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_md5_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_md5_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_md5_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_md5_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_md5_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/RIPEMD160.hs b/Crypto/Hash/RIPEMD160.hs new file mode 100644 index 0000000..e34059d --- /dev/null +++ b/Crypto/Hash/RIPEMD160.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.RIPEMD160 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- RIPEMD160 cryptographic hash. +-- +module Crypto.Hash.RIPEMD160 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | RIPEMD160 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 20 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 128 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(16-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_ripemd.h cryptonite_ripemd160_init" + c_ripemd160_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_ripemd.h cryptonite_ripemd160_update" + c_ripemd160_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_ripemd.h cryptonite_ripemd160_finalize" + c_ripemd160_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_ripemd160_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_ripemd160_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_ripemd160_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_ripemd160_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_ripemd160_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA1.hs b/Crypto/Hash/SHA1.hs new file mode 100644 index 0000000..00d7045 --- /dev/null +++ b/Crypto/Hash/SHA1.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.SHA1 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- SHA1 cryptographic hash. +-- +module Crypto.Hash.SHA1 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | SHA1 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 20 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 96 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(12-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_sha1.h cryptonite_sha1_init" + c_sha1_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_sha1.h cryptonite_sha1_update" + c_sha1_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_sha1.h cryptonite_sha1_finalize" + c_sha1_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_sha1_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_sha1_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_sha1_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha1_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha1_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA224.hs b/Crypto/Hash/SHA224.hs new file mode 100644 index 0000000..7b59815 --- /dev/null +++ b/Crypto/Hash/SHA224.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.SHA224 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- SHA224 cryptographic hash. +-- +module Crypto.Hash.SHA224 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | SHA224 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 28 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 192 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(24-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_sha256.h cryptonite_sha224_init" + c_sha224_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_sha256.h cryptonite_sha224_update" + c_sha224_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_sha256.h cryptonite_sha224_finalize" + c_sha224_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_sha224_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_sha224_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_sha224_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha224_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha224_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA256.hs b/Crypto/Hash/SHA256.hs new file mode 100644 index 0000000..e7f40c9 --- /dev/null +++ b/Crypto/Hash/SHA256.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.SHA256 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- SHA256 cryptographic hash. +-- +module Crypto.Hash.SHA256 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | SHA256 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 32 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 192 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(24-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_sha256.h cryptonite_sha256_init" + c_sha256_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_sha256.h cryptonite_sha256_update" + c_sha256_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_sha256.h cryptonite_sha256_finalize" + c_sha256_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_sha256_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_sha256_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_sha256_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha256_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha256_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA3.hs b/Crypto/Hash/SHA3.hs new file mode 100644 index 0000000..49e99cc --- /dev/null +++ b/Crypto/Hash/SHA3.hs @@ -0,0 +1,144 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.SHA3 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- SHA3 cryptographic hash. +-- +module Crypto.Hash.SHA3 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Int -> Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: Int -> ByteString -> ByteString + , hashlazy -- :: Int -> ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | SHA3 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 360 + +{- return the number of bytes of output for the digest -} +peekHashlen :: Ptr Ctx -> IO Int +peekHashlen ptr = peek iptr >>= \v -> return $! fromIntegral v + where iptr :: Ptr Word32 + iptr = castPtr ptr + +{-# RULES "hash" forall b i. finalize (update (init i) b) = hash i b #-} +{-# RULES "hash.list1" forall b i. finalize (updates (init i) [b]) = hash i b #-} +{-# RULES "hashmany" forall b i. finalize (foldl update (init i) b) = hashlazy i (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b i. finalize (foldl update (init i) $ L.toChunks b) = hashlazy i b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(45-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_sha3.h cryptonite_sha3_init" + c_sha3_init :: Ptr Ctx -> Word32 -> IO () + +foreign import ccall "cryptonite_sha3.h cryptonite_sha3_update" + c_sha3_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_sha3.h cryptonite_sha3_finalize" + c_sha3_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_sha3_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = + peekHashlen ptr >>= \digestSize -> create digestSize (c_sha3_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context where +init :: Int -- ^ algorithm hash size in bits + -> Ctx +init hashlen = unsafeDoIO $ withCtxNew $ \ptr -> c_sha3_init ptr (fromIntegral hashlen) + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: Int -- ^ algorithm hash size in bits + -> ByteString -- ^ the data to hash + -> ByteString -- ^ the digest output +hash hashlen d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha3_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: Int -- ^ algorithm hash size in bits + -> L.ByteString -- ^ the data to hash as a lazy bytestring + -> ByteString -- ^ the digest output +hashlazy hashlen l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha3_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA384.hs b/Crypto/Hash/SHA384.hs new file mode 100644 index 0000000..c5cedf2 --- /dev/null +++ b/Crypto/Hash/SHA384.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.SHA384 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- SHA384 cryptographic hash. +-- +module Crypto.Hash.SHA384 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | SHA384 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 48 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 256 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(32-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_sha512.h cryptonite_sha384_init" + c_sha384_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_sha512.h cryptonite_sha384_update" + c_sha384_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_sha512.h cryptonite_sha384_finalize" + c_sha384_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_sha384_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_sha384_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_sha384_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha384_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha384_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA512.hs b/Crypto/Hash/SHA512.hs new file mode 100644 index 0000000..de2eec7 --- /dev/null +++ b/Crypto/Hash/SHA512.hs @@ -0,0 +1,145 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.SHA512 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- SHA512 cryptographic hash. +-- +module Crypto.Hash.SHA512 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , init_t -- :: Int -> Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | SHA512 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 64 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 256 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(32-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_sha512.h cryptonite_sha512_init" + c_sha512_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_sha512.h cryptonite_sha512_update" + c_sha512_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_sha512.h cryptonite_sha512_finalize" + c_sha512_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +foreign import ccall unsafe "cryptonite_sha512.h cryptonite_sha512_init_t" + c_sha512_init_t :: Ptr Ctx -> Int -> IO () + +{-# NOINLINE init_t #-} +-- | init a context using FIPS 180-4 for truncated SHA512 +init_t :: Int -> Ctx +init_t t = unsafeDoIO $ withCtxNew $ \ptr -> c_sha512_init_t ptr t + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_sha512_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_sha512_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_sha512_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha512_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_sha512_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/SHA512t.hs b/Crypto/Hash/SHA512t.hs new file mode 100644 index 0000000..401532c --- /dev/null +++ b/Crypto/Hash/SHA512t.hs @@ -0,0 +1,52 @@ +-- | +-- Module : Crypto.Hash.SHA512t +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- A module containing SHA512/t +-- +module Crypto.Hash.SHA512t + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Data.List (foldl') +import Data.ByteString (ByteString) +import qualified Data.ByteString as B +import qualified Data.ByteString.Lazy as L + +import qualified Crypto.Hash.SHA512 as SHA512 + +-- | SHA512 Context with variable size output +data Ctx = Ctx !Int !SHA512.Ctx + +-- | init a context +init :: Int -> Ctx +init t = Ctx t (SHA512.init_t t) + +-- | update a context with a bytestring +update :: Ctx -> ByteString -> Ctx +update (Ctx t ctx) d = Ctx t (SHA512.update ctx d) + +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize (Ctx sz ctx) = B.take (sz `div` 8) (SHA512.finalize ctx) + +-- | hash a strict bytestring into a digest bytestring +hash :: Int -> ByteString -> ByteString +hash t = finalize . update (init t) + +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: Int -> L.ByteString -> ByteString +hashlazy t = finalize . foldl' update (init t) . L.toChunks diff --git a/Crypto/Hash/Skein256.hs b/Crypto/Hash/Skein256.hs new file mode 100644 index 0000000..58a7339 --- /dev/null +++ b/Crypto/Hash/Skein256.hs @@ -0,0 +1,144 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.Skein256 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- Skein256 cryptographic hash. +-- +module Crypto.Hash.Skein256 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Int -> Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: Int -> ByteString -> ByteString + , hashlazy -- :: Int -> ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | Skein256 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 96 + +{- return the number of bytes of output for the digest -} +peekHashlen :: Ptr Ctx -> IO Int +peekHashlen ptr = peek iptr >>= \v -> return $! fromIntegral v + where iptr :: Ptr Word32 + iptr = castPtr ptr + +{-# RULES "hash" forall b i. finalize (update (init i) b) = hash i b #-} +{-# RULES "hash.list1" forall b i. finalize (updates (init i) [b]) = hash i b #-} +{-# RULES "hashmany" forall b i. finalize (foldl update (init i) b) = hashlazy i (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b i. finalize (foldl update (init i) $ L.toChunks b) = hashlazy i b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(12-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_skein256.h cryptonite_skein256_init" + c_skein256_init :: Ptr Ctx -> Word32 -> IO () + +foreign import ccall "cryptonite_skein256.h cryptonite_skein256_update" + c_skein256_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_skein256.h cryptonite_skein256_finalize" + c_skein256_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_skein256_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = + peekHashlen ptr >>= \digestSize -> create digestSize (c_skein256_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context where +init :: Int -- ^ algorithm hash size in bits + -> Ctx +init hashlen = unsafeDoIO $ withCtxNew $ \ptr -> c_skein256_init ptr (fromIntegral hashlen) + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: Int -- ^ algorithm hash size in bits + -> ByteString -- ^ the data to hash + -> ByteString -- ^ the digest output +hash hashlen d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_skein256_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: Int -- ^ algorithm hash size in bits + -> L.ByteString -- ^ the data to hash as a lazy bytestring + -> ByteString -- ^ the digest output +hashlazy hashlen l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_skein256_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/Skein512.hs b/Crypto/Hash/Skein512.hs new file mode 100644 index 0000000..b0437b3 --- /dev/null +++ b/Crypto/Hash/Skein512.hs @@ -0,0 +1,144 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.Skein512 +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- Skein512 cryptographic hash. +-- +module Crypto.Hash.Skein512 + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Int -> Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: Int -> ByteString -> ByteString + , hashlazy -- :: Int -> ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | Skein512 Context. +newtype Ctx = Ctx ByteString + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 160 + +{- return the number of bytes of output for the digest -} +peekHashlen :: Ptr Ctx -> IO Int +peekHashlen ptr = peek iptr >>= \v -> return $! fromIntegral v + where iptr :: Ptr Word32 + iptr = castPtr ptr + +{-# RULES "hash" forall b i. finalize (update (init i) b) = hash i b #-} +{-# RULES "hash.list1" forall b i. finalize (updates (init i) [b]) = hash i b #-} +{-# RULES "hashmany" forall b i. finalize (foldl update (init i) b) = hashlazy i (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b i. finalize (foldl update (init i) $ L.toChunks b) = hashlazy i b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(20-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_skein512.h cryptonite_skein512_init" + c_skein512_init :: Ptr Ctx -> Word32 -> IO () + +foreign import ccall "cryptonite_skein512.h cryptonite_skein512_update" + c_skein512_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_skein512.h cryptonite_skein512_finalize" + c_skein512_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_skein512_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = + peekHashlen ptr >>= \digestSize -> create digestSize (c_skein512_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context where +init :: Int -- ^ algorithm hash size in bits + -> Ctx +init hashlen = unsafeDoIO $ withCtxNew $ \ptr -> c_skein512_init ptr (fromIntegral hashlen) + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: Int -- ^ algorithm hash size in bits + -> ByteString -- ^ the data to hash + -> ByteString -- ^ the digest output +hash hashlen d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_skein512_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: Int -- ^ algorithm hash size in bits + -> L.ByteString -- ^ the data to hash as a lazy bytestring + -> ByteString -- ^ the digest output +hashlazy hashlen l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_skein512_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/Tiger.hs b/Crypto/Hash/Tiger.hs new file mode 100644 index 0000000..6de6228 --- /dev/null +++ b/Crypto/Hash/Tiger.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.Tiger +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- Tiger cryptographic hash. +-- +module Crypto.Hash.Tiger + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | Tiger Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 24 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 96 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(12-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_tiger.h cryptonite_tiger_init" + c_tiger_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_tiger.h cryptonite_tiger_update" + c_tiger_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_tiger.h cryptonite_tiger_finalize" + c_tiger_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_tiger_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_tiger_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_tiger_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_tiger_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_tiger_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/Crypto/Hash/Types.hs b/Crypto/Hash/Types.hs new file mode 100644 index 0000000..193637c --- /dev/null +++ b/Crypto/Hash/Types.hs @@ -0,0 +1,76 @@ +-- | +-- Module : Crypto.Hash.Types +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- Crypto hash types definitions +-- +module Crypto.Hash.Types + ( HashAlgorithm(..) + , Context(..) + , Digest(..) + -- * deprecated + , contextToByteString + , digestToByteString + ) + where + +import Data.ByteString (ByteString) +import Data.Byteable +import qualified Data.ByteString.Char8 as BC +import Crypto.Hash.Utils (toHex) + +-- | Class representing hashing algorithms. +-- +-- The hash algorithm is built over 3 primitives: +-- +-- * init : create a new hashing context +-- +-- * updates : update the hashing context with some strict bytestrings +-- and return the new context +-- +-- * finalize : finalize the context into a digest +-- +class HashAlgorithm a where + -- | Block size in bytes the hash algorithm operates on + hashBlockSize :: Context a -> Int + + -- | Initialize a new context for this hash algorithm + hashInit :: Context a + + -- | Update the context with a list of strict bytestring, + -- and return a new context with the updates. + hashUpdates :: Context a -> [ByteString] -> Context a + + -- | Finalize a context and return a digest. + hashFinalize :: Context a -> Digest a + + -- | Try to convert a binary digest bytestring to a digest. + digestFromByteString :: ByteString -> Maybe (Digest a) + +-- | Represent a context for a given hash algorithm. +newtype Context a = Context ByteString + +instance Byteable (Context a) where + toBytes (Context bs) = bs + +-- | return the binary bytestring. deprecated use toBytes. +contextToByteString :: Context a -> ByteString +contextToByteString = toBytes + +-- | Represent a digest for a given hash algorithm. +newtype Digest a = Digest ByteString + deriving (Eq,Ord) + +instance Byteable (Digest a) where + toBytes (Digest bs) = bs + +-- | return the binary bytestring. deprecated use toBytes. +{-# DEPRECATED digestToByteString "use toBytes from byteable:Data.Byteable" #-} +digestToByteString :: Digest a -> ByteString +digestToByteString = toBytes + +instance Show (Digest a) where + show (Digest bs) = BC.unpack $ toHex bs diff --git a/Crypto/Hash/Utils.hs b/Crypto/Hash/Utils.hs new file mode 100644 index 0000000..3c66553 --- /dev/null +++ b/Crypto/Hash/Utils.hs @@ -0,0 +1,77 @@ +{-# LANGUAGE MagicHash, BangPatterns #-} +-- | +-- Module : Crypto.Hash.Utils +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- Crypto hash utility for hexadecimal +-- +module Crypto.Hash.Utils + ( toHex + ) where + +import Data.ByteString (ByteString) +import qualified Data.ByteString.Internal as B +import GHC.Prim +import GHC.Types +import GHC.Word +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Ptr (plusPtr, castPtr) +import Foreign.Storable (poke, peek) +import Crypto.Hash.Utils.Cpu +import Data.Bits (testBit) + +-- | Convert a bytestring to the hexadecimal equivalent +-- using 0123456789abcdef as digit +toHex :: ByteString -> ByteString +toHex (B.PS fp off len) = B.unsafeCreate (len*2) $ \d -> + withForeignPtr fp $ \s -> start d (s `plusPtr` off) + where start db sb + | use32Hex && (len `testBit` 0) == False = loop32 db sb + | otherwise = loop8 db sb + where end = sb `plusPtr` len + -- write the hex output using 32 bits write. + loop32 d s + | s == end = return () + | otherwise = do b1 <- fromIntegral `fmap` (peek s :: IO Word8) + b2 <- fromIntegral `fmap` (peek (s `plusPtr` 1) :: IO Word8) + poke (castPtr d) (to32 b1 b2) + loop32 (d `plusPtr` 4) (s `plusPtr` 2) + -- write the hex output 8 bits, 2 at a time + loop8 d s + | s == end = return () + | otherwise = do b <- fromIntegral `fmap` (peek s :: IO Word8) + poke d (r tableHi b) + poke (d `plusPtr` 1) (r tableLo b) + loop8 (d `plusPtr` 2) (s `plusPtr` 1) + + -- little endian version + to32 (I# i1) (I# i2) = W32# (or# (or# (or# hi2 lo2) hi1) lo1) + where hi2 = uncheckedShiftL# (indexWord8OffAddr# tableLo i2) 24# + lo2 = uncheckedShiftL# (indexWord8OffAddr# tableHi i2) 16# + hi1 = uncheckedShiftL# (indexWord8OffAddr# tableLo i1) 8# + lo1 = indexWord8OffAddr# tableHi i1 + + r :: Addr# -> Int -> Word8 + r table (I# index) = W8# (indexWord8OffAddr# table index) + + !tableLo = + "0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef\ + \0123456789abcdef0123456789abcdef"# + !tableHi = + "00000000000000001111111111111111\ + \22222222222222223333333333333333\ + \44444444444444445555555555555555\ + \66666666666666667777777777777777\ + \88888888888888889999999999999999\ + \aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb\ + \ccccccccccccccccdddddddddddddddd\ + \eeeeeeeeeeeeeeeeffffffffffffffff"# diff --git a/Crypto/Hash/Whirlpool.hs b/Crypto/Hash/Whirlpool.hs new file mode 100644 index 0000000..704f6e8 --- /dev/null +++ b/Crypto/Hash/Whirlpool.hs @@ -0,0 +1,136 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +-- | +-- Module : Crypto.Hash.Whirlpool +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- module containing the basic functions to work with the +-- Whirlpool cryptographic hash. +-- +module Crypto.Hash.Whirlpool + ( Ctx(..) + + -- * Incremental hashing Functions + , init -- :: Ctx + , update -- :: Ctx -> ByteString -> Ctx + , updates -- :: Ctx -> [ByteString] -> Ctx + , finalize -- :: Ctx -> ByteString + + -- * Single Pass hashing + , hash -- :: ByteString -> ByteString + , hashlazy -- :: ByteString -> ByteString + ) where + +import Prelude hiding (init) +import Foreign.Ptr +import Foreign.ForeignPtr (withForeignPtr) +import Foreign.Storable +import Foreign.Marshal.Alloc +import qualified Data.ByteString.Lazy as L +import Data.ByteString (ByteString) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) +import Data.ByteString.Internal (create, toForeignPtr) +import Data.Word +import Crypto.Hash.Internal (unsafeDoIO) + +-- | Whirlpool Context. +newtype Ctx = Ctx ByteString + +{-# INLINE digestSize #-} +digestSize :: Int +digestSize = 64 + +{-# INLINE sizeCtx #-} +sizeCtx :: Int +sizeCtx = 168 + +{-# RULES "hash" forall b. finalize (update init b) = hash b #-} +{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-} +{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-} +{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-} + +{-# INLINE withByteStringPtr #-} +withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a +withByteStringPtr b f = + withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off) + where (fptr, off, _) = toForeignPtr b + +{-# INLINE memcopy64 #-} +memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO () +memcopy64 dst src = mapM_ peekAndPoke [0..(21-1)] + where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i + +withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx +withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx + where createCtx = create sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a +withCtxThrow (Ctx ctxB) f = + allocaBytes sizeCtx $ \dstPtr -> + withByteStringPtr ctxB $ \srcPtr -> do + memcopy64 (castPtr dstPtr) (castPtr srcPtr) + f (castPtr dstPtr) + +withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx +withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr) + +withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a +withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr) + +foreign import ccall unsafe "cryptonite_whirlpool.h cryptonite_whirlpool_init" + c_whirlpool_init :: Ptr Ctx -> IO () + +foreign import ccall "cryptonite_whirlpool.h cryptonite_whirlpool_update" + c_whirlpool_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO () + +foreign import ccall unsafe "cryptonite_whirlpool.h cryptonite_whirlpool_finalize" + c_whirlpool_finalize :: Ptr Ctx -> Ptr Word8 -> IO () + +updateInternalIO :: Ptr Ctx -> ByteString -> IO () +updateInternalIO ptr d = + unsafeUseAsCStringLen d (\(cs, len) -> c_whirlpool_update ptr (castPtr cs) (fromIntegral len)) + +finalizeInternalIO :: Ptr Ctx -> IO ByteString +finalizeInternalIO ptr = create digestSize (c_whirlpool_finalize ptr) + +{-# NOINLINE init #-} +-- | init a context +init :: Ctx +init = unsafeDoIO $ withCtxNew $ c_whirlpool_init + +{-# NOINLINE update #-} +-- | update a context with a bytestring returning the new updated context +update :: Ctx -- ^ the context to update + -> ByteString -- ^ the data to update with + -> Ctx -- ^ the updated context +update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d + +{-# NOINLINE updates #-} +-- | updates a context with multiples bytestring returning the new updated context +updates :: Ctx -- ^ the context to update + -> [ByteString] -- ^ a list of data bytestring to update with + -> Ctx -- ^ the updated context +updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d + +{-# NOINLINE finalize #-} +-- | finalize the context into a digest bytestring +finalize :: Ctx -> ByteString +finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO + +{-# NOINLINE hash #-} +-- | hash a strict bytestring into a digest bytestring +hash :: ByteString -> ByteString +hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_whirlpool_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr + +{-# NOINLINE hashlazy #-} +-- | hash a lazy bytestring into a digest bytestring +hashlazy :: L.ByteString -> ByteString +hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do + c_whirlpool_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr diff --git a/cbits/cryptonite_md2.c b/cbits/cryptonite_md2.c new file mode 100644 index 0000000..fd4bf8b --- /dev/null +++ b/cbits/cryptonite_md2.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2006-2010 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "cryptonite_bitfn.h" +#include "cryptonite_md2.h" + +void cryptonite_md2_init(struct md2_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->sz = 0ULL; +} + +static uint8_t S_table[] = { + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, + 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, + 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, + 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, + 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, + 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, + 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, + 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, + 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, + 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, + 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, + 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, + 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +static uint8_t *padding_table[] = { + "", + "\x1", + "\x2\x2", + "\x3\x3\x3", + "\x4\x4\x4\x4", + "\x5\x5\x5\x5\x5", + "\x6\x6\x6\x6\x6\x6", + "\x7\x7\x7\x7\x7\x7\x7", + "\x8\x8\x8\x8\x8\x8\x8\x8", + "\x9\x9\x9\x9\x9\x9\x9\x9\x9", + "\xa\xa\xa\xa\xa\xa\xa\xa\xa\xa", + "\xb\xb\xb\xb\xb\xb\xb\xb\xb\xb\xb", + "\xc\xc\xc\xc\xc\xc\xc\xc\xc\xc\xc\xc", + "\xd\xd\xd\xd\xd\xd\xd\xd\xd\xd\xd\xd\xd", + "\xe\xe\xe\xe\xe\xe\xe\xe\xe\xe\xe\xe\xe\xe", + "\xf\xf\xf\xf\xf\xf\xf\xf\xf\xf\xf\xf\xf\xf\xf", + "\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10" +}; + +static void md2_do_chunk(struct md2_ctx *ctx, uint8_t *buf) +{ + uint8_t i, j, t; + uint8_t x[48]; + + memcpy(x, ctx->h, 16); + memcpy(x+16, buf, 16); + + for (i = 0; i < 16; i++) + x[i+32] = ctx->h[i] ^ buf[i]; + + for (t = i = 0; i < 18; i++) { + for (j = 0; j < 48; j++) + t = x[j] ^= S_table[t]; + t = (t + i) & 0xff; + } + + memcpy(ctx->h, x, 16); + + t = ctx->cksum[15]; + for (i = 0; i < 16; i++) + t = ctx->cksum[i] ^= S_table[buf[i] ^ t]; +} + +void cryptonite_md2_update(struct md2_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + index = (uint32_t) (ctx->sz & 0xf); + to_fill = 16 - index; + + ctx->sz += len; + + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + md2_do_chunk(ctx, ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 16-block as possible */ + for (; len >= 16; len -= 16, data += 16) + md2_do_chunk(ctx, data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_md2_finalize(struct md2_ctx *ctx, uint8_t *out) +{ + uint32_t index, padlen; + + index = ctx->sz & 0xf; + padlen = 16 - index; + + cryptonite_md2_update(ctx, padding_table[padlen], padlen); + cryptonite_md2_update(ctx, ctx->cksum, 16); + memcpy(out, ctx->h, 16); +} diff --git a/cbits/cryptonite_md2.h b/cbits/cryptonite_md2.h new file mode 100644 index 0000000..37f19ce --- /dev/null +++ b/cbits/cryptonite_md2.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_MD2_H +#define CRYPTOHASH_MD2_H + +#include + +struct md2_ctx +{ + uint64_t sz; + uint8_t buf[16]; + uint8_t h[16]; + uint8_t cksum[16]; +}; + +#define MD2_DIGEST_SIZE 16 +#define MD2_CTX_SIZE sizeof(struct md2_ctx) + +void cryptonite_md2_init(struct md2_ctx *ctx); +void cryptonite_md2_update(struct md2_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_md2_finalize(struct md2_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_md4.c b/cbits/cryptonite_md4.c new file mode 100644 index 0000000..14d4387 --- /dev/null +++ b/cbits/cryptonite_md4.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "cryptonite_bitfn.h" +#include "cryptonite_md4.h" + +void cryptonite_md4_init(struct md4_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->sz = 0ULL; + ctx->h[0] = 0x67452301; + ctx->h[1] = 0xefcdab89; + ctx->h[2] = 0x98badcfe; + ctx->h[3] = 0x10325476; +} + +#define f1(x, y, z) ((x & y) | ((~x) & z)) +#define f2(x, y, z) ((x & y) | (x & z) | (y & z)) +#define f3(x, y, z) (x ^ y ^ z) + +#define K1 0x00000000 +#define K2 0x5A827999 +#define K3 0x6ED9EBA1 +#define R(a,b,c,d,f,k,s,i) (a = rol32(a + f(b,c,d) + w[i] + k, s)) + +static void md4_do_chunk(struct md4_ctx *ctx, uint32_t *buf) +{ + uint32_t a, b, c, d; +#ifdef ARCH_IS_BIG_ENDIAN + uint32_t w[16]; + cpu_to_le32_array(w, (uint32_t *) buf, 16); +#else + uint32_t *w = buf; +#endif + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + + R(a, b, c, d, f1, K1, 3, 0); + R(d, a, b, c, f1, K1, 7, 1); + R(c, d, a, b, f1, K1, 11, 2); + R(b, c, d, a, f1, K1, 19, 3); + R(a, b, c, d, f1, K1, 3, 4); + R(d, a, b, c, f1, K1, 7, 5); + R(c, d, a, b, f1, K1, 11, 6); + R(b, c, d, a, f1, K1, 19, 7); + R(a, b, c, d, f1, K1, 3, 8); + R(d, a, b, c, f1, K1, 7, 9); + R(c, d, a, b, f1, K1, 11, 10); + R(b, c, d, a, f1, K1, 19, 11); + R(a, b, c, d, f1, K1, 3, 12); + R(d, a, b, c, f1, K1, 7, 13); + R(c, d, a, b, f1, K1, 11, 14); + R(b, c, d, a, f1, K1, 19, 15); + + R(a, b, c, d, f2, K2, 3, 0); + R(d, a, b, c, f2, K2, 5, 4); + R(c, d, a, b, f2, K2, 9, 8); + R(b, c, d, a, f2, K2, 13, 12); + R(a, b, c, d, f2, K2, 3, 1); + R(d, a, b, c, f2, K2, 5, 5); + R(c, d, a, b, f2, K2, 9, 9); + R(b, c, d, a, f2, K2, 13, 13); + R(a, b, c, d, f2, K2, 3, 2); + R(d, a, b, c, f2, K2, 5, 6); + R(c, d, a, b, f2, K2, 9, 10); + R(b, c, d, a, f2, K2, 13, 14); + R(a, b, c, d, f2, K2, 3, 3); + R(d, a, b, c, f2, K2, 5, 7); + R(c, d, a, b, f2, K2, 9, 11); + R(b, c, d, a, f2, K2, 13, 15); + + R(a, b, c, d, f3, K3, 3, 0); + R(d, a, b, c, f3, K3, 9, 8); + R(c, d, a, b, f3, K3, 11, 4); + R(b, c, d, a, f3, K3, 15, 12); + R(a, b, c, d, f3, K3, 3, 2); + R(d, a, b, c, f3, K3, 9, 10); + R(c, d, a, b, f3, K3, 11, 6); + R(b, c, d, a, f3, K3, 15, 14); + R(a, b, c, d, f3, K3, 3, 1); + R(d, a, b, c, f3, K3, 9, 9); + R(c, d, a, b, f3, K3, 11, 5); + R(b, c, d, a, f3, K3, 15, 13); + R(a, b, c, d, f3, K3, 3, 3); + R(d, a, b, c, f3, K3, 9, 11); + R(c, d, a, b, f3, K3, 11, 7); + R(b, c, d, a, f3, K3, 15, 15); + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; +} + +void cryptonite_md4_update(struct md4_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + index = (uint32_t) (ctx->sz & 0x3f); + to_fill = 64 - index; + + ctx->sz += len; + + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + md4_do_chunk(ctx, (uint32_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 64-block as possible */ + for (; len >= 64; len -= 64, data += 64) + md4_do_chunk(ctx, (uint32_t *) data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_md4_finalize(struct md4_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[64] = { 0x80, }; + uint64_t bits; + uint32_t index, padlen; + + /* add padding and update data with it */ + bits = cpu_to_le64(ctx->sz << 3); + + /* pad out to 56 */ + index = (uint32_t) (ctx->sz & 0x3f); + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + cryptonite_md4_update(ctx, padding, padlen); + + /* append length */ + cryptonite_md4_update(ctx, (uint8_t *) &bits, sizeof(bits)); + + /* output hash */ + le32_to_cpu_array((uint32_t *) out, ctx->h, 4); +} diff --git a/cbits/cryptonite_md4.h b/cbits/cryptonite_md4.h new file mode 100644 index 0000000..4c6cd69 --- /dev/null +++ b/cbits/cryptonite_md4.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_MD4_H +#define CRYPTOHASH_MD4_H + +#include + +struct md4_ctx +{ + uint64_t sz; + uint8_t buf[64]; + uint32_t h[4]; +}; + +#define MD4_DIGEST_SIZE 16 +#define MD4_CTX_SIZE sizeof(struct md4_ctx) + +void cryptonite_md4_init(struct md4_ctx *ctx); +void cryptonite_md4_update(struct md4_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_md4_finalize(struct md4_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_md5.c b/cbits/cryptonite_md5.c new file mode 100644 index 0000000..fe44f5e --- /dev/null +++ b/cbits/cryptonite_md5.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "cryptonite_bitfn.h" +#include "cryptonite_md5.h" + +void cryptonite_md5_init(struct md5_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->sz = 0ULL; + ctx->h[0] = 0x67452301; + ctx->h[1] = 0xefcdab89; + ctx->h[2] = 0x98badcfe; + ctx->h[3] = 0x10325476; +} + +#define f1(x, y, z) (z ^ (x & (y ^ z))) +#define f2(x, y, z) f1(z, x, y) +#define f3(x, y, z) (x ^ y ^ z) +#define f4(x, y, z) (y ^ (x | ~z)) +#define R(f, a, b, c, d, i, k, s) a += f(b, c, d) + w[i] + k; a = rol32(a, s); a += b + +static void md5_do_chunk(struct md5_ctx *ctx, uint32_t *buf) +{ + uint32_t a, b, c, d; +#ifdef ARCH_IS_BIG_ENDIAN + uint32_t w[16]; + cpu_to_le32_array(w, buf, 16); +#else + uint32_t *w = buf; +#endif + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + + R(f1, a, b, c, d, 0, 0xd76aa478, 7); + R(f1, d, a, b, c, 1, 0xe8c7b756, 12); + R(f1, c, d, a, b, 2, 0x242070db, 17); + R(f1, b, c, d, a, 3, 0xc1bdceee, 22); + R(f1, a, b, c, d, 4, 0xf57c0faf, 7); + R(f1, d, a, b, c, 5, 0x4787c62a, 12); + R(f1, c, d, a, b, 6, 0xa8304613, 17); + R(f1, b, c, d, a, 7, 0xfd469501, 22); + R(f1, a, b, c, d, 8, 0x698098d8, 7); + R(f1, d, a, b, c, 9, 0x8b44f7af, 12); + R(f1, c, d, a, b, 10, 0xffff5bb1, 17); + R(f1, b, c, d, a, 11, 0x895cd7be, 22); + R(f1, a, b, c, d, 12, 0x6b901122, 7); + R(f1, d, a, b, c, 13, 0xfd987193, 12); + R(f1, c, d, a, b, 14, 0xa679438e, 17); + R(f1, b, c, d, a, 15, 0x49b40821, 22); + + R(f2, a, b, c, d, 1, 0xf61e2562, 5); + R(f2, d, a, b, c, 6, 0xc040b340, 9); + R(f2, c, d, a, b, 11, 0x265e5a51, 14); + R(f2, b, c, d, a, 0, 0xe9b6c7aa, 20); + R(f2, a, b, c, d, 5, 0xd62f105d, 5); + R(f2, d, a, b, c, 10, 0x02441453, 9); + R(f2, c, d, a, b, 15, 0xd8a1e681, 14); + R(f2, b, c, d, a, 4, 0xe7d3fbc8, 20); + R(f2, a, b, c, d, 9, 0x21e1cde6, 5); + R(f2, d, a, b, c, 14, 0xc33707d6, 9); + R(f2, c, d, a, b, 3, 0xf4d50d87, 14); + R(f2, b, c, d, a, 8, 0x455a14ed, 20); + R(f2, a, b, c, d, 13, 0xa9e3e905, 5); + R(f2, d, a, b, c, 2, 0xfcefa3f8, 9); + R(f2, c, d, a, b, 7, 0x676f02d9, 14); + R(f2, b, c, d, a, 12, 0x8d2a4c8a, 20); + + R(f3, a, b, c, d, 5, 0xfffa3942, 4); + R(f3, d, a, b, c, 8, 0x8771f681, 11); + R(f3, c, d, a, b, 11, 0x6d9d6122, 16); + R(f3, b, c, d, a, 14, 0xfde5380c, 23); + R(f3, a, b, c, d, 1, 0xa4beea44, 4); + R(f3, d, a, b, c, 4, 0x4bdecfa9, 11); + R(f3, c, d, a, b, 7, 0xf6bb4b60, 16); + R(f3, b, c, d, a, 10, 0xbebfbc70, 23); + R(f3, a, b, c, d, 13, 0x289b7ec6, 4); + R(f3, d, a, b, c, 0, 0xeaa127fa, 11); + R(f3, c, d, a, b, 3, 0xd4ef3085, 16); + R(f3, b, c, d, a, 6, 0x04881d05, 23); + R(f3, a, b, c, d, 9, 0xd9d4d039, 4); + R(f3, d, a, b, c, 12, 0xe6db99e5, 11); + R(f3, c, d, a, b, 15, 0x1fa27cf8, 16); + R(f3, b, c, d, a, 2, 0xc4ac5665, 23); + + R(f4, a, b, c, d, 0, 0xf4292244, 6); + R(f4, d, a, b, c, 7, 0x432aff97, 10); + R(f4, c, d, a, b, 14, 0xab9423a7, 15); + R(f4, b, c, d, a, 5, 0xfc93a039, 21); + R(f4, a, b, c, d, 12, 0x655b59c3, 6); + R(f4, d, a, b, c, 3, 0x8f0ccc92, 10); + R(f4, c, d, a, b, 10, 0xffeff47d, 15); + R(f4, b, c, d, a, 1, 0x85845dd1, 21); + R(f4, a, b, c, d, 8, 0x6fa87e4f, 6); + R(f4, d, a, b, c, 15, 0xfe2ce6e0, 10); + R(f4, c, d, a, b, 6, 0xa3014314, 15); + R(f4, b, c, d, a, 13, 0x4e0811a1, 21); + R(f4, a, b, c, d, 4, 0xf7537e82, 6); + R(f4, d, a, b, c, 11, 0xbd3af235, 10); + R(f4, c, d, a, b, 2, 0x2ad7d2bb, 15); + R(f4, b, c, d, a, 9, 0xeb86d391, 21); + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; +} + +void cryptonite_md5_update(struct md5_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + index = (uint32_t) (ctx->sz & 0x3f); + to_fill = 64 - index; + + ctx->sz += len; + + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + md5_do_chunk(ctx, (uint32_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 64-block as possible */ + for (; len >= 64; len -= 64, data += 64) + md5_do_chunk(ctx, (uint32_t *) data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_md5_finalize(struct md5_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[64] = { 0x80, }; + uint64_t bits; + uint32_t index, padlen; + uint32_t *p = (uint32_t *) out; + + /* add padding and update data with it */ + bits = cpu_to_le64(ctx->sz << 3); + + /* pad out to 56 */ + index = (uint32_t) (ctx->sz & 0x3f); + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + cryptonite_md5_update(ctx, padding, padlen); + + /* append length */ + cryptonite_md5_update(ctx, (uint8_t *) &bits, sizeof(bits)); + + /* output hash */ + p[0] = cpu_to_le32(ctx->h[0]); + p[1] = cpu_to_le32(ctx->h[1]); + p[2] = cpu_to_le32(ctx->h[2]); + p[3] = cpu_to_le32(ctx->h[3]); +} diff --git a/cbits/cryptonite_md5.h b/cbits/cryptonite_md5.h new file mode 100644 index 0000000..7f7ca2c --- /dev/null +++ b/cbits/cryptonite_md5.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_MD5_H +#define CRYPTOHASH_MD5_H + +#include + +struct md5_ctx +{ + uint64_t sz; + uint8_t buf[64]; + uint32_t h[4]; +}; + +#define MD5_DIGEST_SIZE 16 +#define MD5_CTX_SIZE sizeof(struct md5_ctx) + +void cryptonite_md5_init(struct md5_ctx *ctx); +void cryptonite_md5_update(struct md5_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_md5_finalize(struct md5_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_ripemd.c b/cbits/cryptonite_ripemd.c new file mode 100644 index 0000000..83d52ae --- /dev/null +++ b/cbits/cryptonite_ripemd.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cryptonite_ripemd.h" +#include "cryptonite_bitfn.h" +#include + +void cryptonite_ripemd160_init(struct ripemd160_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x67452301; + ctx->h[1] = 0xefcdab89; + ctx->h[2] = 0x98badcfe; + ctx->h[3] = 0x10325476; + ctx->h[4] = 0xc3d2e1f0; +} + +#define K1 0x00000000 +#define K2 0x5a827999 +#define K3 0x6ed9eba1 +#define K4 0x8f1bbcdc +#define K5 0xa953fd4e +#define K6 0x50a28be6 +#define K7 0x5c4dd124 +#define K8 0x6d703ef3 +#define K9 0x7a6d76e9 + +#define f1(x, y, z) (x ^ y ^ z) +#define f2(x, y, z) (z ^ (x & (y ^ z))) +#define f3(x, y, z) ((x | ~y) ^ z) +#define f4(x, y, z) (y ^ (z & (x ^ y))) +#define f5(x, y, z) (x ^ (y | ~z)) + +#define R(a, b, c, d, e, f, k, i, s) \ + a += f(b, c, d) + w[i] + k; a = rol32(a, s) + e; c = rol32(c, 10) + +static void ripemd160_do_chunk(struct ripemd160_ctx *ctx, uint32_t *buf) +{ + uint32_t a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; +#ifdef ARCH_IS_BIG_ENDIAN + uint32_t w[16]; + cpu_to_le32_array(w, buf, 16); +#else + uint32_t *w = buf; +#endif + + a1 = ctx->h[0]; b1 = ctx->h[1]; c1 = ctx->h[2]; d1 = ctx->h[3]; e1 = ctx->h[4]; + a2 = ctx->h[0]; b2 = ctx->h[1]; c2 = ctx->h[2]; d2 = ctx->h[3]; e2 = ctx->h[4]; + + /* 5 passes on first state copy */ + R(a1, b1, c1, d1, e1, f1, K1, 0, 11); + R(e1, a1, b1, c1, d1, f1, K1, 1, 14); + R(d1, e1, a1, b1, c1, f1, K1, 2, 15); + R(c1, d1, e1, a1, b1, f1, K1, 3, 12); + R(b1, c1, d1, e1, a1, f1, K1, 4, 5); + R(a1, b1, c1, d1, e1, f1, K1, 5, 8); + R(e1, a1, b1, c1, d1, f1, K1, 6, 7); + R(d1, e1, a1, b1, c1, f1, K1, 7, 9); + R(c1, d1, e1, a1, b1, f1, K1, 8, 11); + R(b1, c1, d1, e1, a1, f1, K1, 9, 13); + R(a1, b1, c1, d1, e1, f1, K1, 10, 14); + R(e1, a1, b1, c1, d1, f1, K1, 11, 15); + R(d1, e1, a1, b1, c1, f1, K1, 12, 6); + R(c1, d1, e1, a1, b1, f1, K1, 13, 7); + R(b1, c1, d1, e1, a1, f1, K1, 14, 9); + R(a1, b1, c1, d1, e1, f1, K1, 15, 8); + + R(e1, a1, b1, c1, d1, f2, K2, 7, 7); + R(d1, e1, a1, b1, c1, f2, K2, 4, 6); + R(c1, d1, e1, a1, b1, f2, K2, 13, 8); + R(b1, c1, d1, e1, a1, f2, K2, 1, 13); + R(a1, b1, c1, d1, e1, f2, K2, 10, 11); + R(e1, a1, b1, c1, d1, f2, K2, 6, 9); + R(d1, e1, a1, b1, c1, f2, K2, 15, 7); + R(c1, d1, e1, a1, b1, f2, K2, 3, 15); + R(b1, c1, d1, e1, a1, f2, K2, 12, 7); + R(a1, b1, c1, d1, e1, f2, K2, 0, 12); + R(e1, a1, b1, c1, d1, f2, K2, 9, 15); + R(d1, e1, a1, b1, c1, f2, K2, 5, 9); + R(c1, d1, e1, a1, b1, f2, K2, 2, 11); + R(b1, c1, d1, e1, a1, f2, K2, 14, 7); + R(a1, b1, c1, d1, e1, f2, K2, 11, 13); + R(e1, a1, b1, c1, d1, f2, K2, 8, 12); + + R(d1, e1, a1, b1, c1, f3, K3, 3, 11); + R(c1, d1, e1, a1, b1, f3, K3, 10, 13); + R(b1, c1, d1, e1, a1, f3, K3, 14, 6); + R(a1, b1, c1, d1, e1, f3, K3, 4, 7); + R(e1, a1, b1, c1, d1, f3, K3, 9, 14); + R(d1, e1, a1, b1, c1, f3, K3, 15, 9); + R(c1, d1, e1, a1, b1, f3, K3, 8, 13); + R(b1, c1, d1, e1, a1, f3, K3, 1, 15); + R(a1, b1, c1, d1, e1, f3, K3, 2, 14); + R(e1, a1, b1, c1, d1, f3, K3, 7, 8); + R(d1, e1, a1, b1, c1, f3, K3, 0, 13); + R(c1, d1, e1, a1, b1, f3, K3, 6, 6); + R(b1, c1, d1, e1, a1, f3, K3, 13, 5); + R(a1, b1, c1, d1, e1, f3, K3, 11, 12); + R(e1, a1, b1, c1, d1, f3, K3, 5, 7); + R(d1, e1, a1, b1, c1, f3, K3, 12, 5); + + R(c1, d1, e1, a1, b1, f4, K4, 1, 11); + R(b1, c1, d1, e1, a1, f4, K4, 9, 12); + R(a1, b1, c1, d1, e1, f4, K4, 11, 14); + R(e1, a1, b1, c1, d1, f4, K4, 10, 15); + R(d1, e1, a1, b1, c1, f4, K4, 0, 14); + R(c1, d1, e1, a1, b1, f4, K4, 8, 15); + R(b1, c1, d1, e1, a1, f4, K4, 12, 9); + R(a1, b1, c1, d1, e1, f4, K4, 4, 8); + R(e1, a1, b1, c1, d1, f4, K4, 13, 9); + R(d1, e1, a1, b1, c1, f4, K4, 3, 14); + R(c1, d1, e1, a1, b1, f4, K4, 7, 5); + R(b1, c1, d1, e1, a1, f4, K4, 15, 6); + R(a1, b1, c1, d1, e1, f4, K4, 14, 8); + R(e1, a1, b1, c1, d1, f4, K4, 5, 6); + R(d1, e1, a1, b1, c1, f4, K4, 6, 5); + R(c1, d1, e1, a1, b1, f4, K4, 2, 12); + + R(b1, c1, d1, e1, a1, f5, K5, 4, 9); + R(a1, b1, c1, d1, e1, f5, K5, 0, 15); + R(e1, a1, b1, c1, d1, f5, K5, 5, 5); + R(d1, e1, a1, b1, c1, f5, K5, 9, 11); + R(c1, d1, e1, a1, b1, f5, K5, 7, 6); + R(b1, c1, d1, e1, a1, f5, K5, 12, 8); + R(a1, b1, c1, d1, e1, f5, K5, 2, 13); + R(e1, a1, b1, c1, d1, f5, K5, 10, 12); + R(d1, e1, a1, b1, c1, f5, K5, 14, 5); + R(c1, d1, e1, a1, b1, f5, K5, 1, 12); + R(b1, c1, d1, e1, a1, f5, K5, 3, 13); + R(a1, b1, c1, d1, e1, f5, K5, 8, 14); + R(e1, a1, b1, c1, d1, f5, K5, 11, 11); + R(d1, e1, a1, b1, c1, f5, K5, 6, 8); + R(c1, d1, e1, a1, b1, f5, K5, 15, 5); + R(b1, c1, d1, e1, a1, f5, K5, 13, 6); + + /* 5 passes on second state copy */ + R(a2, b2, c2, d2, e2, f5, K6, 5, 8); + R(e2, a2, b2, c2, d2, f5, K6, 14, 9); + R(d2, e2, a2, b2, c2, f5, K6, 7, 9); + R(c2, d2, e2, a2, b2, f5, K6, 0, 11); + R(b2, c2, d2, e2, a2, f5, K6, 9, 13); + R(a2, b2, c2, d2, e2, f5, K6, 2, 15); + R(e2, a2, b2, c2, d2, f5, K6, 11, 15); + R(d2, e2, a2, b2, c2, f5, K6, 4, 5); + R(c2, d2, e2, a2, b2, f5, K6, 13, 7); + R(b2, c2, d2, e2, a2, f5, K6, 6, 7); + R(a2, b2, c2, d2, e2, f5, K6, 15, 8); + R(e2, a2, b2, c2, d2, f5, K6, 8, 11); + R(d2, e2, a2, b2, c2, f5, K6, 1, 14); + R(c2, d2, e2, a2, b2, f5, K6, 10, 14); + R(b2, c2, d2, e2, a2, f5, K6, 3, 12); + R(a2, b2, c2, d2, e2, f5, K6, 12, 6); + + R(e2, a2, b2, c2, d2, f4, K7, 6, 9); + R(d2, e2, a2, b2, c2, f4, K7, 11, 13); + R(c2, d2, e2, a2, b2, f4, K7, 3, 15); + R(b2, c2, d2, e2, a2, f4, K7, 7, 7); + R(a2, b2, c2, d2, e2, f4, K7, 0, 12); + R(e2, a2, b2, c2, d2, f4, K7, 13, 8); + R(d2, e2, a2, b2, c2, f4, K7, 5, 9); + R(c2, d2, e2, a2, b2, f4, K7, 10, 11); + R(b2, c2, d2, e2, a2, f4, K7, 14, 7); + R(a2, b2, c2, d2, e2, f4, K7, 15, 7); + R(e2, a2, b2, c2, d2, f4, K7, 8, 12); + R(d2, e2, a2, b2, c2, f4, K7, 12, 7); + R(c2, d2, e2, a2, b2, f4, K7, 4, 6); + R(b2, c2, d2, e2, a2, f4, K7, 9, 15); + R(a2, b2, c2, d2, e2, f4, K7, 1, 13); + R(e2, a2, b2, c2, d2, f4, K7, 2, 11); + + R(d2, e2, a2, b2, c2, f3, K8, 15, 9); + R(c2, d2, e2, a2, b2, f3, K8, 5, 7); + R(b2, c2, d2, e2, a2, f3, K8, 1, 15); + R(a2, b2, c2, d2, e2, f3, K8, 3, 11); + R(e2, a2, b2, c2, d2, f3, K8, 7, 8); + R(d2, e2, a2, b2, c2, f3, K8, 14, 6); + R(c2, d2, e2, a2, b2, f3, K8, 6, 6); + R(b2, c2, d2, e2, a2, f3, K8, 9, 14); + R(a2, b2, c2, d2, e2, f3, K8, 11, 12); + R(e2, a2, b2, c2, d2, f3, K8, 8, 13); + R(d2, e2, a2, b2, c2, f3, K8, 12, 5); + R(c2, d2, e2, a2, b2, f3, K8, 2, 14); + R(b2, c2, d2, e2, a2, f3, K8, 10, 13); + R(a2, b2, c2, d2, e2, f3, K8, 0, 13); + R(e2, a2, b2, c2, d2, f3, K8, 4, 7); + R(d2, e2, a2, b2, c2, f3, K8, 13, 5); + + R(c2, d2, e2, a2, b2, f2, K9, 8, 15); + R(b2, c2, d2, e2, a2, f2, K9, 6, 5); + R(a2, b2, c2, d2, e2, f2, K9, 4, 8); + R(e2, a2, b2, c2, d2, f2, K9, 1, 11); + R(d2, e2, a2, b2, c2, f2, K9, 3, 14); + R(c2, d2, e2, a2, b2, f2, K9, 11, 14); + R(b2, c2, d2, e2, a2, f2, K9, 15, 6); + R(a2, b2, c2, d2, e2, f2, K9, 0, 14); + R(e2, a2, b2, c2, d2, f2, K9, 5, 6); + R(d2, e2, a2, b2, c2, f2, K9, 12, 9); + R(c2, d2, e2, a2, b2, f2, K9, 2, 12); + R(b2, c2, d2, e2, a2, f2, K9, 13, 9); + R(a2, b2, c2, d2, e2, f2, K9, 9, 12); + R(e2, a2, b2, c2, d2, f2, K9, 7, 5); + R(d2, e2, a2, b2, c2, f2, K9, 10, 15); + R(c2, d2, e2, a2, b2, f2, K9, 14, 8); + + R(b2, c2, d2, e2, a2, f1, K1, 12, 8); + R(a2, b2, c2, d2, e2, f1, K1, 15, 5); + R(e2, a2, b2, c2, d2, f1, K1, 10, 12); + R(d2, e2, a2, b2, c2, f1, K1, 4, 9); + R(c2, d2, e2, a2, b2, f1, K1, 1, 12); + R(b2, c2, d2, e2, a2, f1, K1, 5, 5); + R(a2, b2, c2, d2, e2, f1, K1, 8, 14); + R(e2, a2, b2, c2, d2, f1, K1, 7, 6); + R(d2, e2, a2, b2, c2, f1, K1, 6, 8); + R(c2, d2, e2, a2, b2, f1, K1, 2, 13); + R(b2, c2, d2, e2, a2, f1, K1, 13, 6); + R(a2, b2, c2, d2, e2, f1, K1, 14, 5); + R(e2, a2, b2, c2, d2, f1, K1, 0, 15); + R(d2, e2, a2, b2, c2, f1, K1, 3, 13); + R(c2, d2, e2, a2, b2, f1, K1, 9, 11); + R(b2, c2, d2, e2, a2, f1, K1, 11, 11); + + d2 += c1 + ctx->h[1]; + ctx->h[1] = ctx->h[2] + d1 + e2; + ctx->h[2] = ctx->h[3] + e1 + a2; + ctx->h[3] = ctx->h[4] + a1 + b2; + ctx->h[4] = ctx->h[0] + b1 + c2; + ctx->h[0] = d2; +} + +void cryptonite_ripemd160_update(struct ripemd160_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + index = (uint32_t) (ctx->sz & 0x3f); + to_fill = 64 - index; + + ctx->sz += len; + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + ripemd160_do_chunk(ctx, (uint32_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + for (; len >= 64; len -= 64, data += 64) + ripemd160_do_chunk(ctx, (uint32_t *) data); + + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_ripemd160_finalize(struct ripemd160_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[64] = { 0x80, }; + uint64_t bits; + uint32_t index, padlen; + uint32_t *p = (uint32_t *) out; + + /* add padding and update data with it */ + bits = cpu_to_le64(ctx->sz << 3); + + /* pad out to 56 */ + index = (uint32_t) (ctx->sz & 0x3f); + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + cryptonite_ripemd160_update(ctx, padding, padlen); + + /* append length */ + cryptonite_ripemd160_update(ctx, (uint8_t *) &bits, sizeof(bits)); + + /* output digest */ + p[0] = cpu_to_le32(ctx->h[0]); + p[1] = cpu_to_le32(ctx->h[1]); + p[2] = cpu_to_le32(ctx->h[2]); + p[3] = cpu_to_le32(ctx->h[3]); + p[4] = cpu_to_le32(ctx->h[4]); +} diff --git a/cbits/cryptonite_ripemd.h b/cbits/cryptonite_ripemd.h new file mode 100644 index 0000000..59b5363 --- /dev/null +++ b/cbits/cryptonite_ripemd.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_RIPEMD_H +#define CRYPTOHASH_RIPEMD_H + +#include + +struct ripemd160_ctx +{ + uint64_t sz; + uint8_t buf[64]; + uint32_t h[5]; +}; + +#define RIPEMD160_DIGEST_SIZE 20 +#define RIPEMD160_CTX_SIZE sizeof(struct ripemd160_ctx) + +void cryptonite_ripemd160_init(struct ripemd160_ctx *ctx); +void cryptonite_ripemd160_update(struct ripemd160_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_ripemd160_finalize(struct ripemd160_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_sha1.c b/cbits/cryptonite_sha1.c new file mode 100644 index 0000000..185b4df --- /dev/null +++ b/cbits/cryptonite_sha1.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_sha1.h" +#include "cryptonite_bitfn.h" + +void cryptonite_sha1_init(struct sha1_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x67452301; + ctx->h[1] = 0xefcdab89; + ctx->h[2] = 0x98badcfe; + ctx->h[3] = 0x10325476; + ctx->h[4] = 0xc3d2e1f0; +} + +#define f1(x, y, z) (z ^ (x & (y ^ z))) +#define f2(x, y, z) (x ^ y ^ z) +#define f3(x, y, z) ((x & y) + (z & (x ^ y))) +#define f4(x, y, z) f2(x, y, z) + +#define K1 0x5a827999 +#define K2 0x6ed9eba1 +#define K3 0x8f1bbcdc +#define K4 0xca62c1d6 + +#define R(a, b, c, d, e, f, k, w) \ + e += rol32(a, 5) + f(b, c, d) + k + w; b = rol32(b, 30) + +#define M(i) (w[i & 0x0f] = rol32(w[i & 0x0f] ^ w[(i - 14) & 0x0f] \ + ^ w[(i - 8) & 0x0f] ^ w[(i - 3) & 0x0f], 1)) + +static inline void sha1_do_chunk(struct sha1_ctx *ctx, uint32_t *buf) +{ + uint32_t a, b, c, d, e; + uint32_t w[16]; +#define CPY(i) w[i] = be32_to_cpu(buf[i]) + CPY(0); CPY(1); CPY(2); CPY(3); CPY(4); CPY(5); CPY(6); CPY(7); + CPY(8); CPY(9); CPY(10); CPY(11); CPY(12); CPY(13); CPY(14); CPY(15); +#undef CPY + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; e = ctx->h[4]; + + R(a, b, c, d, e, f1, K1, w[0]); + R(e, a, b, c, d, f1, K1, w[1]); + R(d, e, a, b, c, f1, K1, w[2]); + R(c, d, e, a, b, f1, K1, w[3]); + R(b, c, d, e, a, f1, K1, w[4]); + R(a, b, c, d, e, f1, K1, w[5]); + R(e, a, b, c, d, f1, K1, w[6]); + R(d, e, a, b, c, f1, K1, w[7]); + R(c, d, e, a, b, f1, K1, w[8]); + R(b, c, d, e, a, f1, K1, w[9]); + R(a, b, c, d, e, f1, K1, w[10]); + R(e, a, b, c, d, f1, K1, w[11]); + R(d, e, a, b, c, f1, K1, w[12]); + R(c, d, e, a, b, f1, K1, w[13]); + R(b, c, d, e, a, f1, K1, w[14]); + R(a, b, c, d, e, f1, K1, w[15]); + R(e, a, b, c, d, f1, K1, M(16)); + R(d, e, a, b, c, f1, K1, M(17)); + R(c, d, e, a, b, f1, K1, M(18)); + R(b, c, d, e, a, f1, K1, M(19)); + + R(a, b, c, d, e, f2, K2, M(20)); + R(e, a, b, c, d, f2, K2, M(21)); + R(d, e, a, b, c, f2, K2, M(22)); + R(c, d, e, a, b, f2, K2, M(23)); + R(b, c, d, e, a, f2, K2, M(24)); + R(a, b, c, d, e, f2, K2, M(25)); + R(e, a, b, c, d, f2, K2, M(26)); + R(d, e, a, b, c, f2, K2, M(27)); + R(c, d, e, a, b, f2, K2, M(28)); + R(b, c, d, e, a, f2, K2, M(29)); + R(a, b, c, d, e, f2, K2, M(30)); + R(e, a, b, c, d, f2, K2, M(31)); + R(d, e, a, b, c, f2, K2, M(32)); + R(c, d, e, a, b, f2, K2, M(33)); + R(b, c, d, e, a, f2, K2, M(34)); + R(a, b, c, d, e, f2, K2, M(35)); + R(e, a, b, c, d, f2, K2, M(36)); + R(d, e, a, b, c, f2, K2, M(37)); + R(c, d, e, a, b, f2, K2, M(38)); + R(b, c, d, e, a, f2, K2, M(39)); + + R(a, b, c, d, e, f3, K3, M(40)); + R(e, a, b, c, d, f3, K3, M(41)); + R(d, e, a, b, c, f3, K3, M(42)); + R(c, d, e, a, b, f3, K3, M(43)); + R(b, c, d, e, a, f3, K3, M(44)); + R(a, b, c, d, e, f3, K3, M(45)); + R(e, a, b, c, d, f3, K3, M(46)); + R(d, e, a, b, c, f3, K3, M(47)); + R(c, d, e, a, b, f3, K3, M(48)); + R(b, c, d, e, a, f3, K3, M(49)); + R(a, b, c, d, e, f3, K3, M(50)); + R(e, a, b, c, d, f3, K3, M(51)); + R(d, e, a, b, c, f3, K3, M(52)); + R(c, d, e, a, b, f3, K3, M(53)); + R(b, c, d, e, a, f3, K3, M(54)); + R(a, b, c, d, e, f3, K3, M(55)); + R(e, a, b, c, d, f3, K3, M(56)); + R(d, e, a, b, c, f3, K3, M(57)); + R(c, d, e, a, b, f3, K3, M(58)); + R(b, c, d, e, a, f3, K3, M(59)); + + R(a, b, c, d, e, f4, K4, M(60)); + R(e, a, b, c, d, f4, K4, M(61)); + R(d, e, a, b, c, f4, K4, M(62)); + R(c, d, e, a, b, f4, K4, M(63)); + R(b, c, d, e, a, f4, K4, M(64)); + R(a, b, c, d, e, f4, K4, M(65)); + R(e, a, b, c, d, f4, K4, M(66)); + R(d, e, a, b, c, f4, K4, M(67)); + R(c, d, e, a, b, f4, K4, M(68)); + R(b, c, d, e, a, f4, K4, M(69)); + R(a, b, c, d, e, f4, K4, M(70)); + R(e, a, b, c, d, f4, K4, M(71)); + R(d, e, a, b, c, f4, K4, M(72)); + R(c, d, e, a, b, f4, K4, M(73)); + R(b, c, d, e, a, f4, K4, M(74)); + R(a, b, c, d, e, f4, K4, M(75)); + R(e, a, b, c, d, f4, K4, M(76)); + R(d, e, a, b, c, f4, K4, M(77)); + R(c, d, e, a, b, f4, K4, M(78)); + R(b, c, d, e, a, f4, K4, M(79)); + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; +} + +void cryptonite_sha1_update(struct sha1_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + index = (uint32_t) (ctx->sz & 0x3f); + to_fill = 64 - index; + + ctx->sz += len; + + /* process partial buffer if there's enough data to make a block */ + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + sha1_do_chunk(ctx, (uint32_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 64-block as possible */ + for (; len >= 64; len -= 64, data += 64) + sha1_do_chunk(ctx, (uint32_t *) data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[64] = { 0x80, }; + uint64_t bits; + uint32_t index, padlen; + uint32_t *p = (uint32_t *) out; + + /* add padding and update data with it */ + bits = cpu_to_be64(ctx->sz << 3); + + /* pad out to 56 */ + index = (uint32_t) (ctx->sz & 0x3f); + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + cryptonite_sha1_update(ctx, padding, padlen); + + /* append length */ + cryptonite_sha1_update(ctx, (uint8_t *) &bits, sizeof(bits)); + + /* output hash */ + p[0] = cpu_to_be32(ctx->h[0]); + p[1] = cpu_to_be32(ctx->h[1]); + p[2] = cpu_to_be32(ctx->h[2]); + p[3] = cpu_to_be32(ctx->h[3]); + p[4] = cpu_to_be32(ctx->h[4]); +} diff --git a/cbits/cryptonite_sha1.h b/cbits/cryptonite_sha1.h new file mode 100644 index 0000000..fc32514 --- /dev/null +++ b/cbits/cryptonite_sha1.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SHA1_H +#define CRYPTOHASH_SHA1_H + +#include + +struct sha1_ctx +{ + uint64_t sz; + uint8_t buf[64]; + uint32_t h[5]; +}; + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_CTX_SIZE (sizeof(struct sha1_ctx)) + +void cryptonite_sha1_init(struct sha1_ctx *ctx); +void cryptonite_sha1_update(struct sha1_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_sha256.c b/cbits/cryptonite_sha256.c new file mode 100644 index 0000000..f1a9cc1 --- /dev/null +++ b/cbits/cryptonite_sha256.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_sha256.h" +#include "cryptonite_bitfn.h" + +void cryptonite_sha224_init(struct sha224_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0xc1059ed8; + ctx->h[1] = 0x367cd507; + ctx->h[2] = 0x3070dd17; + ctx->h[3] = 0xf70e5939; + ctx->h[4] = 0xffc00b31; + ctx->h[5] = 0x68581511; + ctx->h[6] = 0x64f98fa7; + ctx->h[7] = 0xbefa4fa4; +} + +void cryptonite_sha256_init(struct sha256_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x6a09e667; + ctx->h[1] = 0xbb67ae85; + ctx->h[2] = 0x3c6ef372; + ctx->h[3] = 0xa54ff53a; + ctx->h[4] = 0x510e527f; + ctx->h[5] = 0x9b05688c; + ctx->h[6] = 0x1f83d9ab; + ctx->h[7] = 0x5be0cd19; +} + +/* 232 times the cube root of the first 64 primes 2..311 */ +static const uint32_t k[] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#define e0(x) (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22)) +#define e1(x) (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25)) +#define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3)) +#define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10)) + +static void sha256_do_chunk(struct sha256_ctx *ctx, uint32_t buf[]) +{ + uint32_t a, b, c, d, e, f, g, h, t1, t2; + int i; + uint32_t w[64]; + + cpu_to_be32_array(w, buf, 16); + for (i = 16; i < 64; i++) + w[i] = s1(w[i - 2]) + w[i - 7] + s0(w[i - 15]) + w[i - 16]; + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7]; + +#define R(a, b, c, d, e, f, g, h, k, w) \ + t1 = h + e1(e) + (g ^ (e & (f ^ g))) + k + w; \ + t2 = e0(a) + ((a & b) | (c & (a | b))); \ + d += t1; \ + h = t1 + t2; + + for (i = 0; i < 64; i += 8) { + R(a, b, c, d, e, f, g, h, k[i + 0], w[i + 0]); + R(h, a, b, c, d, e, f, g, k[i + 1], w[i + 1]); + R(g, h, a, b, c, d, e, f, k[i + 2], w[i + 2]); + R(f, g, h, a, b, c, d, e, k[i + 3], w[i + 3]); + R(e, f, g, h, a, b, c, d, k[i + 4], w[i + 4]); + R(d, e, f, g, h, a, b, c, k[i + 5], w[i + 5]); + R(c, d, e, f, g, h, a, b, k[i + 6], w[i + 6]); + R(b, c, d, e, f, g, h, a, k[i + 7], w[i + 7]); + } + +#undef R + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; + ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h; +} + +void cryptonite_sha224_update(struct sha224_ctx *ctx, uint8_t *data, uint32_t len) +{ + return cryptonite_sha256_update(ctx, data, len); +} + +void cryptonite_sha256_update(struct sha256_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + /* check for partial buffer */ + index = (uint32_t) (ctx->sz & 0x3f); + to_fill = 64 - index; + + ctx->sz += len; + + /* process partial buffer if there's enough data to make a block */ + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + sha256_do_chunk(ctx, (uint32_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 64-block as possible */ + for (; len >= 64; len -= 64, data += 64) + sha256_do_chunk(ctx, (uint32_t *) data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out) +{ + uint8_t intermediate[SHA256_DIGEST_SIZE]; + + cryptonite_sha256_finalize(ctx, intermediate); + memcpy(out, intermediate, SHA224_DIGEST_SIZE); +} + +void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[64] = { 0x80, }; + uint64_t bits; + uint32_t i, index, padlen; + uint32_t *p = (uint32_t *) out; + + /* cpu -> big endian */ + bits = cpu_to_be64(ctx->sz << 3); + + /* pad out to 56 */ + index = (uint32_t) (ctx->sz & 0x3f); + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + cryptonite_sha256_update(ctx, padding, padlen); + + /* append length */ + cryptonite_sha256_update(ctx, (uint8_t *) &bits, sizeof(bits)); + + /* store to digest */ + for (i = 0; i < 8; i++) + p[i] = cpu_to_be32(ctx->h[i]); +} diff --git a/cbits/cryptonite_sha256.h b/cbits/cryptonite_sha256.h new file mode 100644 index 0000000..1d960a2 --- /dev/null +++ b/cbits/cryptonite_sha256.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CRYPTOHASH_SHA256_H +#define CRYPTOHASH_SHA256_H + +#include + +struct sha256_ctx +{ + uint64_t sz; + uint8_t buf[128]; + uint32_t h[8]; +}; + +#define sha224_ctx sha256_ctx + +#define SHA224_DIGEST_SIZE 28 +#define SHA224_CTX_SIZE sizeof(struct sha224_ctx) + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_CTX_SIZE sizeof(struct sha256_ctx) + +void cryptonite_sha224_init(struct sha224_ctx *ctx); +void cryptonite_sha224_update(struct sha224_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out); + +void cryptonite_sha256_init(struct sha256_ctx *ctx); +void cryptonite_sha256_update(struct sha256_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_sha3.c b/cbits/cryptonite_sha3.c new file mode 100644 index 0000000..bc2c0b8 --- /dev/null +++ b/cbits/cryptonite_sha3.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2012 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "cryptonite_bitfn.h" +#include "cryptonite_sha3.h" + +#define KECCAK_NB_ROUNDS 24 + +/* rounds constants */ +static const uint64_t keccak_rndc[24] = +{ + 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, + 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL, + 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, + 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL, + 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL, +}; + +/* triangular numbers constants */ +static const int keccak_rotc[24] = + { 1,3,6,10,15,21,28,36,45,55,2,14,27,41,56,8,25,43,62,18,39,61,20,44 }; + +static const int keccak_piln[24] = + { 10,7,11,17,18,3,5,16,8,21,24,4,15,23,19,13,12,2,20,14,22,9,6,1 }; + +static inline void sha3_do_chunk(uint64_t state[25], uint64_t buf[], int bufsz) +{ + int i, j, r; + uint64_t tmp, bc[5]; + + /* merge buf with state */ + for (i = 0; i < bufsz; i++) + state[i] ^= le64_to_cpu(buf[i]); + + /* run keccak rounds */ + for (r = 0; r < KECCAK_NB_ROUNDS; r++) { + /* compute the parity of each columns */ + for (i = 0; i < 5; i++) + bc[i] = state[i] ^ state[i+5] ^ state[i+10] ^ state[i+15] ^ state[i+20]; + + for (i = 0; i < 5; i++) { + tmp = bc[(i + 4) % 5] ^ rol64(bc[(i + 1) % 5], 1); + for (j = 0; j < 25; j += 5) + state[j + i] ^= tmp; + } + + /* rho pi */ + tmp = state[1]; + for (i = 0; i < 24; i++) { + j = keccak_piln[i]; + bc[0] = state[j]; + state[j] = rol64(tmp, keccak_rotc[i]); + tmp = bc[0]; + } + + /* bitwise combine along rows using a = a xor (not b and c) */ + for (j = 0; j < 25; j += 5) { + for (i = 0; i < 5; i++) + bc[i] = state[j + i]; + #define andn(b,c) (~(b) & (c)) + state[j + 0] ^= andn(bc[1], bc[2]); + state[j + 1] ^= andn(bc[2], bc[3]); + state[j + 2] ^= andn(bc[3], bc[4]); + state[j + 3] ^= andn(bc[4], bc[0]); + state[j + 4] ^= andn(bc[0], bc[1]); + #undef andn + } + + /* xor the round constant */ + state[0] ^= keccak_rndc[r]; + } +} + +void cryptonite_sha3_init(struct sha3_ctx *ctx, uint32_t hashlen) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->hashlen = hashlen / 8; + ctx->bufsz = 200 - 2 * ctx->hashlen; +} + +void cryptonite_sha3_update(struct sha3_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t to_fill; + + to_fill = ctx->bufsz - ctx->bufindex; + + if (ctx->bufindex == ctx->bufsz) { + sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8); + ctx->bufindex = 0; + } + + /* process partial buffer if there's enough data to make a block */ + if (ctx->bufindex && len >= to_fill) { + memcpy(ctx->buf + ctx->bufindex, data, to_fill); + sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8); + len -= to_fill; + data += to_fill; + ctx->bufindex = 0; + } + + /* process as much ctx->bufsz-block */ + for (; len >= ctx->bufsz; len -= ctx->bufsz, data += ctx->bufsz) + sha3_do_chunk(ctx->state, (uint64_t *) data, ctx->bufsz / 8); + + /* append data into buf */ + if (len) { + memcpy(ctx->buf + ctx->bufindex, data, len); + ctx->bufindex += len; + } +} + +void cryptonite_sha3_finalize(struct sha3_ctx *ctx, uint8_t *out) +{ + uint64_t w[25]; + + /* process full buffer if needed */ + if (ctx->bufindex == ctx->bufsz) { + sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8); + ctx->bufindex = 0; + } + + /* add the 10*1 padding */ + ctx->buf[ctx->bufindex++] = 1; + memset(ctx->buf + ctx->bufindex, 0, ctx->bufsz - ctx->bufindex); + ctx->buf[ctx->bufsz - 1] |= 0x80; + + /* process */ + sha3_do_chunk(ctx->state, (uint64_t *) ctx->buf, ctx->bufsz / 8); + + /* output */ + cpu_to_le64_array(w, ctx->state, 25); + memcpy(out, w, ctx->hashlen); +} diff --git a/cbits/cryptonite_sha3.h b/cbits/cryptonite_sha3.h new file mode 100644 index 0000000..b18d74f --- /dev/null +++ b/cbits/cryptonite_sha3.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SHA3_H +#define CRYPTOHASH_SHA3_H + +#include + +struct sha3_ctx +{ + uint32_t hashlen; /* in bytes */ + uint32_t bufindex; + uint64_t state[25]; + uint32_t bufsz; + uint32_t _padding; + uint8_t buf[144]; /* minimum SHA3-224, otherwise buffer need increases */ +}; + +#define SHA3_CTX_SIZE sizeof(struct sha3_ctx) + +void cryptonite_sha3_init(struct sha3_ctx *ctx, uint32_t hashlen); +void cryptonite_sha3_update(struct sha3_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_sha3_finalize(struct sha3_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_sha512.c b/cbits/cryptonite_sha512.c new file mode 100644 index 0000000..9a0791c --- /dev/null +++ b/cbits/cryptonite_sha512.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_bitfn.h" +#include "cryptonite_sha512.h" + +void cryptonite_sha384_init(struct sha512_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0xcbbb9d5dc1059ed8ULL; + ctx->h[1] = 0x629a292a367cd507ULL; + ctx->h[2] = 0x9159015a3070dd17ULL; + ctx->h[3] = 0x152fecd8f70e5939ULL; + ctx->h[4] = 0x67332667ffc00b31ULL; + ctx->h[5] = 0x8eb44a8768581511ULL; + ctx->h[6] = 0xdb0c2e0d64f98fa7ULL; + ctx->h[7] = 0x47b5481dbefa4fa4ULL; +} + +void cryptonite_sha512_init(struct sha512_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x6a09e667f3bcc908ULL; + ctx->h[1] = 0xbb67ae8584caa73bULL; + ctx->h[2] = 0x3c6ef372fe94f82bULL; + ctx->h[3] = 0xa54ff53a5f1d36f1ULL; + ctx->h[4] = 0x510e527fade682d1ULL; + ctx->h[5] = 0x9b05688c2b3e6c1fULL; + ctx->h[6] = 0x1f83d9abfb41bd6bULL; + ctx->h[7] = 0x5be0cd19137e2179ULL; +} + +/* 232 times the cube root of the first 64 primes 2..311 */ +static const uint64_t k[] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +#define e0(x) (ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39)) +#define e1(x) (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41)) +#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) +#define s1(x) (ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6)) + +static void sha512_do_chunk(struct sha512_ctx *ctx, uint64_t *buf) +{ + uint64_t a, b, c, d, e, f, g, h, t1, t2; + int i; + uint64_t w[80]; + + cpu_to_be64_array(w, buf, 16); + + for (i = 16; i < 80; i++) + w[i] = s1(w[i - 2]) + w[i - 7] + s0(w[i - 15]) + w[i - 16]; + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7]; + +#define R(a, b, c, d, e, f, g, h, k, w) \ + t1 = h + e1(e) + (g ^ (e & (f ^ g))) + k + w; \ + t2 = e0(a) + ((a & b) | (c & (a | b))); \ + d += t1; \ + h = t1 + t2 + + for (i = 0; i < 80; i += 8) { + R(a, b, c, d, e, f, g, h, k[i + 0], w[i + 0]); + R(h, a, b, c, d, e, f, g, k[i + 1], w[i + 1]); + R(g, h, a, b, c, d, e, f, k[i + 2], w[i + 2]); + R(f, g, h, a, b, c, d, e, k[i + 3], w[i + 3]); + R(e, f, g, h, a, b, c, d, k[i + 4], w[i + 4]); + R(d, e, f, g, h, a, b, c, k[i + 5], w[i + 5]); + R(c, d, e, f, g, h, a, b, k[i + 6], w[i + 6]); + R(b, c, d, e, f, g, h, a, k[i + 7], w[i + 7]); + } + +#undef R + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; + ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h; +} + +void cryptonite_sha384_update(struct sha384_ctx *ctx, uint8_t *data, uint32_t len) +{ + return cryptonite_sha512_update(ctx, data, len); +} + +void cryptonite_sha512_update(struct sha512_ctx *ctx, uint8_t *data, uint32_t len) +{ + unsigned int index, to_fill; + + /* check for partial buffer */ + index = (unsigned int) (ctx->sz[0] & 0x7f); + to_fill = 128 - index; + + ctx->sz[0] += len; + if (ctx->sz[0] < len) + ctx->sz[1]++; + + /* process partial buffer if there's enough data to make a block */ + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + sha512_do_chunk(ctx, (uint64_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 128-block as possible */ + for (; len >= 128; len -= 128, data += 128) + sha512_do_chunk(ctx, (uint64_t *) data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out) +{ + uint8_t intermediate[SHA512_DIGEST_SIZE]; + + cryptonite_sha512_finalize(ctx, intermediate); + memcpy(out, intermediate, SHA384_DIGEST_SIZE); +} + +void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[128] = { 0x80, }; + uint32_t i, index, padlen; + uint64_t bits[2]; + uint64_t *p = (uint64_t *) out; + + /* cpu -> big endian */ + bits[0] = cpu_to_be64((ctx->sz[1] << 3 | ctx->sz[0] >> 61)); + bits[1] = cpu_to_be64((ctx->sz[0] << 3)); + + /* pad out to 56 */ + index = (unsigned int) (ctx->sz[0] & 0x7f); + padlen = (index < 112) ? (112 - index) : ((128 + 112) - index); + cryptonite_sha512_update(ctx, padding, padlen); + + /* append length */ + cryptonite_sha512_update(ctx, (uint8_t *) bits, sizeof(bits)); + + /* store to digest */ + for (i = 0; i < 8; i++) + p[i] = cpu_to_be64(ctx->h[i]); +} + +#include + +void cryptonite_sha512_init_t(struct sha512_ctx *ctx, int t) +{ + memset(ctx, 0, sizeof(*ctx)); + if (t >= 512) + return; + + switch (t) { + case 224: + ctx->h[0] = 0x8c3d37c819544da2ULL; + ctx->h[1] = 0x73e1996689dcd4d6ULL; + ctx->h[2] = 0x1dfab7ae32ff9c82ULL; + ctx->h[3] = 0x679dd514582f9fcfULL; + ctx->h[4] = 0x0f6d2b697bd44da8ULL; + ctx->h[5] = 0x77e36f7304c48942ULL; + ctx->h[6] = 0x3f9d85a86a1d36c8ULL; + ctx->h[7] = 0x1112e6ad91d692a1ULL; + break; + case 256: + ctx->h[0] = 0x22312194fc2bf72cULL; + ctx->h[1] = 0x9f555fa3c84c64c2ULL; + ctx->h[2] = 0x2393b86b6f53b151ULL; + ctx->h[3] = 0x963877195940eabdULL; + ctx->h[4] = 0x96283ee2a88effe3ULL; + ctx->h[5] = 0xbe5e1e2553863992ULL; + ctx->h[6] = 0x2b0199fc2c85b8aaULL; + ctx->h[7] = 0x0eb72ddc81c52ca2ULL; + break; + default: { + char buf[8+4]; + uint8_t out[64]; + int i; + + cryptonite_sha512_init(ctx); + for (i = 0; i < 8; i++) + ctx->h[i] ^= 0xa5a5a5a5a5a5a5a5ULL; + + i = sprintf(buf, "SHA-512/%d", t); + cryptonite_sha512_update(ctx, buf, i); + cryptonite_sha512_finalize(ctx, out); + + /* re-init the context, otherwise len is changed */ + memset(ctx, 0, sizeof(*ctx)); + for (i = 0; i < 8; i++) + ctx->h[i] = cpu_to_be64(((uint64_t *) out)[i]); + } + } +} diff --git a/cbits/cryptonite_sha512.h b/cbits/cryptonite_sha512.h new file mode 100644 index 0000000..a5c199f --- /dev/null +++ b/cbits/cryptonite_sha512.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SHA512_H +#define CRYPTOHASH_SHA512_H + +#include + +struct sha512_ctx +{ + uint64_t sz[2]; + uint8_t buf[128]; + uint64_t h[8]; +}; + +#define sha384_ctx sha512_ctx + +#define SHA384_DIGEST_SIZE 64 +#define SHA384_CTX_SIZE sizeof(struct sha384_ctx) + +#define SHA512_DIGEST_SIZE 64 +#define SHA512_CTX_SIZE sizeof(struct sha512_ctx) + +void cryptonite_sha384_init(struct sha384_ctx *ctx); +void cryptonite_sha384_update(struct sha384_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out); + +void cryptonite_sha512_init(struct sha512_ctx *ctx); +void cryptonite_sha512_update(struct sha512_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out); + +void cryptonite_sha512_init_t(struct sha512_ctx *ctx, int t); + +#endif diff --git a/cbits/cryptonite_skein.h b/cbits/cryptonite_skein.h new file mode 100644 index 0000000..ec09b97 --- /dev/null +++ b/cbits/cryptonite_skein.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2006-2010 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SKEIN_H +#define CRYPTOHASH_SKEIN_H + +#define SKEIN_VERSION 1ULL +#define SKEIN_IDSTRING 0x33414853ULL + +/* +t0 0-63 || t1 64-127 +0-95 96-111 112-118 119 120-125 126 127 +Position reserved TreeLevel BitPad Type First Final +*/ +#define FLAG_FIRST (1ULL << 62) +#define FLAG_FINAL (1ULL << 63) +#define FLAG_TYPE(x) (((uint64_t) ((x) & 0x3f)) << 56) + +#define TYPE_KEY 0x00 +#define TYPE_CFG 0x04 +#define TYPE_MSG 0x30 +#define TYPE_OUT 0x3f + +#define SET_TYPE(ctx, ty) ctx->t0 = 0; ctx->t1 = (ty) + +#endif diff --git a/cbits/cryptonite_skein256.c b/cbits/cryptonite_skein256.c new file mode 100644 index 0000000..42c8853 --- /dev/null +++ b/cbits/cryptonite_skein256.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2006-2010 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_skein.h" +#include "cryptonite_skein256.h" +#include "cryptonite_bitfn.h" + +static const uint8_t K256_0[2] = { 14, 16, }; +static const uint8_t K256_1[2] = { 52, 57, }; +static const uint8_t K256_2[2] = { 23, 40, }; +static const uint8_t K256_3[2] = { 5, 37, }; +static const uint8_t K256_4[2] = { 25, 33, }; +static const uint8_t K256_5[2] = { 46, 12, }; +static const uint8_t K256_6[2] = { 58, 22, }; +static const uint8_t K256_7[2] = { 32, 32, }; + +static inline void skein256_do_chunk(struct skein256_ctx *ctx, uint64_t *buf, uint32_t len) +{ + uint64_t x[4]; + uint64_t ts[3]; + uint64_t ks[4+1]; + + ks[4] = 0x1bd11bdaa9fc1a22ULL; + ks[0] = ctx->h[0]; ks[4] ^= ctx->h[0]; + ks[1] = ctx->h[1]; ks[4] ^= ctx->h[1]; + ks[2] = ctx->h[2]; ks[4] ^= ctx->h[2]; + ks[3] = ctx->h[3]; ks[4] ^= ctx->h[3]; + + ts[0] = ctx->t0; + ts[1] = ctx->t1; + + ts[0] += len; + + ts[2] = ts[0] ^ ts[1]; + +#define INJECTKEY(r) \ + x[0] += ks[((r)+0) % (4+1)]; \ + x[1] += ks[((r)+1) % (4+1)] + ts[((r)+0) % 3]; \ + x[2] += ks[((r)+2) % (4+1)] + ts[((r)+1) % 3]; \ + x[3] += ks[((r)+3) % (4+1)] + (r) + +#define ROUND(a,b,c,d,k) \ + x[a] += x[b]; x[b] = rol64(x[b],k[0]); x[b] ^= x[a]; \ + x[c] += x[d]; x[d] = rol64(x[d],k[1]); x[d] ^= x[c]; + +#define PASS(i) \ + ROUND(0,1,2,3,K256_0); \ + ROUND(0,3,2,1,K256_1); \ + ROUND(0,1,2,3,K256_2); \ + ROUND(0,3,2,1,K256_3); \ + INJECTKEY((i*2) + 1); \ + ROUND(0,1,2,3,K256_4); \ + ROUND(0,3,2,1,K256_5); \ + ROUND(0,1,2,3,K256_6); \ + ROUND(0,3,2,1,K256_7); \ + INJECTKEY((i*2) + 2) + + x[0] = le64_to_cpu(buf[0]) + ks[0]; + x[1] = le64_to_cpu(buf[1]) + ks[1] + ts[0]; + x[2] = le64_to_cpu(buf[2]) + ks[2] + ts[1]; + x[3] = le64_to_cpu(buf[3]) + ks[3]; + + /* 9 pass of 8 rounds = 72 rounds */ + PASS(0); + PASS(1); + PASS(2); + PASS(3); + PASS(4); + PASS(5); + PASS(6); + PASS(7); + PASS(8); + + ts[1] &= ~FLAG_FIRST; + ctx->t0 = ts[0]; + ctx->t1 = ts[1]; + + ctx->h[0] = x[0] ^ cpu_to_le64(buf[0]); + ctx->h[1] = x[1] ^ cpu_to_le64(buf[1]); + ctx->h[2] = x[2] ^ cpu_to_le64(buf[2]); + ctx->h[3] = x[3] ^ cpu_to_le64(buf[3]); +} + +void cryptonite_skein256_init(struct skein256_ctx *ctx, uint32_t hashlen) +{ + uint64_t buf[4]; + memset(ctx, 0, sizeof(*ctx)); + + ctx->hashlen = (hashlen + 7) >> 3; + SET_TYPE(ctx, FLAG_FIRST | FLAG_FINAL | FLAG_TYPE(TYPE_CFG)); + + memset(buf, '\0', sizeof(buf)); + buf[0] = cpu_to_le64((SKEIN_VERSION << 32) | SKEIN_IDSTRING); + buf[1] = cpu_to_le64(hashlen); + buf[2] = 0; /* tree info, not implemented */ + skein256_do_chunk(ctx, buf, 4*8); + + SET_TYPE(ctx, FLAG_FIRST | FLAG_TYPE(TYPE_MSG)); +} + +void cryptonite_skein256_update(struct skein256_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t to_fill; + + if (!len) + return; + + to_fill = 32 - ctx->bufindex; + + if (ctx->bufindex == 32) { + skein256_do_chunk(ctx, (uint64_t *) ctx->buf, 32); + ctx->bufindex = 0; + } + + /* process partial buffer if there's enough data to make a block + * and there's without doubt further blocks */ + if (ctx->bufindex && len > to_fill) { + memcpy(ctx->buf + ctx->bufindex, data, to_fill); + skein256_do_chunk(ctx, (uint64_t *) ctx->buf, 32); + len -= to_fill; + data += to_fill; + ctx->bufindex = 0; + } + + /* process as much 32-block as possible except the last one in case we finalize */ + for (; len > 32; len -= 32, data += 32) + skein256_do_chunk(ctx, (uint64_t *) data, 32); + + /* append data into buf */ + if (len) { + memcpy(ctx->buf + ctx->bufindex, data, len); + ctx->bufindex += len; + } +} + +void cryptonite_skein256_finalize(struct skein256_ctx *ctx, uint8_t *out) +{ + uint32_t outsize; + uint64_t *p = (uint64_t *) out; + uint64_t x[4]; + int i, j, n; + + ctx->t1 |= FLAG_FINAL; + /* if buf is not complete pad with 0 bytes */ + if (ctx->bufindex < 32) + memset(ctx->buf + ctx->bufindex, '\0', 32 - ctx->bufindex); + skein256_do_chunk(ctx, (uint64_t *) ctx->buf, ctx->bufindex); + + memset(ctx->buf, '\0', 32); + + /* make sure we have a 8 bit rounded value */ + outsize = ctx->hashlen; + + /* backup h[0--4] */ + for (j = 0; j < 4; j++) + x[j] = ctx->h[j]; + /* threefish in counter mode, 0 for 1st 64 bytes, 1 for 2nd 64 bytes, .. */ + for (i = 0; i*32 < outsize; i++) { + uint64_t w[4]; + *((uint64_t *) ctx->buf) = cpu_to_le64(i); + SET_TYPE(ctx, FLAG_FIRST | FLAG_FINAL | FLAG_TYPE(TYPE_OUT)); + skein256_do_chunk(ctx, (uint64_t *) ctx->buf, sizeof(uint64_t)); + + n = outsize - i * 32; + if (n >= 32) n = 32; + + cpu_to_le64_array(w, ctx->h, 4); + memcpy(out + i*32, w, n); + + /* restore h[0--4] */ + for (j = 0; j < 4; j++) + ctx->h[j] = x[j]; + } +} diff --git a/cbits/cryptonite_skein256.h b/cbits/cryptonite_skein256.h new file mode 100644 index 0000000..1ba977d --- /dev/null +++ b/cbits/cryptonite_skein256.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2006-2010 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SKEIN256_H +#define CRYPTOHASH_SKEIN256_H + +#include + +struct skein256_ctx +{ + uint32_t hashlen; + uint32_t bufindex; + uint8_t buf[32]; + uint64_t h[4]; + uint64_t t0; + uint64_t t1; +}; + +#define SKEIN256_CTX_SIZE sizeof(struct skein256_ctx) + +void cryponite_skein256_init(struct skein256_ctx *ctx, uint32_t hashlen); +void cryponite_skein256_update(struct skein256_ctx *ctx, uint8_t *data, uint32_t len); +void cryponite_skein256_finalize(struct skein256_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_skein512.c b/cbits/cryptonite_skein512.c new file mode 100644 index 0000000..3c84dca --- /dev/null +++ b/cbits/cryptonite_skein512.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2006-2010 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_skein.h" +#include "cryptonite_skein512.h" +#include "cryptonite_bitfn.h" + +static const uint8_t K512_0[4] = { 46, 36, 19, 37, }; +static const uint8_t K512_1[4] = { 33, 27, 14, 42, }; +static const uint8_t K512_2[4] = { 17, 49, 36, 39, }; +static const uint8_t K512_3[4] = { 44, 9, 54, 56, }; +static const uint8_t K512_4[4] = { 39, 30, 34, 24, }; +static const uint8_t K512_5[4] = { 13, 50, 10, 17, }; +static const uint8_t K512_6[4] = { 25, 29, 39, 43, }; +static const uint8_t K512_7[4] = { 8, 35, 56, 22, }; + +static inline void skein512_do_chunk(struct skein512_ctx *ctx, uint64_t *buf, uint32_t len) +{ + uint64_t x[8]; + uint64_t ts[3]; + uint64_t ks[8+1]; + + ks[8] = 0x1bd11bdaa9fc1a22ULL; + ks[0] = ctx->h[0]; ks[8] ^= ctx->h[0]; + ks[1] = ctx->h[1]; ks[8] ^= ctx->h[1]; + ks[2] = ctx->h[2]; ks[8] ^= ctx->h[2]; + ks[3] = ctx->h[3]; ks[8] ^= ctx->h[3]; + ks[4] = ctx->h[4]; ks[8] ^= ctx->h[4]; + ks[5] = ctx->h[5]; ks[8] ^= ctx->h[5]; + ks[6] = ctx->h[6]; ks[8] ^= ctx->h[6]; + ks[7] = ctx->h[7]; ks[8] ^= ctx->h[7]; + + ts[0] = ctx->t0; + ts[1] = ctx->t1; + + ts[0] += len; + + ts[2] = ts[0] ^ ts[1]; + +#define INJECTKEY(r) \ + x[0] += ks[((r)+0) % (8+1)]; \ + x[1] += ks[((r)+1) % (8+1)]; \ + x[2] += ks[((r)+2) % (8+1)]; \ + x[3] += ks[((r)+3) % (8+1)]; \ + x[4] += ks[((r)+4) % (8+1)]; \ + x[5] += ks[((r)+5) % (8+1)] + ts[((r)+0) % 3]; \ + x[6] += ks[((r)+6) % (8+1)] + ts[((r)+1) % 3]; \ + x[7] += ks[((r)+7) % (8+1)] + (r) + +#define ROUND(a,b,c,d,e,f,g,h,k) \ + x[a] += x[b]; x[b] = rol64(x[b],k[0]); x[b] ^= x[a]; \ + x[c] += x[d]; x[d] = rol64(x[d],k[1]); x[d] ^= x[c]; \ + x[e] += x[f]; x[f] = rol64(x[f],k[2]); x[f] ^= x[e]; \ + x[g] += x[h]; x[h] = rol64(x[h],k[3]); x[h] ^= x[g]; + +#define PASS(i) \ + ROUND(0,1,2,3,4,5,6,7,K512_0); \ + ROUND(2,1,4,7,6,5,0,3,K512_1); \ + ROUND(4,1,6,3,0,5,2,7,K512_2); \ + ROUND(6,1,0,7,2,5,4,3,K512_3); \ + INJECTKEY((i*2) + 1); \ + ROUND(0,1,2,3,4,5,6,7,K512_4); \ + ROUND(2,1,4,7,6,5,0,3,K512_5); \ + ROUND(4,1,6,3,0,5,2,7,K512_6); \ + ROUND(6,1,0,7,2,5,4,3,K512_7); \ + INJECTKEY((i*2) + 2) + + x[0] = le64_to_cpu(buf[0]) + ks[0]; + x[1] = le64_to_cpu(buf[1]) + ks[1]; + x[2] = le64_to_cpu(buf[2]) + ks[2]; + x[3] = le64_to_cpu(buf[3]) + ks[3]; + x[4] = le64_to_cpu(buf[4]) + ks[4]; + x[5] = le64_to_cpu(buf[5]) + ks[5] + ts[0]; + x[6] = le64_to_cpu(buf[6]) + ks[6] + ts[1]; + x[7] = le64_to_cpu(buf[7]) + ks[7]; + + /* 9 pass of 8 rounds = 72 rounds */ + PASS(0); + PASS(1); + PASS(2); + PASS(3); + PASS(4); + PASS(5); + PASS(6); + PASS(7); + PASS(8); + + ts[1] &= ~FLAG_FIRST; + ctx->t0 = ts[0]; + ctx->t1 = ts[1]; + + ctx->h[0] = x[0] ^ cpu_to_le64(buf[0]); + ctx->h[1] = x[1] ^ cpu_to_le64(buf[1]); + ctx->h[2] = x[2] ^ cpu_to_le64(buf[2]); + ctx->h[3] = x[3] ^ cpu_to_le64(buf[3]); + ctx->h[4] = x[4] ^ cpu_to_le64(buf[4]); + ctx->h[5] = x[5] ^ cpu_to_le64(buf[5]); + ctx->h[6] = x[6] ^ cpu_to_le64(buf[6]); + ctx->h[7] = x[7] ^ cpu_to_le64(buf[7]); +} + +void cryptonite_skein512_init(struct skein512_ctx *ctx, uint32_t hashlen) +{ + uint64_t buf[8]; + memset(ctx, 0, sizeof(*ctx)); + + ctx->hashlen = (hashlen + 7) >> 3; + SET_TYPE(ctx, FLAG_FIRST | FLAG_FINAL | FLAG_TYPE(TYPE_CFG)); + + memset(buf, '\0', sizeof(buf)); + buf[0] = cpu_to_le64((SKEIN_VERSION << 32) | SKEIN_IDSTRING); + buf[1] = cpu_to_le64(hashlen); + buf[2] = 0; /* tree info, not implemented */ + skein512_do_chunk(ctx, buf, 4*8); + + SET_TYPE(ctx, FLAG_FIRST | FLAG_TYPE(TYPE_MSG)); +} + +void cryptonite_skein512_update(struct skein512_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t to_fill; + + if (!len) + return; + + to_fill = 64 - ctx->bufindex; + + if (ctx->bufindex == 64) { + skein512_do_chunk(ctx, (uint64_t *) ctx->buf, 64); + ctx->bufindex = 0; + } + + /* process partial buffer if there's enough data to make a block + * and there's without doubt further blocks */ + if (ctx->bufindex && len > to_fill) { + memcpy(ctx->buf + ctx->bufindex, data, to_fill); + skein512_do_chunk(ctx, (uint64_t *) ctx->buf, 64); + len -= to_fill; + data += to_fill; + ctx->bufindex = 0; + } + + /* process as much 64-block as possible except the last one in case we finalize */ + for (; len > 64; len -= 64, data += 64) + skein512_do_chunk(ctx, (uint64_t *) data, 64); + + /* append data into buf */ + if (len) { + memcpy(ctx->buf + ctx->bufindex, data, len); + ctx->bufindex += len; + } +} + +void cryptonite_skein512_finalize(struct skein512_ctx *ctx, uint8_t *out) +{ + uint32_t outsize; + uint64_t *p = (uint64_t *) out; + uint64_t x[8]; + int i, j, n; + + ctx->t1 |= FLAG_FINAL; + /* if buf is not complete pad with 0 bytes */ + if (ctx->bufindex < 64) + memset(ctx->buf + ctx->bufindex, '\0', 64 - ctx->bufindex); + skein512_do_chunk(ctx, (uint64_t *) ctx->buf, ctx->bufindex); + + memset(ctx->buf, '\0', 64); + + /* make sure we have a 8 bit rounded value */ + outsize = ctx->hashlen; + + /* backup h[0--7] */ + for (j = 0; j < 8; j++) + x[j] = ctx->h[j]; + /* threefish in counter mode, 0 for 1st 64 bytes, 1 for 2nd 64 bytes, .. */ + for (i = 0; i*64 < outsize; i++) { + uint64_t w[8]; + *((uint64_t *) ctx->buf) = cpu_to_le64(i); + SET_TYPE(ctx, FLAG_FIRST | FLAG_FINAL | FLAG_TYPE(TYPE_OUT)); + skein512_do_chunk(ctx, (uint64_t *) ctx->buf, sizeof(uint64_t)); + + n = outsize - i * 64; + if (n >= 64) n = 64; + + cpu_to_le64_array(w, ctx->h, 8); + memcpy(out + i*64, w, n); + + /* restore h[0--7] */ + for (j = 0; j < 8; j++) + ctx->h[j] = x[j]; + } +} diff --git a/cbits/cryptonite_skein512.h b/cbits/cryptonite_skein512.h new file mode 100644 index 0000000..7ec2866 --- /dev/null +++ b/cbits/cryptonite_skein512.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2006-2010 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_SKEIN512_H +#define CRYPTOHASH_SKEIN512_H + +#include + +struct skein512_ctx +{ + uint32_t hashlen; /* in bytes, typically 384/8, 512/8 */ + uint32_t bufindex; + uint8_t buf[64]; + uint64_t h[8]; + uint64_t t0; + uint64_t t1; +}; + +#define SKEIN512_CTX_SIZE sizeof(struct skein512_ctx) + +void cryponite_skein512_init(struct skein512_ctx *ctx, uint32_t hashlen); +void cryponite_skein512_update(struct skein512_ctx *ctx, uint8_t *data, uint32_t len); +void cryponite_skein512_finalize(struct skein512_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_tiger.c b/cbits/cryptonite_tiger.c new file mode 100644 index 0000000..cc968a9 --- /dev/null +++ b/cbits/cryptonite_tiger.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "cryptonite_tiger.h" +#include "cryptonite_bitfn.h" + +static const uint64_t t1[256] = { + 0x02aab17cf7e90c5eULL,0xac424b03e243a8ecULL,0x72cd5be30dd5fcd3ULL,0x6d019b93f6f97f3aULL, + 0xcd9978ffd21f9193ULL,0x7573a1c9708029e2ULL,0xb164326b922a83c3ULL,0x46883eee04915870ULL, + 0xeaace3057103ece6ULL,0xc54169b808a3535cULL,0x4ce754918ddec47cULL,0x0aa2f4dfdc0df40cULL, + 0x10b76f18a74dbefaULL,0xc6ccb6235ad1ab6aULL,0x13726121572fe2ffULL,0x1a488c6f199d921eULL, + 0x4bc9f9f4da0007caULL,0x26f5e6f6e85241c7ULL,0x859079dbea5947b6ULL,0x4f1885c5c99e8c92ULL, + 0xd78e761ea96f864bULL,0x8e36428c52b5c17dULL,0x69cf6827373063c1ULL,0xb607c93d9bb4c56eULL, + 0x7d820e760e76b5eaULL,0x645c9cc6f07fdc42ULL,0xbf38a078243342e0ULL,0x5f6b343c9d2e7d04ULL, + 0xf2c28aeb600b0ec6ULL,0x6c0ed85f7254bcacULL,0x71592281a4db4fe5ULL,0x1967fa69ce0fed9fULL, + 0xfd5293f8b96545dbULL,0xc879e9d7f2a7600bULL,0x860248920193194eULL,0xa4f9533b2d9cc0b3ULL, + 0x9053836c15957613ULL,0xdb6dcf8afc357bf1ULL,0x18beea7a7a370f57ULL,0x037117ca50b99066ULL, + 0x6ab30a9774424a35ULL,0xf4e92f02e325249bULL,0x7739db07061ccae1ULL,0xd8f3b49ceca42a05ULL, + 0xbd56be3f51382f73ULL,0x45faed5843b0bb28ULL,0x1c813d5c11bf1f83ULL,0x8af0e4b6d75fa169ULL, + 0x33ee18a487ad9999ULL,0x3c26e8eab1c94410ULL,0xb510102bc0a822f9ULL,0x141eef310ce6123bULL, + 0xfc65b90059ddb154ULL,0xe0158640c5e0e607ULL,0x884e079826c3a3cfULL,0x930d0d9523c535fdULL, + 0x35638d754e9a2b00ULL,0x4085fccf40469dd5ULL,0xc4b17ad28be23a4cULL,0xcab2f0fc6a3e6a2eULL, + 0x2860971a6b943fcdULL,0x3dde6ee212e30446ULL,0x6222f32ae01765aeULL,0x5d550bb5478308feULL, + 0xa9efa98da0eda22aULL,0xc351a71686c40da7ULL,0x1105586d9c867c84ULL,0xdcffee85fda22853ULL, + 0xccfbd0262c5eef76ULL,0xbaf294cb8990d201ULL,0xe69464f52afad975ULL,0x94b013afdf133e14ULL, + 0x06a7d1a32823c958ULL,0x6f95fe5130f61119ULL,0xd92ab34e462c06c0ULL,0xed7bde33887c71d2ULL, + 0x79746d6e6518393eULL,0x5ba419385d713329ULL,0x7c1ba6b948a97564ULL,0x31987c197bfdac67ULL, + 0xde6c23c44b053d02ULL,0x581c49fed002d64dULL,0xdd474d6338261571ULL,0xaa4546c3e473d062ULL, + 0x928fce349455f860ULL,0x48161bbacaab94d9ULL,0x63912430770e6f68ULL,0x6ec8a5e602c6641cULL, + 0x87282515337ddd2bULL,0x2cda6b42034b701bULL,0xb03d37c181cb096dULL,0xe108438266c71c6fULL, + 0x2b3180c7eb51b255ULL,0xdf92b82f96c08bbcULL,0x5c68c8c0a632f3baULL,0x5504cc861c3d0556ULL, + 0xabbfa4e55fb26b8fULL,0x41848b0ab3baceb4ULL,0xb334a273aa445d32ULL,0xbca696f0a85ad881ULL, + 0x24f6ec65b528d56cULL,0x0ce1512e90f4524aULL,0x4e9dd79d5506d35aULL,0x258905fac6ce9779ULL, + 0x2019295b3e109b33ULL,0xf8a9478b73a054ccULL,0x2924f2f934417eb0ULL,0x3993357d536d1bc4ULL, + 0x38a81ac21db6ff8bULL,0x47c4fbf17d6016bfULL,0x1e0faadd7667e3f5ULL,0x7abcff62938beb96ULL, + 0xa78dad948fc179c9ULL,0x8f1f98b72911e50dULL,0x61e48eae27121a91ULL,0x4d62f7ad31859808ULL, + 0xeceba345ef5ceaebULL,0xf5ceb25ebc9684ceULL,0xf633e20cb7f76221ULL,0xa32cdf06ab8293e4ULL, + 0x985a202ca5ee2ca4ULL,0xcf0b8447cc8a8fb1ULL,0x9f765244979859a3ULL,0xa8d516b1a1240017ULL, + 0x0bd7ba3ebb5dc726ULL,0xe54bca55b86adb39ULL,0x1d7a3afd6c478063ULL,0x519ec608e7669eddULL, + 0x0e5715a2d149aa23ULL,0x177d4571848ff194ULL,0xeeb55f3241014c22ULL,0x0f5e5ca13a6e2ec2ULL, + 0x8029927b75f5c361ULL,0xad139fabc3d6e436ULL,0x0d5df1a94ccf402fULL,0x3e8bd948bea5dfc8ULL, + 0xa5a0d357bd3ff77eULL,0xa2d12e251f74f645ULL,0x66fd9e525e81a082ULL,0x2e0c90ce7f687a49ULL, + 0xc2e8bcbeba973bc5ULL,0x000001bce509745fULL,0x423777bbe6dab3d6ULL,0xd1661c7eaef06eb5ULL, + 0xa1781f354daacfd8ULL,0x2d11284a2b16affcULL,0xf1fc4f67fa891d1fULL,0x73ecc25dcb920adaULL, + 0xae610c22c2a12651ULL,0x96e0a810d356b78aULL,0x5a9a381f2fe7870fULL,0xd5ad62ede94e5530ULL, + 0xd225e5e8368d1427ULL,0x65977b70c7af4631ULL,0x99f889b2de39d74fULL,0x233f30bf54e1d143ULL, + 0x9a9675d3d9a63c97ULL,0x5470554ff334f9a8ULL,0x166acb744a4f5688ULL,0x70c74caab2e4aeadULL, + 0xf0d091646f294d12ULL,0x57b82a89684031d1ULL,0xefd95a5a61be0b6bULL,0x2fbd12e969f2f29aULL, + 0x9bd37013feff9fe8ULL,0x3f9b0404d6085a06ULL,0x4940c1f3166cfe15ULL,0x09542c4dcdf3defbULL, + 0xb4c5218385cd5ce3ULL,0xc935b7dc4462a641ULL,0x3417f8a68ed3b63fULL,0xb80959295b215b40ULL, + 0xf99cdaef3b8c8572ULL,0x018c0614f8fcb95dULL,0x1b14accd1a3acdf3ULL,0x84d471f200bb732dULL, + 0xc1a3110e95e8da16ULL,0x430a7220bf1a82b8ULL,0xb77e090d39df210eULL,0x5ef4bd9f3cd05e9dULL, + 0x9d4ff6da7e57a444ULL,0xda1d60e183d4a5f8ULL,0xb287c38417998e47ULL,0xfe3edc121bb31886ULL, + 0xc7fe3ccc980ccbefULL,0xe46fb590189bfd03ULL,0x3732fd469a4c57dcULL,0x7ef700a07cf1ad65ULL, + 0x59c64468a31d8859ULL,0x762fb0b4d45b61f6ULL,0x155baed099047718ULL,0x68755e4c3d50baa6ULL, + 0xe9214e7f22d8b4dfULL,0x2addbf532eac95f4ULL,0x32ae3909b4bd0109ULL,0x834df537b08e3450ULL, + 0xfa209da84220728dULL,0x9e691d9b9efe23f7ULL,0x0446d288c4ae8d7fULL,0x7b4cc524e169785bULL, + 0x21d87f0135ca1385ULL,0xcebb400f137b8aa5ULL,0x272e2b66580796beULL,0x3612264125c2b0deULL, + 0x057702bdad1efbb2ULL,0xd4babb8eacf84be9ULL,0x91583139641bc67bULL,0x8bdc2de08036e024ULL, + 0x603c8156f49f68edULL,0xf7d236f7dbef5111ULL,0x9727c4598ad21e80ULL,0xa08a0896670a5fd7ULL, + 0xcb4a8f4309eba9cbULL,0x81af564b0f7036a1ULL,0xc0b99aa778199abdULL,0x959f1ec83fc8e952ULL, + 0x8c505077794a81b9ULL,0x3acaaf8f056338f0ULL,0x07b43f50627a6778ULL,0x4a44ab49f5eccc77ULL, + 0x3bc3d6e4b679ee98ULL,0x9cc0d4d1cf14108cULL,0x4406c00b206bc8a0ULL,0x82a18854c8d72d89ULL, + 0x67e366b35c3c432cULL,0xb923dd61102b37f2ULL,0x56ab2779d884271dULL,0xbe83e1b0ff1525afULL, + 0xfb7c65d4217e49a9ULL,0x6bdbe0e76d48e7d4ULL,0x08df828745d9179eULL,0x22ea6a9add53bd34ULL, + 0xe36e141c5622200aULL,0x7f805d1b8cb750eeULL,0xafe5c7a59f58e837ULL,0xe27f996a4fb1c23cULL, + 0xd3867dfb0775f0d0ULL,0xd0e673de6e88891aULL,0x123aeb9eafb86c25ULL,0x30f1d5d5c145b895ULL, + 0xbb434a2dee7269e7ULL,0x78cb67ecf931fa38ULL,0xf33b0372323bbf9cULL,0x52d66336fb279c74ULL, + 0x505f33ac0afb4eaaULL,0xe8a5cd99a2cce187ULL,0x534974801e2d30bbULL,0x8d2d5711d5876d90ULL, + 0x1f1a412891bc038eULL,0xd6e2e71d82e56648ULL,0x74036c3a497732b7ULL,0x89b67ed96361f5abULL, + 0xffed95d8f1ea02a2ULL,0xe72b3bd61464d43dULL,0xa6300f170bdc4820ULL,0xebc18760ed78a77aULL, +}; + +static const uint64_t t2[256] = +{ + 0xe6a6be5a05a12138ULL,0xb5a122a5b4f87c98ULL,0x563c6089140b6990ULL,0x4c46cb2e391f5dd5ULL, + 0xd932addbc9b79434ULL,0x08ea70e42015aff5ULL,0xd765a6673e478cf1ULL,0xc4fb757eab278d99ULL, + 0xdf11c6862d6e0692ULL,0xddeb84f10d7f3b16ULL,0x6f2ef604a665ea04ULL,0x4a8e0f0ff0e0dfb3ULL, + 0xa5edeef83dbcba51ULL,0xfc4f0a2a0ea4371eULL,0xe83e1da85cb38429ULL,0xdc8ff882ba1b1ce2ULL, + 0xcd45505e8353e80dULL,0x18d19a00d4db0717ULL,0x34a0cfeda5f38101ULL,0x0be77e518887caf2ULL, + 0x1e341438b3c45136ULL,0xe05797f49089ccf9ULL,0xffd23f9df2591d14ULL,0x543dda228595c5cdULL, + 0x661f81fd99052a33ULL,0x8736e641db0f7b76ULL,0x15227725418e5307ULL,0xe25f7f46162eb2faULL, + 0x48a8b2126c13d9feULL,0xafdc541792e76eeaULL,0x03d912bfc6d1898fULL,0x31b1aafa1b83f51bULL, + 0xf1ac2796e42ab7d9ULL,0x40a3a7d7fcd2ebacULL,0x1056136d0afbbcc5ULL,0x7889e1dd9a6d0c85ULL, + 0xd33525782a7974aaULL,0xa7e25d09078ac09bULL,0xbd4138b3eac6edd0ULL,0x920abfbe71eb9e70ULL, + 0xa2a5d0f54fc2625cULL,0xc054e36b0b1290a3ULL,0xf6dd59ff62fe932bULL,0x3537354511a8ac7dULL, + 0xca845e9172fadcd4ULL,0x84f82b60329d20dcULL,0x79c62ce1cd672f18ULL,0x8b09a2add124642cULL, + 0xd0c1e96a19d9e726ULL,0x5a786a9b4ba9500cULL,0x0e020336634c43f3ULL,0xc17b474aeb66d822ULL, + 0x6a731ae3ec9baac2ULL,0x8226667ae0840258ULL,0x67d4567691caeca5ULL,0x1d94155c4875adb5ULL, + 0x6d00fd985b813fdfULL,0x51286efcb774cd06ULL,0x5e8834471fa744afULL,0xf72ca0aee761ae2eULL, + 0xbe40e4cdaee8e09aULL,0xe9970bbb5118f665ULL,0x726e4beb33df1964ULL,0x703b000729199762ULL, + 0x4631d816f5ef30a7ULL,0xb880b5b51504a6beULL,0x641793c37ed84b6cULL,0x7b21ed77f6e97d96ULL, + 0x776306312ef96b73ULL,0xae528948e86ff3f4ULL,0x53dbd7f286a3f8f8ULL,0x16cadce74cfc1063ULL, + 0x005c19bdfa52c6ddULL,0x68868f5d64d46ad3ULL,0x3a9d512ccf1e186aULL,0x367e62c2385660aeULL, + 0xe359e7ea77dcb1d7ULL,0x526c0773749abe6eULL,0x735ae5f9d09f734bULL,0x493fc7cc8a558ba8ULL, + 0xb0b9c1533041ab45ULL,0x321958ba470a59bdULL,0x852db00b5f46c393ULL,0x91209b2bd336b0e5ULL, + 0x6e604f7d659ef19fULL,0xb99a8ae2782ccb24ULL,0xccf52ab6c814c4c7ULL,0x4727d9afbe11727bULL, + 0x7e950d0c0121b34dULL,0x756f435670ad471fULL,0xf5add442615a6849ULL,0x4e87e09980b9957aULL, + 0x2acfa1df50aee355ULL,0xd898263afd2fd556ULL,0xc8f4924dd80c8fd6ULL,0xcf99ca3d754a173aULL, + 0xfe477bacaf91bf3cULL,0xed5371f6d690c12dULL,0x831a5c285e687094ULL,0xc5d3c90a3708a0a4ULL, + 0x0f7f903717d06580ULL,0x19f9bb13b8fdf27fULL,0xb1bd6f1b4d502843ULL,0x1c761ba38fff4012ULL, + 0x0d1530c4e2e21f3bULL,0x8943ce69a7372c8aULL,0xe5184e11feb5ce66ULL,0x618bdb80bd736621ULL, + 0x7d29bad68b574d0bULL,0x81bb613e25e6fe5bULL,0x071c9c10bc07913fULL,0xc7beeb7909ac2d97ULL, + 0xc3e58d353bc5d757ULL,0xeb017892f38f61e8ULL,0xd4effb9c9b1cc21aULL,0x99727d26f494f7abULL, + 0xa3e063a2956b3e03ULL,0x9d4a8b9a4aa09c30ULL,0x3f6ab7d500090fb4ULL,0x9cc0f2a057268ac0ULL, + 0x3dee9d2dedbf42d1ULL,0x330f49c87960a972ULL,0xc6b2720287421b41ULL,0x0ac59ec07c00369cULL, + 0xef4eac49cb353425ULL,0xf450244eef0129d8ULL,0x8acc46e5caf4deb6ULL,0x2ffeab63989263f7ULL, + 0x8f7cb9fe5d7a4578ULL,0x5bd8f7644e634635ULL,0x427a7315bf2dc900ULL,0x17d0c4aa2125261cULL, + 0x3992486c93518e50ULL,0xb4cbfee0a2d7d4c3ULL,0x7c75d6202c5ddd8dULL,0xdbc295d8e35b6c61ULL, + 0x60b369d302032b19ULL,0xce42685fdce44132ULL,0x06f3ddb9ddf65610ULL,0x8ea4d21db5e148f0ULL, + 0x20b0fce62fcd496fULL,0x2c1b912358b0ee31ULL,0xb28317b818f5a308ULL,0xa89c1e189ca6d2cfULL, + 0x0c6b18576aaadbc8ULL,0xb65deaa91299fae3ULL,0xfb2b794b7f1027e7ULL,0x04e4317f443b5bebULL, + 0x4b852d325939d0a6ULL,0xd5ae6beefb207ffcULL,0x309682b281c7d374ULL,0xbae309a194c3b475ULL, + 0x8cc3f97b13b49f05ULL,0x98a9422ff8293967ULL,0x244b16b01076ff7cULL,0xf8bf571c663d67eeULL, + 0x1f0d6758eee30da1ULL,0xc9b611d97adeb9b7ULL,0xb7afd5887b6c57a2ULL,0x6290ae846b984fe1ULL, + 0x94df4cdeacc1a5fdULL,0x058a5bd1c5483affULL,0x63166cc142ba3c37ULL,0x8db8526eb2f76f40ULL, + 0xe10880036f0d6d4eULL,0x9e0523c9971d311dULL,0x45ec2824cc7cd691ULL,0x575b8359e62382c9ULL, + 0xfa9e400dc4889995ULL,0xd1823ecb45721568ULL,0xdafd983b8206082fULL,0xaa7d29082386a8cbULL, + 0x269fcd4403b87588ULL,0x1b91f5f728bdd1e0ULL,0xe4669f39040201f6ULL,0x7a1d7c218cf04adeULL, + 0x65623c29d79ce5ceULL,0x2368449096c00bb1ULL,0xab9bf1879da503baULL,0xbc23ecb1a458058eULL, + 0x9a58df01bb401eccULL,0xa070e868a85f143dULL,0x4ff188307df2239eULL,0x14d565b41a641183ULL, + 0xee13337452701602ULL,0x950e3dcf3f285e09ULL,0x59930254b9c80953ULL,0x3bf299408930da6dULL, + 0xa955943f53691387ULL,0xa15edecaa9cb8784ULL,0x29142127352be9a0ULL,0x76f0371fff4e7afbULL, + 0x0239f450274f2228ULL,0xbb073af01d5e868bULL,0xbfc80571c10e96c1ULL,0xd267088568222e23ULL, + 0x9671a3d48e80b5b0ULL,0x55b5d38ae193bb81ULL,0x693ae2d0a18b04b8ULL,0x5c48b4ecadd5335fULL, + 0xfd743b194916a1caULL,0x2577018134be98c4ULL,0xe77987e83c54a4adULL,0x28e11014da33e1b9ULL, + 0x270cc59e226aa213ULL,0x71495f756d1a5f60ULL,0x9be853fb60afef77ULL,0xadc786a7f7443dbfULL, + 0x0904456173b29a82ULL,0x58bc7a66c232bd5eULL,0xf306558c673ac8b2ULL,0x41f639c6b6c9772aULL, + 0x216defe99fda35daULL,0x11640cc71c7be615ULL,0x93c43694565c5527ULL,0xea038e6246777839ULL, + 0xf9abf3ce5a3e2469ULL,0x741e768d0fd312d2ULL,0x0144b883ced652c6ULL,0xc20b5a5ba33f8552ULL, + 0x1ae69633c3435a9dULL,0x97a28ca4088cfdecULL,0x8824a43c1e96f420ULL,0x37612fa66eeea746ULL, + 0x6b4cb165f9cf0e5aULL,0x43aa1c06a0abfb4aULL,0x7f4dc26ff162796bULL,0x6cbacc8e54ed9b0fULL, + 0xa6b7ffefd2bb253eULL,0x2e25bc95b0a29d4fULL,0x86d6a58bdef1388cULL,0xded74ac576b6f054ULL, + 0x8030bdbc2b45805dULL,0x3c81af70e94d9289ULL,0x3eff6dda9e3100dbULL,0xb38dc39fdfcc8847ULL, + 0x123885528d17b87eULL,0xf2da0ed240b1b642ULL,0x44cefadcd54bf9a9ULL,0x1312200e433c7ee6ULL, + 0x9ffcc84f3a78c748ULL,0xf0cd1f72248576bbULL,0xec6974053638cfe4ULL,0x2ba7b67c0cec4e4cULL, + 0xac2f4df3e5ce32edULL,0xcb33d14326ea4c11ULL,0xa4e9044cc77e58bcULL,0x5f513293d934fcefULL, + 0x5dc9645506e55444ULL,0x50de418f317de40aULL,0x388cb31a69dde259ULL,0x2db4a83455820a86ULL, + 0x9010a91e84711ae9ULL,0x4df7f0b7b1498371ULL,0xd62a2eabc0977179ULL,0x22fac097aa8d5c0eULL, +}; + +static const uint64_t t3[256]= { + 0xf49fcc2ff1daf39bULL,0x487fd5c66ff29281ULL,0xe8a30667fcdca83fULL,0x2c9b4be3d2fcce63ULL, + 0xda3ff74b93fbbbc2ULL,0x2fa165d2fe70ba66ULL,0xa103e279970e93d4ULL,0xbecdec77b0e45e71ULL, + 0xcfb41e723985e497ULL,0xb70aaa025ef75017ULL,0xd42309f03840b8e0ULL,0x8efc1ad035898579ULL, + 0x96c6920be2b2abc5ULL,0x66af4163375a9172ULL,0x2174abdcca7127fbULL,0xb33ccea64a72ff41ULL, + 0xf04a4933083066a5ULL,0x8d970acdd7289af5ULL,0x8f96e8e031c8c25eULL,0xf3fec02276875d47ULL, + 0xec7bf310056190ddULL,0xf5adb0aebb0f1491ULL,0x9b50f8850fd58892ULL,0x4975488358b74de8ULL, + 0xa3354ff691531c61ULL,0x0702bbe481d2c6eeULL,0x89fb24057deded98ULL,0xac3075138596e902ULL, + 0x1d2d3580172772edULL,0xeb738fc28e6bc30dULL,0x5854ef8f63044326ULL,0x9e5c52325add3bbeULL, + 0x90aa53cf325c4623ULL,0xc1d24d51349dd067ULL,0x2051cfeea69ea624ULL,0x13220f0a862e7e4fULL, + 0xce39399404e04864ULL,0xd9c42ca47086fcb7ULL,0x685ad2238a03e7ccULL,0x066484b2ab2ff1dbULL, + 0xfe9d5d70efbf79ecULL,0x5b13b9dd9c481854ULL,0x15f0d475ed1509adULL,0x0bebcd060ec79851ULL, + 0xd58c6791183ab7f8ULL,0xd1187c5052f3eee4ULL,0xc95d1192e54e82ffULL,0x86eea14cb9ac6ca2ULL, + 0x3485beb153677d5dULL,0xdd191d781f8c492aULL,0xf60866baa784ebf9ULL,0x518f643ba2d08c74ULL, + 0x8852e956e1087c22ULL,0xa768cb8dc410ae8dULL,0x38047726bfec8e1aULL,0xa67738b4cd3b45aaULL, + 0xad16691cec0dde19ULL,0xc6d4319380462e07ULL,0xc5a5876d0ba61938ULL,0x16b9fa1fa58fd840ULL, + 0x188ab1173ca74f18ULL,0xabda2f98c99c021fULL,0x3e0580ab134ae816ULL,0x5f3b05b773645abbULL, + 0x2501a2be5575f2f6ULL,0x1b2f74004e7e8ba9ULL,0x1cd7580371e8d953ULL,0x7f6ed89562764e30ULL, + 0xb15926ff596f003dULL,0x9f65293da8c5d6b9ULL,0x6ecef04dd690f84cULL,0x4782275fff33af88ULL, + 0xe41433083f820801ULL,0xfd0dfe409a1af9b5ULL,0x4325a3342cdb396bULL,0x8ae77e62b301b252ULL, + 0xc36f9e9f6655615aULL,0x85455a2d92d32c09ULL,0xf2c7dea949477485ULL,0x63cfb4c133a39ebaULL, + 0x83b040cc6ebc5462ULL,0x3b9454c8fdb326b0ULL,0x56f56a9e87ffd78cULL,0x2dc2940d99f42bc6ULL, + 0x98f7df096b096e2dULL,0x19a6e01e3ad852bfULL,0x42a99ccbdbd4b40bULL,0xa59998af45e9c559ULL, + 0x366295e807d93186ULL,0x6b48181bfaa1f773ULL,0x1fec57e2157a0a1dULL,0x4667446af6201ad5ULL, + 0xe615ebcacfb0f075ULL,0xb8f31f4f68290778ULL,0x22713ed6ce22d11eULL,0x3057c1a72ec3c93bULL, + 0xcb46acc37c3f1f2fULL,0xdbb893fd02aaf50eULL,0x331fd92e600b9fcfULL,0xa498f96148ea3ad6ULL, + 0xa8d8426e8b6a83eaULL,0xa089b274b7735cdcULL,0x87f6b3731e524a11ULL,0x118808e5cbc96749ULL, + 0x9906e4c7b19bd394ULL,0xafed7f7e9b24a20cULL,0x6509eadeeb3644a7ULL,0x6c1ef1d3e8ef0edeULL, + 0xb9c97d43e9798fb4ULL,0xa2f2d784740c28a3ULL,0x7b8496476197566fULL,0x7a5be3e6b65f069dULL, + 0xf96330ed78be6f10ULL,0xeee60de77a076a15ULL,0x2b4bee4aa08b9bd0ULL,0x6a56a63ec7b8894eULL, + 0x02121359ba34fef4ULL,0x4cbf99f8283703fcULL,0x398071350caf30c8ULL,0xd0a77a89f017687aULL, + 0xf1c1a9eb9e423569ULL,0x8c7976282dee8199ULL,0x5d1737a5dd1f7abdULL,0x4f53433c09a9fa80ULL, + 0xfa8b0c53df7ca1d9ULL,0x3fd9dcbc886ccb77ULL,0xc040917ca91b4720ULL,0x7dd00142f9d1dcdfULL, + 0x8476fc1d4f387b58ULL,0x23f8e7c5f3316503ULL,0x032a2244e7e37339ULL,0x5c87a5d750f5a74bULL, + 0x082b4cc43698992eULL,0xdf917becb858f63cULL,0x3270b8fc5bf86ddaULL,0x10ae72bb29b5dd76ULL, + 0x576ac94e7700362bULL,0x1ad112dac61efb8fULL,0x691bc30ec5faa427ULL,0xff246311cc327143ULL, + 0x3142368e30e53206ULL,0x71380e31e02ca396ULL,0x958d5c960aad76f1ULL,0xf8d6f430c16da536ULL, + 0xc8ffd13f1be7e1d2ULL,0x7578ae66004ddbe1ULL,0x05833f01067be646ULL,0xbb34b5ad3bfe586dULL, + 0x095f34c9a12b97f0ULL,0x247ab64525d60ca8ULL,0xdcdbc6f3017477d1ULL,0x4a2e14d4decad24dULL, + 0xbdb5e6d9be0a1eebULL,0x2a7e70f7794301abULL,0xdef42d8a270540fdULL,0x01078ec0a34c22c1ULL, + 0xe5de511af4c16387ULL,0x7ebb3a52bd9a330aULL,0x77697857aa7d6435ULL,0x004e831603ae4c32ULL, + 0xe7a21020ad78e312ULL,0x9d41a70c6ab420f2ULL,0x28e06c18ea1141e6ULL,0xd2b28cbd984f6b28ULL, + 0x26b75f6c446e9d83ULL,0xba47568c4d418d7fULL,0xd80badbfe6183d8eULL,0x0e206d7f5f166044ULL, + 0xe258a43911cbca3eULL,0x723a1746b21dc0bcULL,0xc7caa854f5d7cdd3ULL,0x7cac32883d261d9cULL, + 0x7690c26423ba942cULL,0x17e55524478042b8ULL,0xe0be477656a2389fULL,0x4d289b5e67ab2da0ULL, + 0x44862b9c8fbbfd31ULL,0xb47cc8049d141365ULL,0x822c1b362b91c793ULL,0x4eb14655fb13dfd8ULL, + 0x1ecbba0714e2a97bULL,0x6143459d5cde5f14ULL,0x53a8fbf1d5f0ac89ULL,0x97ea04d81c5e5b00ULL, + 0x622181a8d4fdb3f3ULL,0xe9bcd341572a1208ULL,0x1411258643cce58aULL,0x9144c5fea4c6e0a4ULL, + 0x0d33d06565cf620fULL,0x54a48d489f219ca1ULL,0xc43e5eac6d63c821ULL,0xa9728b3a72770dafULL, + 0xd7934e7b20df87efULL,0xe35503b61a3e86e5ULL,0xcae321fbc819d504ULL,0x129a50b3ac60bfa6ULL, + 0xcd5e68ea7e9fb6c3ULL,0xb01c90199483b1c7ULL,0x3de93cd5c295376cULL,0xaed52edf2ab9ad13ULL, + 0x2e60f512c0a07884ULL,0xbc3d86a3e36210c9ULL,0x35269d9b163951ceULL,0x0c7d6e2ad0cdb5faULL, + 0x59e86297d87f5733ULL,0x298ef221898db0e7ULL,0x55000029d1a5aa7eULL,0x8bc08ae1b5061b45ULL, + 0xc2c31c2b6c92703aULL,0x94cc596baf25ef42ULL,0x0a1d73db22540456ULL,0x04b6a0f9d9c4179aULL, + 0xeffdafa2ae3d3c60ULL,0xf7c8075bb49496c4ULL,0x9cc5c7141d1cd4e3ULL,0x78bd1638218e5534ULL, + 0xb2f11568f850246aULL,0xedfabcfa9502bc29ULL,0x796ce5f2da23051bULL,0xaae128b0dc93537cULL, + 0x3a493da0ee4b29aeULL,0xb5df6b2c416895d7ULL,0xfcabbd25122d7f37ULL,0x70810b58105dc4b1ULL, + 0xe10fdd37f7882a90ULL,0x524dcab5518a3f5cULL,0x3c9e85878451255bULL,0x4029828119bd34e2ULL, + 0x74a05b6f5d3ceccbULL,0xb610021542e13ecaULL,0x0ff979d12f59e2acULL,0x6037da27e4f9cc50ULL, + 0x5e92975a0df1847dULL,0xd66de190d3e623feULL,0x5032d6b87b568048ULL,0x9a36b7ce8235216eULL, + 0x80272a7a24f64b4aULL,0x93efed8b8c6916f7ULL,0x37ddbff44cce1555ULL,0x4b95db5d4b99bd25ULL, + 0x92d3fda169812fc0ULL,0xfb1a4a9a90660bb6ULL,0x730c196946a4b9b2ULL,0x81e289aa7f49da68ULL, + 0x64669a0f83b1a05fULL,0x27b3ff7d9644f48bULL,0xcc6b615c8db675b3ULL,0x674f20b9bcebbe95ULL, + 0x6f31238275655982ULL,0x5ae488713e45cf05ULL,0xbf619f9954c21157ULL,0xeabac46040a8eae9ULL, + 0x454c6fe9f2c0c1cdULL,0x419cf6496412691cULL,0xd3dc3bef265b0f70ULL,0x6d0e60f5c3578a9eULL, +}; + +static const uint64_t t4[256]= +{ + 0x5b0e608526323c55ULL,0x1a46c1a9fa1b59f5ULL, 0xa9e245a17c4c8ffaULL,0x65ca5159db2955d7ULL, + 0x05db0a76ce35afc2ULL,0x81eac77ea9113d45ULL, 0x528ef88ab6ac0a0dULL,0xa09ea253597be3ffULL, + 0x430ddfb3ac48cd56ULL,0xc4b3a67af45ce46fULL, 0x4ececfd8fbe2d05eULL,0x3ef56f10b39935f0ULL, + 0x0b22d6829cd619c6ULL,0x17fd460a74df2069ULL, 0x6cf8cc8e8510ed40ULL,0xd6c824bf3a6ecaa7ULL, + 0x61243d581a817049ULL,0x048bacb6bbc163a2ULL, 0xd9a38ac27d44cc32ULL,0x7fddff5baaf410abULL, + 0xad6d495aa804824bULL,0xe1a6a74f2d8c9f94ULL, 0xd4f7851235dee8e3ULL,0xfd4b7f886540d893ULL, + 0x247c20042aa4bfdaULL,0x096ea1c517d1327cULL, 0xd56966b4361a6685ULL,0x277da5c31221057dULL, + 0x94d59893a43acff7ULL,0x64f0c51ccdc02281ULL, 0x3d33bcc4ff6189dbULL,0xe005cb184ce66af1ULL, + 0xff5ccd1d1db99beaULL,0xb0b854a7fe42980fULL, 0x7bd46a6a718d4b9fULL,0xd10fa8cc22a5fd8cULL, + 0xd31484952be4bd31ULL,0xc7fa975fcb243847ULL, 0x4886ed1e5846c407ULL,0x28cddb791eb70b04ULL, + 0xc2b00be2f573417fULL,0x5c9590452180f877ULL, 0x7a6bddfff370eb00ULL,0xce509e38d6d9d6a4ULL, + 0xebeb0f00647fa702ULL,0x1dcc06cf76606f06ULL, 0xe4d9f28ba286ff0aULL,0xd85a305dc918c262ULL, + 0x475b1d8732225f54ULL,0x2d4fb51668ccb5feULL, 0xa679b9d9d72bba20ULL,0x53841c0d912d43a5ULL, + 0x3b7eaa48bf12a4e8ULL,0x781e0e47f22f1ddfULL, 0xeff20ce60ab50973ULL,0x20d261d19dffb742ULL, + 0x16a12b03062a2e39ULL,0x1960eb2239650495ULL, 0x251c16fed50eb8b8ULL,0x9ac0c330f826016eULL, + 0xed152665953e7671ULL,0x02d63194a6369570ULL, 0x5074f08394b1c987ULL,0x70ba598c90b25ce1ULL, + 0x794a15810b9742f6ULL,0x0d5925e9fcaf8c6cULL, 0x3067716cd868744eULL,0x910ab077e8d7731bULL, + 0x6a61bbdb5ac42f61ULL,0x93513efbf0851567ULL, 0xf494724b9e83e9d5ULL,0xe887e1985c09648dULL, + 0x34b1d3c675370cfdULL,0xdc35e433bc0d255dULL, 0xd0aab84234131be0ULL,0x08042a50b48b7eafULL, + 0x9997c4ee44a3ab35ULL,0x829a7b49201799d0ULL, 0x263b8307b7c54441ULL,0x752f95f4fd6a6ca6ULL, + 0x927217402c08c6e5ULL,0x2a8ab754a795d9eeULL, 0xa442f7552f72943dULL,0x2c31334e19781208ULL, + 0x4fa98d7ceaee6291ULL,0x55c3862f665db309ULL, 0xbd0610175d53b1f3ULL,0x46fe6cb840413f27ULL, + 0x3fe03792df0cfa59ULL,0xcfe700372eb85e8fULL, 0xa7be29e7adbce118ULL,0xe544ee5cde8431ddULL, + 0x8a781b1b41f1873eULL,0xa5c94c78a0d2f0e7ULL, 0x39412e2877b60728ULL,0xa1265ef3afc9a62cULL, + 0xbcc2770c6a2506c5ULL,0x3ab66dd5dce1ce12ULL, 0xe65499d04a675b37ULL,0x7d8f523481bfd216ULL, + 0x0f6f64fcec15f389ULL,0x74efbe618b5b13c8ULL, 0xacdc82b714273e1dULL,0xdd40bfe003199d17ULL, + 0x37e99257e7e061f8ULL,0xfa52626904775aaaULL, 0x8bbbf63a463d56f9ULL,0xf0013f1543a26e64ULL, + 0xa8307e9f879ec898ULL,0xcc4c27a4150177ccULL, 0x1b432f2cca1d3348ULL,0xde1d1f8f9f6fa013ULL, + 0x606602a047a7ddd6ULL,0xd237ab64cc1cb2c7ULL, 0x9b938e7225fcd1d3ULL,0xec4e03708e0ff476ULL, + 0xfeb2fbda3d03c12dULL,0xae0bced2ee43889aULL, 0x22cb8923ebfb4f43ULL,0x69360d013cf7396dULL, + 0x855e3602d2d4e022ULL,0x073805bad01f784cULL, 0x33e17a133852f546ULL,0xdf4874058ac7b638ULL, + 0xba92b29c678aa14aULL,0x0ce89fc76cfaadcdULL, 0x5f9d4e0908339e34ULL,0xf1afe9291f5923b9ULL, + 0x6e3480f60f4a265fULL,0xeebf3a2ab29b841cULL, 0xe21938a88f91b4adULL,0x57dfeff845c6d3c3ULL, + 0x2f006b0bf62caaf2ULL,0x62f479ef6f75ee78ULL, 0x11a55ad41c8916a9ULL,0xf229d29084fed453ULL, + 0x42f1c27b16b000e6ULL,0x2b1f76749823c074ULL, 0x4b76eca3c2745360ULL,0x8c98f463b91691bdULL, + 0x14bcc93cf1ade66aULL,0x8885213e6d458397ULL, 0x8e177df0274d4711ULL,0xb49b73b5503f2951ULL, + 0x10168168c3f96b6bULL,0x0e3d963b63cab0aeULL, 0x8dfc4b5655a1db14ULL,0xf789f1356e14de5cULL, + 0x683e68af4e51dac1ULL,0xc9a84f9d8d4b0fd9ULL, 0x3691e03f52a0f9d1ULL,0x5ed86e46e1878e80ULL, + 0x3c711a0e99d07150ULL,0x5a0865b20c4e9310ULL, 0x56fbfc1fe4f0682eULL,0xea8d5de3105edf9bULL, + 0x71abfdb12379187aULL,0x2eb99de1bee77b9cULL, 0x21ecc0ea33cf4523ULL,0x59a4d7521805c7a1ULL, + 0x3896f5eb56ae7c72ULL,0xaa638f3db18f75dcULL, 0x9f39358dabe9808eULL,0xb7defa91c00b72acULL, + 0x6b5541fd62492d92ULL,0x6dc6dee8f92e4d5bULL, 0x353f57abc4beea7eULL,0x735769d6da5690ceULL, + 0x0a234aa642391484ULL,0xf6f9508028f80d9dULL, 0xb8e319a27ab3f215ULL,0x31ad9c1151341a4dULL, + 0x773c22a57bef5805ULL,0x45c7561a07968633ULL, 0xf913da9e249dbe36ULL,0xda652d9b78a64c68ULL, + 0x4c27a97f3bc334efULL,0x76621220e66b17f4ULL, 0x967743899acd7d0bULL,0xf3ee5bcae0ed6782ULL, + 0x409f753600c879fcULL,0x06d09a39b5926db6ULL, 0x6f83aeb0317ac588ULL,0x01e6ca4a86381f21ULL, + 0x66ff3462d19f3025ULL,0x72207c24ddfd3bfbULL, 0x4af6b6d3e2ece2ebULL,0x9c994dbec7ea08deULL, + 0x49ace597b09a8bc4ULL,0xb38c4766cf0797baULL, 0x131b9373c57c2a75ULL,0xb1822cce61931e58ULL, + 0x9d7555b909ba1c0cULL,0x127fafdd937d11d2ULL, 0x29da3badc66d92e4ULL,0xa2c1d57154c2ecbcULL, + 0x58c5134d82f6fe24ULL,0x1c3ae3515b62274fULL, 0xe907c82e01cb8126ULL,0xf8ed091913e37fcbULL, + 0x3249d8f9c80046c9ULL,0x80cf9bede388fb63ULL, 0x1881539a116cf19eULL,0x5103f3f76bd52457ULL, + 0x15b7e6f5ae47f7a8ULL,0xdbd7c6ded47e9ccfULL, 0x44e55c410228bb1aULL,0xb647d4255edb4e99ULL, + 0x5d11882bb8aafc30ULL,0xf5098bbb29d3212aULL, 0x8fb5ea14e90296b3ULL,0x677b942157dd025aULL, + 0xfb58e7c0a390acb5ULL,0x89d3674c83bd4a01ULL, 0x9e2da4df4bf3b93bULL,0xfcc41e328cab4829ULL, + 0x03f38c96ba582c52ULL,0xcad1bdbd7fd85db2ULL, 0xbbb442c16082ae83ULL,0xb95fe86ba5da9ab0ULL, + 0xb22e04673771a93fULL,0x845358c9493152d8ULL, 0xbe2a488697b4541eULL,0x95a2dc2dd38e6966ULL, + 0xc02c11ac923c852bULL,0x2388b1990df2a87bULL, 0x7c8008fa1b4f37beULL,0x1f70d0c84d54e503ULL, + 0x5490adec7ece57d4ULL,0x002b3c27d9063a3aULL, 0x7eaea3848030a2bfULL,0xc602326ded2003c0ULL, + 0x83a7287d69a94086ULL,0xc57a5fcb30f57a8aULL, 0xb56844e479ebe779ULL,0xa373b40f05dcbce9ULL, + 0xd71a786e88570ee2ULL,0x879cbacdbde8f6a0ULL, 0x976ad1bcc164a32fULL,0xab21e25e9666d78bULL, + 0x901063aae5e5c33cULL,0x9818b34448698d90ULL, 0xe36487ae3e1e8abbULL,0xafbdf931893bdcb4ULL, + 0x6345a0dc5fbbd519ULL,0x8628fe269b9465caULL, 0x1e5d01603f9c51ecULL,0x4de44006a15049b7ULL, + 0xbf6c70e5f776cbb1ULL,0x411218f2ef552bedULL, 0xcb0c0708705a36a3ULL,0xe74d14754f986044ULL, + 0xcd56d9430ea8280eULL,0xc12591d7535f5065ULL, 0xc83223f1720aef96ULL,0xc3a0396f7363a51fULL, +}; + +void cryptonite_tiger_init(struct tiger_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->h[0] = 0x0123456789abcdefULL; + ctx->h[1] = 0xfedcba9876543210ULL; + ctx->h[2] = 0xf096a5b4c3b2e187ULL; +} + +static inline void tiger_do_chunk(struct tiger_ctx *ctx, uint64_t *buf) +{ + uint64_t x0, x1, x2, x3, x4, x5, x6, x7; + uint64_t a,b,c; + a = ctx->h[0]; + b = ctx->h[1]; + c = ctx->h[2]; + + x0 = cpu_to_le64(buf[0]); x1 = cpu_to_le64(buf[1]); x2 = cpu_to_le64(buf[2]); x3 = cpu_to_le64(buf[3]); + x4 = cpu_to_le64(buf[4]); x5 = cpu_to_le64(buf[5]); x6 = cpu_to_le64(buf[6]); x7 = cpu_to_le64(buf[7]); + +#define BYTEOF(c, n) ((uint8_t) (c >> ((n * 8)))) + +#define ROUND(a,b,c,x,mul) \ + c ^= x; \ + a -= t1[BYTEOF(c,0)] ^ t2[BYTEOF(c,2)] ^ t3[BYTEOF(c,4)] ^ t4[BYTEOF(c,6)]; \ + b += t4[BYTEOF(c,1)] ^ t3[BYTEOF(c,3)] ^ t2[BYTEOF(c,5)] ^ t1[BYTEOF(c,7)]; \ + b *= mul; + +#define PASS(a,b,c,mul) \ + ROUND(a,b,c,x0,mul); \ + ROUND(b,c,a,x1,mul); \ + ROUND(c,a,b,x2,mul); \ + ROUND(a,b,c,x3,mul); \ + ROUND(b,c,a,x4,mul); \ + ROUND(c,a,b,x5,mul); \ + ROUND(a,b,c,x6,mul); \ + ROUND(b,c,a,x7,mul) + +#define SCHEDULE() \ + x0 -= x7 ^ 0xa5a5a5a5a5a5a5a5ULL; \ + x1 ^= x0; \ + x2 += x1; \ + x3 -= x2 ^ ((~x1)<<19); \ + x4 ^= x3; \ + x5 += x4; \ + x6 -= x5 ^ ((~x4)>>23); \ + x7 ^= x6; \ + x0 += x7; \ + x1 -= x0 ^ ((~x7)<<19); \ + x2 ^= x1; \ + x3 += x2; \ + x4 -= x3 ^ ((~x2)>>23); \ + x5 ^= x4; \ + x6 += x5; \ + x7 -= x6 ^ 0x0123456789abcdefULL + + PASS(a,b,c,5); + SCHEDULE(); + PASS(c,a,b,7); + SCHEDULE(); + PASS(b,c,a,9); + + ctx->h[0] ^= a; + ctx->h[1] = b - ctx->h[1]; + ctx->h[2] += c; +} + +void cryptonite_tiger_update(struct tiger_ctx *ctx, uint8_t *data, uint32_t len) +{ + uint32_t index, to_fill; + + index = (uint32_t) (ctx->sz & 0x3f); + to_fill = 64 - index; + + ctx->sz += len; + + /* process partial buffer if there's enough data to make a block */ + if (index && len >= to_fill) { + memcpy(ctx->buf + index, data, to_fill); + tiger_do_chunk(ctx, (uint64_t *) ctx->buf); + len -= to_fill; + data += to_fill; + index = 0; + } + + /* process as much 64-block as possible */ + for (; len >= 64; len -= 64, data += 64) + tiger_do_chunk(ctx, (uint64_t *) data); + + /* append data into buf */ + if (len) + memcpy(ctx->buf + index, data, len); +} + +void cryptonite_tiger_finalize(struct tiger_ctx *ctx, uint8_t *out) +{ + static uint8_t padding[64] = { 0x01, }; + uint64_t bits; + uint32_t index, padlen; + uint64_t *p = (uint64_t *) out; + + /* add padding and update data with it */ + bits = cpu_to_le64(ctx->sz << 3); + + /* pad out to 56 */ + index = (uint32_t) (ctx->sz & 0x3f); + padlen = (index < 56) ? (56 - index) : ((64 + 56) - index); + cryptonite_tiger_update(ctx, padding, padlen); + + /* append length */ + cryptonite_tiger_update(ctx, (uint8_t *) &bits, sizeof(bits)); + + /* output hash */ + p[0] = cpu_to_le64(ctx->h[0]); + p[1] = cpu_to_le64(ctx->h[1]); + p[2] = cpu_to_le64(ctx->h[2]); +} diff --git a/cbits/cryptonite_tiger.h b/cbits/cryptonite_tiger.h new file mode 100644 index 0000000..06c7d62 --- /dev/null +++ b/cbits/cryptonite_tiger.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006-2009 Vincent Hanquez + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CRYPTOHASH_TIGER_H +#define CRYPTOHASH_TIGER_H + +#include + +struct tiger_ctx +{ + uint64_t sz; + uint8_t buf[64]; + uint64_t h[3]; +}; + +#define TIGER_DIGEST_SIZE 24 +#define TIGER_CTX_SIZE (sizeof(struct tiger_ctx)) + +void cryptonite_tiger_init(struct tiger_ctx *ctx); +void cryptonite_tiger_update(struct tiger_ctx *ctx, uint8_t *data, uint32_t len); +void cryptonite_tiger_finalize(struct tiger_ctx *ctx, uint8_t *out); + +#endif diff --git a/cbits/cryptonite_whirlpool.c b/cbits/cryptonite_whirlpool.c new file mode 100644 index 0000000..c63df7e --- /dev/null +++ b/cbits/cryptonite_whirlpool.c @@ -0,0 +1,1027 @@ +/** + * The Whirlpool hashing function. + * + *

+ * References + * + *

+ * The Whirlpool algorithm was developed by + * Paulo S. L. M. Barreto and + * Vincent Rijmen. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * @author Paulo S.L.M. Barreto + * @author Vincent Rijmen. + * + * @version 3.0 (2003.03.12) + * + * ============================================================================= + * + * Differences from version 2.1: + * + * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9). + * + * ============================================================================= + * + * Differences from version 2.0: + * + * - Generation of ISO/IEC 10118-3 test vectors. + * - Bug fix: nonzero carry was ignored when tallying the data length + * (this bug apparently only manifested itself when feeding data + * in pieces rather than in a single chunk at once). + * - Support for MS Visual C++ 64-bit integer arithmetic. + * + * Differences from version 1.0: + * + * - Original S-box replaced by the tweaked, hardware-efficient version. + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* Modified by Stijn van Drongelen for use in the cryptohash library. +*/ + +#include +#include + +#include "cryptonite_bitfn.h" +#include "cryptonite_whirlpool.h" + +/* #define TRACE_INTERMEDIATE_VALUES */ + +/* + * The number of rounds of the internal dedicated block cipher. + */ +#define R 10 + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +static const uint64_t C0[256] = { + 0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL, 0xe8e887e8136fcdfbULL, + 0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL, 0x0101040108050209ULL, 0x4f4f214f426e9e0dULL, + 0x3636d836adee6c9bULL, 0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL, + 0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL, 0x52525552aa07a4f8ULL, + 0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL, 0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL, + 0xa3a3b6a371155bd2ULL, 0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL, + 0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL, 0xc2c22fc25eed999cULL, + 0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL, 0xfefedffea321e15dULL, 0x575741578216aed5ULL, + 0x15155415a8412abdULL, 0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL, + 0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL, 0xdada4fda9e95a944ULL, + 0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL, 0x2929a429558d527cULL, 0x0a0a280a5022145aULL, + 0xb1b1feb1e14f7f50ULL, 0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL, + 0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL, 0xf4f4f7f4f303f507ULL, + 0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL, 0x0505140528110a2dULL, 0x676781671fe6ce78ULL, + 0xe4e4b7e47353d597ULL, 0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL, + 0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL, 0xd8d847d88e9fad56ULL, + 0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL, 0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL, + 0xdddd53dda68ea77bULL, 0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL, + 0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL, 0x07071c07381b0e3fULL, + 0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL, 0x838336836cb51befULL, 0x3333cc3385ff66b6ULL, + 0x636391633ff2c65cULL, 0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL, + 0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL, 0xd9d943d9869aaf5fULL, + 0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL, 0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL, + 0x9a9a529aa4c8293eULL, 0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL, + 0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL, 0x80803a8074ba1df4ULL, + 0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL, 0x3434d034bde46889ULL, 0x48483d487a759032ULL, + 0xffffdbffab24e354ULL, 0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL, + 0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL, 0xaeae82ae192c41b7ULL, + 0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL, 0x93937693ece53b7fULL, 0x222288220daa442fULL, + 0x64648d6407e9c863ULL, 0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL, + 0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL, 0xecec97ec337bc5dfULL, + 0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL, 0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL, + 0x97976697ccf1335bULL, 0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL, + 0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL, 0x1b1b6c1bd87736c3ULL, + 0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL, 0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL, + 0x45450945124c8a57ULL, 0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL, + 0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL, 0xeaea8fea0365c9e9ULL, + 0x656589650fecca6aULL, 0xbabad2bab9686903ULL, 0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL, + 0xdede5fdebe81a160ULL, 0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL, + 0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL, 0x8a8a128a249809aeULL, + 0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL, 0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL, + 0x6262956237f7c455ULL, 0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL, + 0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL, 0x59597959f220b2abULL, + 0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL, 0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL, + 0x5e5e655eca3bbc94ULL, 0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL, + 0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL, 0x616199612ff8c24eULL, + 0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL, 0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL, + 0x4343114322528661ULL, 0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL, + 0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL, 0x0d0d340d68391a65ULL, + 0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL, 0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL, + 0x3b3bec3bc5d776feULL, 0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL, + 0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL, 0xebeb8beb0b60cbe0ULL, + 0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL, 0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL, + 0xb9b9deb9a1676f18ULL, 0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL, + 0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL, 0x03030c03180f061bULL, + 0x565645568a13acdcULL, 0x44440d441a49885eULL, 0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL, + 0x2a2aa82a4d825467ULL, 0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL, + 0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL, 0x6c6cad6c47c1d82bULL, + 0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL, 0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL, + 0xacac8aac092645a5ULL, 0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL, + 0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL, 0x09092409482d1241ULL, + 0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL, 0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL, + 0xcccc17cc2edb85e2ULL, 0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL, + 0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL, 0x8686228644a411c2ULL, +}; + +static const uint64_t C1[256] = { + 0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL, 0xfbe8e887e8136fcdULL, + 0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL, 0x0901010401080502ULL, 0x0d4f4f214f426e9eULL, + 0x9b3636d836adee6cULL, 0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL, + 0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL, 0xf852525552aa07a4ULL, + 0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL, 0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL, + 0xd2a3a3b6a371155bULL, 0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL, + 0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL, 0x9cc2c22fc25eed99ULL, + 0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL, 0x5dfefedffea321e1ULL, 0xd5575741578216aeULL, + 0xbd15155415a8412aULL, 0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL, + 0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL, 0x44dada4fda9e95a9ULL, + 0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL, 0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL, + 0x50b1b1feb1e14f7fULL, 0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL, + 0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL, 0x07f4f4f7f4f303f5ULL, + 0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL, 0x2d0505140528110aULL, 0x78676781671fe6ceULL, + 0x97e4e4b7e47353d5ULL, 0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL, + 0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL, 0x56d8d847d88e9fadULL, + 0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL, 0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL, + 0x7bdddd53dda68ea7ULL, 0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL, + 0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL, 0x3f07071c07381b0eULL, + 0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL, 0xef838336836cb51bULL, 0xb63333cc3385ff66ULL, + 0x5c636391633ff2c6ULL, 0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL, + 0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL, 0x5fd9d943d9869aafULL, + 0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL, 0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL, + 0x3e9a9a529aa4c829ULL, 0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL, + 0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL, 0xf480803a8074ba1dULL, + 0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL, 0x893434d034bde468ULL, 0x3248483d487a7590ULL, + 0x54ffffdbffab24e3ULL, 0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL, + 0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL, 0xb7aeae82ae192c41ULL, + 0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL, 0x7f93937693ece53bULL, 0x2f222288220daa44ULL, + 0x6364648d6407e9c8ULL, 0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL, + 0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL, 0xdfecec97ec337bc5ULL, + 0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL, 0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL, + 0x5b97976697ccf133ULL, 0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL, + 0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL, 0xc31b1b6c1bd87736ULL, + 0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL, 0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL, + 0x5745450945124c8aULL, 0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL, + 0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL, 0xe9eaea8fea0365c9ULL, + 0x6a656589650feccaULL, 0x03babad2bab96869ULL, 0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL, + 0x60dede5fdebe81a1ULL, 0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL, + 0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL, 0xae8a8a128a249809ULL, + 0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL, 0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL, + 0x556262956237f7c4ULL, 0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL, + 0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL, 0xab59597959f220b2ULL, + 0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL, 0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL, + 0x945e5e655eca3bbcULL, 0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL, + 0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL, 0x4e616199612ff8c2ULL, + 0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL, 0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL, + 0x6143431143225286ULL, 0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL, + 0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL, 0x650d0d340d68391aULL, + 0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL, 0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL, + 0xfe3b3bec3bc5d776ULL, 0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL, + 0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL, 0xe0ebeb8beb0b60cbULL, + 0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL, 0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL, + 0x18b9b9deb9a1676fULL, 0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL, + 0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL, 0x1b03030c03180f06ULL, + 0xdc565645568a13acULL, 0x5e44440d441a4988ULL, 0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL, + 0x672a2aa82a4d8254ULL, 0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL, + 0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL, 0x2b6c6cad6c47c1d8ULL, + 0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL, 0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL, + 0xa5acac8aac092645ULL, 0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL, + 0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL, 0x4109092409482d12ULL, + 0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL, 0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL, + 0xe2cccc17cc2edb85ULL, 0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL, + 0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL, 0xc28686228644a411ULL, +}; + +static const uint64_t C2[256] = { + 0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL, 0xcdfbe8e887e8136fULL, + 0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL, 0x0209010104010805ULL, 0x9e0d4f4f214f426eULL, + 0x6c9b3636d836adeeULL, 0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL, + 0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL, 0xa4f852525552aa07ULL, + 0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL, 0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL, + 0x5bd2a3a3b6a37115ULL, 0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL, + 0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL, 0x999cc2c22fc25eedULL, + 0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL, 0xe15dfefedffea321ULL, 0xaed5575741578216ULL, + 0x2abd15155415a841ULL, 0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL, + 0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL, 0xa944dada4fda9e95ULL, + 0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL, 0x527c2929a429558dULL, 0x145a0a0a280a5022ULL, + 0x7f50b1b1feb1e14fULL, 0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL, + 0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL, 0xf507f4f4f7f4f303ULL, + 0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL, 0x0a2d050514052811ULL, 0xce78676781671fe6ULL, + 0xd597e4e4b7e47353ULL, 0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL, + 0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL, 0xad56d8d847d88e9fULL, + 0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL, 0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL, + 0xa77bdddd53dda68eULL, 0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL, + 0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL, 0x0e3f07071c07381bULL, + 0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL, 0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL, + 0xc65c636391633ff2ULL, 0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL, + 0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL, 0xaf5fd9d943d9869aULL, + 0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL, 0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL, + 0x293e9a9a529aa4c8ULL, 0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL, + 0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL, 0x1df480803a8074baULL, + 0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL, 0x68893434d034bde4ULL, 0x903248483d487a75ULL, + 0xe354ffffdbffab24ULL, 0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL, + 0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL, 0x41b7aeae82ae192cULL, + 0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL, 0x3b7f93937693ece5ULL, 0x442f222288220daaULL, + 0xc86364648d6407e9ULL, 0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL, + 0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL, 0xc5dfecec97ec337bULL, + 0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL, 0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL, + 0x335b97976697ccf1ULL, 0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL, + 0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL, 0x36c31b1b6c1bd877ULL, + 0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL, 0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL, + 0x8a5745450945124cULL, 0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL, + 0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL, 0xc9e9eaea8fea0365ULL, + 0xca6a656589650fecULL, 0x6903babad2bab968ULL, 0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL, + 0xa160dede5fdebe81ULL, 0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL, + 0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL, 0x09ae8a8a128a2498ULL, + 0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL, 0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL, + 0xc4556262956237f7ULL, 0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL, + 0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL, 0xb2ab59597959f220ULL, + 0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL, 0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL, + 0xbc945e5e655eca3bULL, 0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL, + 0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL, 0xc24e616199612ff8ULL, + 0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL, 0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL, + 0x8661434311432252ULL, 0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL, + 0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL, 0x1a650d0d340d6839ULL, + 0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL, 0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL, + 0x76fe3b3bec3bc5d7ULL, 0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL, + 0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL, 0xcbe0ebeb8beb0b60ULL, + 0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL, 0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL, + 0x6f18b9b9deb9a167ULL, 0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL, + 0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL, 0x061b03030c03180fULL, + 0xacdc565645568a13ULL, 0x885e44440d441a49ULL, 0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL, + 0x54672a2aa82a4d82ULL, 0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL, + 0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL, 0xd82b6c6cad6c47c1ULL, + 0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL, 0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL, + 0x45a5acac8aac0926ULL, 0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL, + 0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL, 0x124109092409482dULL, + 0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL, 0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL, + 0x85e2cccc17cc2edbULL, 0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL, + 0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL, 0x11c28686228644a4ULL, +}; + +static const uint64_t C3[256] = { + 0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL, 0x6fcdfbe8e887e813ULL, + 0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL, 0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL, + 0xee6c9b3636d836adULL, 0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL, + 0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL, 0x07a4f852525552aaULL, + 0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL, 0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL, + 0x155bd2a3a3b6a371ULL, 0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL, + 0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL, 0xed999cc2c22fc25eULL, + 0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL, 0x21e15dfefedffea3ULL, 0x16aed55757415782ULL, + 0x412abd15155415a8ULL, 0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL, + 0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL, 0x95a944dada4fda9eULL, + 0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL, 0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL, + 0x4f7f50b1b1feb1e1ULL, 0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL, + 0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL, 0x03f507f4f4f7f4f3ULL, + 0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL, 0x110a2d0505140528ULL, 0xe6ce78676781671fULL, + 0x53d597e4e4b7e473ULL, 0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL, + 0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL, 0x9fad56d8d847d88eULL, + 0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL, 0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL, + 0x8ea77bdddd53dda6ULL, 0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL, + 0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL, 0x1b0e3f07071c0738ULL, + 0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL, 0xb51bef838336836cULL, 0xff66b63333cc3385ULL, + 0xf2c65c636391633fULL, 0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL, + 0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL, 0x9aaf5fd9d943d986ULL, + 0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL, 0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL, + 0xc8293e9a9a529aa4ULL, 0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL, + 0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL, 0xba1df480803a8074ULL, + 0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL, 0xe468893434d034bdULL, 0x75903248483d487aULL, + 0x24e354ffffdbffabULL, 0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL, + 0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL, 0x2c41b7aeae82ae19ULL, + 0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL, 0xe53b7f93937693ecULL, 0xaa442f222288220dULL, + 0xe9c86364648d6407ULL, 0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL, + 0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL, 0x7bc5dfecec97ec33ULL, + 0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL, 0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL, + 0xf1335b97976697ccULL, 0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL, + 0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL, 0x7736c31b1b6c1bd8ULL, + 0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL, 0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL, + 0x4c8a574545094512ULL, 0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL, + 0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL, 0x65c9e9eaea8fea03ULL, + 0xecca6a656589650fULL, 0x686903babad2bab9ULL, 0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL, + 0x81a160dede5fdebeULL, 0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL, + 0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL, 0x9809ae8a8a128a24ULL, + 0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL, 0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL, + 0xf7c4556262956237ULL, 0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL, + 0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL, 0x20b2ab59597959f2ULL, + 0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL, 0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL, + 0x3bbc945e5e655ecaULL, 0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL, + 0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL, 0xf8c24e616199612fULL, + 0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL, 0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL, + 0x5286614343114322ULL, 0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL, + 0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL, 0x391a650d0d340d68ULL, + 0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL, 0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL, + 0xd776fe3b3bec3bc5ULL, 0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL, + 0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL, 0x60cbe0ebeb8beb0bULL, + 0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL, 0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL, + 0x676f18b9b9deb9a1ULL, 0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL, + 0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL, 0x0f061b03030c0318ULL, + 0x13acdc565645568aULL, 0x49885e44440d441aULL, 0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL, + 0x8254672a2aa82a4dULL, 0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL, + 0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL, 0xc1d82b6c6cad6c47ULL, + 0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL, 0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL, + 0x2645a5acac8aac09ULL, 0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL, + 0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL, 0x2d12410909240948ULL, + 0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL, 0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL, + 0xdb85e2cccc17cc2eULL, 0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL, + 0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL, 0xa411c28686228644ULL, +}; + +static const uint64_t C4[256] = { + 0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL, 0x136fcdfbe8e887e8ULL, + 0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL, 0x0805020901010401ULL, 0x426e9e0d4f4f214fULL, + 0xadee6c9b3636d836ULL, 0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL, + 0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL, 0xaa07a4f852525552ULL, + 0x27fdc04760609d60ULL, 0x89766535bcbccabcULL, 0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL, + 0x71155bd2a3a3b6a3ULL, 0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL, + 0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL, 0x5eed999cc2c22fc2ULL, + 0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL, 0xa321e15dfefedffeULL, 0x8216aed557574157ULL, + 0xa8412abd15155415ULL, 0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL, + 0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL, 0x9e95a944dada4fdaULL, + 0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL, 0x558d527c2929a429ULL, 0x5022145a0a0a280aULL, + 0xe14f7f50b1b1feb1ULL, 0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL, + 0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL, 0xf303f507f4f4f7f4ULL, + 0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL, 0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL, + 0x7353d597e4e4b7e4ULL, 0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL, + 0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL, 0x8e9fad56d8d847d8ULL, + 0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL, 0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL, + 0xa68ea77bdddd53ddULL, 0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL, + 0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL, 0x381b0e3f07071c07ULL, + 0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL, 0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL, + 0x3ff2c65c63639163ULL, 0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL, + 0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL, 0x869aaf5fd9d943d9ULL, + 0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL, 0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL, + 0xa4c8293e9a9a529aULL, 0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL, + 0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL, 0x74ba1df480803a80ULL, + 0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL, 0xbde468893434d034ULL, 0x7a75903248483d48ULL, + 0xab24e354ffffdbffULL, 0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL, + 0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL, 0x192c41b7aeae82aeULL, + 0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL, 0xece53b7f93937693ULL, 0x0daa442f22228822ULL, + 0x07e9c86364648d64ULL, 0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL, + 0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL, 0x337bc5dfecec97ecULL, + 0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL, 0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL, + 0xccf1335b97976697ULL, 0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL, + 0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL, 0xd87736c31b1b6c1bULL, + 0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL, 0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL, + 0x124c8a5745450945ULL, 0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL, + 0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL, 0x0365c9e9eaea8feaULL, + 0x0fecca6a65658965ULL, 0xb9686903babad2baULL, 0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL, + 0xbe81a160dede5fdeULL, 0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL, + 0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL, 0x249809ae8a8a128aULL, + 0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL, 0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL, + 0x37f7c45562629562ULL, 0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL, + 0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL, 0xf220b2ab59597959ULL, + 0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL, 0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL, + 0xca3bbc945e5e655eULL, 0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL, + 0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL, 0x2ff8c24e61619961ULL, + 0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL, 0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL, + 0x2252866143431143ULL, 0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL, + 0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL, 0x68391a650d0d340dULL, + 0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL, 0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL, + 0xc5d776fe3b3bec3bULL, 0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL, + 0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL, 0x0b60cbe0ebeb8bebULL, + 0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL, 0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL, + 0xa1676f18b9b9deb9ULL, 0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL, + 0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL, 0x180f061b03030c03ULL, + 0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL, 0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL, + 0x4d8254672a2aa82aULL, 0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL, + 0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL, 0x47c1d82b6c6cad6cULL, + 0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL, 0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL, + 0x092645a5acac8aacULL, 0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL, + 0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL, 0x482d124109092409ULL, + 0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL, 0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL, + 0x2edb85e2cccc17ccULL, 0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL, + 0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL, 0x44a411c286862286ULL, +}; + +static const uint64_t C5[256] = { + 0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL, 0xe8136fcdfbe8e887ULL, + 0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL, 0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL, + 0x36adee6c9b3636d8ULL, 0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL, + 0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL, 0x52aa07a4f8525255ULL, + 0x6027fdc04760609dULL, 0xbc89766535bcbccaULL, 0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL, + 0xa371155bd2a3a3b6ULL, 0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL, + 0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL, 0xc25eed999cc2c22fULL, + 0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL, 0xfea321e15dfefedfULL, 0x578216aed5575741ULL, + 0x15a8412abd151554ULL, 0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL, + 0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL, 0xda9e95a944dada4fULL, + 0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL, 0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL, + 0xb1e14f7f50b1b1feULL, 0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL, + 0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL, 0xf4f303f507f4f4f7ULL, + 0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL, 0x0528110a2d050514ULL, 0x671fe6ce78676781ULL, + 0xe47353d597e4e4b7ULL, 0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL, + 0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL, 0xd88e9fad56d8d847ULL, + 0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL, 0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL, + 0xdda68ea77bdddd53ULL, 0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL, + 0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL, 0x07381b0e3f07071cULL, + 0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL, 0x836cb51bef838336ULL, 0x3385ff66b63333ccULL, + 0x633ff2c65c636391ULL, 0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL, + 0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL, 0xd9869aaf5fd9d943ULL, + 0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL, 0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL, + 0x9aa4c8293e9a9a52ULL, 0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL, + 0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL, 0x8074ba1df480803aULL, + 0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL, 0x34bde468893434d0ULL, 0x487a75903248483dULL, + 0xffab24e354ffffdbULL, 0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL, + 0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL, 0xae192c41b7aeae82ULL, + 0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL, 0x93ece53b7f939376ULL, 0x220daa442f222288ULL, + 0x6407e9c86364648dULL, 0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL, + 0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL, 0xec337bc5dfecec97ULL, + 0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL, 0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL, + 0x97ccf1335b979766ULL, 0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL, + 0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL, 0x1bd87736c31b1b6cULL, + 0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL, 0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL, + 0x45124c8a57454509ULL, 0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL, + 0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL, 0xea0365c9e9eaea8fULL, + 0x650fecca6a656589ULL, 0xbab9686903babad2ULL, 0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL, + 0xdebe81a160dede5fULL, 0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL, + 0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL, 0x8a249809ae8a8a12ULL, + 0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL, 0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL, + 0x6237f7c455626295ULL, 0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL, + 0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL, 0x59f220b2ab595979ULL, + 0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL, 0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL, + 0x5eca3bbc945e5e65ULL, 0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL, + 0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL, 0x612ff8c24e616199ULL, + 0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL, 0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL, + 0x4322528661434311ULL, 0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL, + 0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL, 0x0d68391a650d0d34ULL, + 0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL, 0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL, + 0x3bc5d776fe3b3becULL, 0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL, + 0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL, 0xeb0b60cbe0ebeb8bULL, + 0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL, 0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL, + 0xb9a1676f18b9b9deULL, 0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL, + 0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL, 0x03180f061b03030cULL, + 0x568a13acdc565645ULL, 0x441a49885e44440dULL, 0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL, + 0x2a4d8254672a2aa8ULL, 0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL, + 0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL, 0x6c47c1d82b6c6cadULL, + 0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL, 0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL, + 0xac092645a5acac8aULL, 0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL, + 0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL, 0x09482d1241090924ULL, + 0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL, 0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL, + 0xcc2edb85e2cccc17ULL, 0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL, + 0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL, 0x8644a411c2868622ULL, +}; + +static const uint64_t C6[256] = { + 0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL, 0x87e8136fcdfbe8e8ULL, + 0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL, 0x0401080502090101ULL, 0x214f426e9e0d4f4fULL, + 0xd836adee6c9b3636ULL, 0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL, + 0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL, 0x5552aa07a4f85252ULL, + 0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL, 0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL, + 0xb6a371155bd2a3a3ULL, 0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL, + 0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL, 0x2fc25eed999cc2c2ULL, + 0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL, 0xdffea321e15dfefeULL, 0x41578216aed55757ULL, + 0x5415a8412abd1515ULL, 0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL, + 0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL, 0x4fda9e95a944dadaULL, + 0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL, 0xa429558d527c2929ULL, 0x280a5022145a0a0aULL, + 0xfeb1e14f7f50b1b1ULL, 0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL, + 0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL, 0xf7f4f303f507f4f4ULL, + 0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL, 0x140528110a2d0505ULL, 0x81671fe6ce786767ULL, + 0xb7e47353d597e4e4ULL, 0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL, + 0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL, 0x47d88e9fad56d8d8ULL, + 0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL, 0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL, + 0x53dda68ea77bddddULL, 0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL, + 0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL, 0x1c07381b0e3f0707ULL, + 0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL, 0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL, + 0x91633ff2c65c6363ULL, 0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL, + 0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL, 0x43d9869aaf5fd9d9ULL, + 0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL, 0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL, + 0x529aa4c8293e9a9aULL, 0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL, + 0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL, 0x3a8074ba1df48080ULL, + 0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL, 0xd034bde468893434ULL, 0x3d487a7590324848ULL, + 0xdbffab24e354ffffULL, 0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL, + 0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL, 0x82ae192c41b7aeaeULL, + 0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL, 0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL, + 0x8d6407e9c8636464ULL, 0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL, + 0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL, 0x97ec337bc5dfececULL, + 0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL, 0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL, + 0x6697ccf1335b9797ULL, 0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL, + 0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL, 0x6c1bd87736c31b1bULL, + 0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL, 0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL, + 0x0945124c8a574545ULL, 0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL, + 0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL, 0x8fea0365c9e9eaeaULL, + 0x89650fecca6a6565ULL, 0xd2bab9686903babaULL, 0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL, + 0x5fdebe81a160dedeULL, 0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL, + 0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL, 0x128a249809ae8a8aULL, + 0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL, 0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL, + 0x956237f7c4556262ULL, 0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL, + 0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL, 0x7959f220b2ab5959ULL, + 0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL, 0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL, + 0x655eca3bbc945e5eULL, 0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL, + 0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL, 0x99612ff8c24e6161ULL, + 0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL, 0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL, + 0x1143225286614343ULL, 0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL, + 0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL, 0x340d68391a650d0dULL, + 0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL, 0xe57ed79bfca97e7eULL, 0x90243db448192424ULL, + 0xec3bc5d776fe3b3bULL, 0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL, + 0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL, 0x8beb0b60cbe0ebebULL, + 0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL, 0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL, + 0xdeb9a1676f18b9b9ULL, 0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL, + 0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL, 0x0c03180f061b0303ULL, + 0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL, 0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL, + 0xa82a4d8254672a2aULL, 0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL, + 0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL, 0xad6c47c1d82b6c6cULL, + 0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL, 0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL, + 0x8aac092645a5acacULL, 0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL, + 0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL, 0x2409482d12410909ULL, + 0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL, 0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL, + 0x17cc2edb85e2ccccULL, 0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL, + 0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL, 0x228644a411c28686ULL, +}; + +static const uint64_t C7[256] = { + 0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL, 0xe887e8136fcdfbe8ULL, + 0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL, 0x0104010805020901ULL, 0x4f214f426e9e0d4fULL, + 0x36d836adee6c9b36ULL, 0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL, + 0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL, 0x525552aa07a4f852ULL, + 0x609d6027fdc04760ULL, 0xbccabc89766535bcULL, 0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL, + 0xa3b6a371155bd2a3ULL, 0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL, + 0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL, 0xc22fc25eed999cc2ULL, + 0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL, 0xfedffea321e15dfeULL, 0x5741578216aed557ULL, + 0x155415a8412abd15ULL, 0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL, + 0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL, 0xda4fda9e95a944daULL, + 0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL, 0x29a429558d527c29ULL, 0x0a280a5022145a0aULL, + 0xb1feb1e14f7f50b1ULL, 0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL, + 0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL, 0xf4f7f4f303f507f4ULL, + 0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL, 0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL, + 0xe4b7e47353d597e4ULL, 0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL, + 0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL, 0xd847d88e9fad56d8ULL, + 0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL, 0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL, + 0xdd53dda68ea77bddULL, 0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL, + 0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL, 0x071c07381b0e3f07ULL, + 0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL, 0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL, + 0x6391633ff2c65c63ULL, 0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL, + 0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL, 0xd943d9869aaf5fd9ULL, + 0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL, 0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL, + 0x9a529aa4c8293e9aULL, 0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL, + 0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL, 0x803a8074ba1df480ULL, + 0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL, 0x34d034bde4688934ULL, 0x483d487a75903248ULL, + 0xffdbffab24e354ffULL, 0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL, + 0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL, 0xae82ae192c41b7aeULL, + 0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL, 0x937693ece53b7f93ULL, 0x2288220daa442f22ULL, + 0x648d6407e9c86364ULL, 0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL, + 0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL, 0xec97ec337bc5dfecULL, + 0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL, 0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL, + 0x976697ccf1335b97ULL, 0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL, + 0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL, 0x1b6c1bd87736c31bULL, + 0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL, 0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL, + 0x450945124c8a5745ULL, 0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL, + 0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL, 0xea8fea0365c9e9eaULL, + 0x6589650fecca6a65ULL, 0xbad2bab9686903baULL, 0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL, + 0xde5fdebe81a160deULL, 0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL, + 0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL, 0x8a128a249809ae8aULL, + 0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL, 0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL, + 0x62956237f7c45562ULL, 0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL, + 0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL, 0x597959f220b2ab59ULL, + 0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL, 0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL, + 0x5e655eca3bbc945eULL, 0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL, + 0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL, 0x6199612ff8c24e61ULL, + 0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL, 0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL, + 0x4311432252866143ULL, 0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL, + 0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL, 0x0d340d68391a650dULL, + 0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL, 0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL, + 0x3bec3bc5d776fe3bULL, 0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL, + 0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL, 0xeb8beb0b60cbe0ebULL, + 0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL, 0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL, + 0xb9deb9a1676f18b9ULL, 0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL, + 0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL, 0x030c03180f061b03ULL, + 0x5645568a13acdc56ULL, 0x440d441a49885e44ULL, 0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL, + 0x2aa82a4d8254672aULL, 0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL, + 0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL, 0x6cad6c47c1d82b6cULL, + 0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL, 0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL, + 0xac8aac092645a5acULL, 0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL, + 0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL, 0x092409482d124109ULL, + 0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL, 0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL, + 0xcc17cc2edb85e2ccULL, 0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL, + 0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL, 0x86228644a411c286ULL, +}; + +static const uint64_t rc[R + 1] = { + 0x0000000000000000ULL, + 0x1823c6e887b8014fULL, + 0x36a6d2f5796f9152ULL, + 0x60bc9b8ea30c7b35ULL, + 0x1de0d7c22e4bfe57ULL, + 0x157737e59ff04adaULL, + 0x58c9290ab1a06b85ULL, + 0xbd5d10f4cb3e0567ULL, + 0xe427418ba77d95d8ULL, + 0xfbee7c66dd17479eULL, + 0xca2dbf07ad5a8333ULL, +}; + +/* This might not be true for all platforms and compilers. */ +#define SANE_ARRAY_PACKING 1 + +#if defined(SANE_ARRAY_PACKING) && (defined(ARCH_IS_LITTLE_ENDIAN) || defined(ARCH_IS_BIG_ENDIAN)) + +#if defined(ARCH_IS_LITTLE_ENDIAN) +#define LB(n) do { L[n] = C0[mu[((n+0)%8) * 8 + 7]] \ + ^ C1[mu[((n+7)%8) * 8 + 6]] \ + ^ C2[mu[((n+6)%8) * 8 + 5]] \ + ^ C3[mu[((n+5)%8) * 8 + 4]] \ + ^ C4[mu[((n+4)%8) * 8 + 3]] \ + ^ C5[mu[((n+3)%8) * 8 + 2]] \ + ^ C6[mu[((n+2)%8) * 8 + 1]] \ + ^ C7[mu[((n+1)%8) * 8 + 0]] \ + ; } while (0) +#else +#define LB(n) do { L[n] = C0[mu[((n+0)%8) * 8 + 0]] \ + ^ C1[mu[((n+7)%8) * 8 + 1]] \ + ^ C2[mu[((n+6)%8) * 8 + 2]] \ + ^ C3[mu[((n+5)%8) * 8 + 3]] \ + ^ C4[mu[((n+4)%8) * 8 + 4]] \ + ^ C5[mu[((n+3)%8) * 8 + 5]] \ + ^ C6[mu[((n+2)%8) * 8 + 6]] \ + ^ C7[mu[((n+1)%8) * 8 + 7]] \ + ; } while (0) +#endif + +static void transformMatrix(uint64_t m[8]) +{ + uint64_t L[8]; + uint8_t *mu = (uint8_t*)m; + + LB(0); + LB(1); + LB(2); + LB(3); + LB(4); + LB(5); + LB(6); + LB(7); + + array_copy64(m, L, 8); +} + +#else + +static void transformMatrix(uint64_t m[8]) +{ + uint64_t L[8]; + + L[0] = + C0[(int)(m[0] >> 56) ] ^ + C1[(int)(m[7] >> 48) & 0xff] ^ + C2[(int)(m[6] >> 40) & 0xff] ^ + C3[(int)(m[5] >> 32) & 0xff] ^ + C4[(int)(m[4] >> 24) & 0xff] ^ + C5[(int)(m[3] >> 16) & 0xff] ^ + C6[(int)(m[2] >> 8) & 0xff] ^ + C7[(int)(m[1] ) & 0xff]; + L[1] = + C0[(int)(m[1] >> 56) ] ^ + C1[(int)(m[0] >> 48) & 0xff] ^ + C2[(int)(m[7] >> 40) & 0xff] ^ + C3[(int)(m[6] >> 32) & 0xff] ^ + C4[(int)(m[5] >> 24) & 0xff] ^ + C5[(int)(m[4] >> 16) & 0xff] ^ + C6[(int)(m[3] >> 8) & 0xff] ^ + C7[(int)(m[2] ) & 0xff]; + L[2] = + C0[(int)(m[2] >> 56) ] ^ + C1[(int)(m[1] >> 48) & 0xff] ^ + C2[(int)(m[0] >> 40) & 0xff] ^ + C3[(int)(m[7] >> 32) & 0xff] ^ + C4[(int)(m[6] >> 24) & 0xff] ^ + C5[(int)(m[5] >> 16) & 0xff] ^ + C6[(int)(m[4] >> 8) & 0xff] ^ + C7[(int)(m[3] ) & 0xff]; + L[3] = + C0[(int)(m[3] >> 56) ] ^ + C1[(int)(m[2] >> 48) & 0xff] ^ + C2[(int)(m[1] >> 40) & 0xff] ^ + C3[(int)(m[0] >> 32) & 0xff] ^ + C4[(int)(m[7] >> 24) & 0xff] ^ + C5[(int)(m[6] >> 16) & 0xff] ^ + C6[(int)(m[5] >> 8) & 0xff] ^ + C7[(int)(m[4] ) & 0xff]; + L[4] = + C0[(int)(m[4] >> 56) ] ^ + C1[(int)(m[3] >> 48) & 0xff] ^ + C2[(int)(m[2] >> 40) & 0xff] ^ + C3[(int)(m[1] >> 32) & 0xff] ^ + C4[(int)(m[0] >> 24) & 0xff] ^ + C5[(int)(m[7] >> 16) & 0xff] ^ + C6[(int)(m[6] >> 8) & 0xff] ^ + C7[(int)(m[5] ) & 0xff]; + L[5] = + C0[(int)(m[5] >> 56) ] ^ + C1[(int)(m[4] >> 48) & 0xff] ^ + C2[(int)(m[3] >> 40) & 0xff] ^ + C3[(int)(m[2] >> 32) & 0xff] ^ + C4[(int)(m[1] >> 24) & 0xff] ^ + C5[(int)(m[0] >> 16) & 0xff] ^ + C6[(int)(m[7] >> 8) & 0xff] ^ + C7[(int)(m[6] ) & 0xff]; + L[6] = + C0[(int)(m[6] >> 56) ] ^ + C1[(int)(m[5] >> 48) & 0xff] ^ + C2[(int)(m[4] >> 40) & 0xff] ^ + C3[(int)(m[3] >> 32) & 0xff] ^ + C4[(int)(m[2] >> 24) & 0xff] ^ + C5[(int)(m[1] >> 16) & 0xff] ^ + C6[(int)(m[0] >> 8) & 0xff] ^ + C7[(int)(m[7] ) & 0xff]; + L[7] = + C0[(int)(m[7] >> 56) ] ^ + C1[(int)(m[6] >> 48) & 0xff] ^ + C2[(int)(m[5] >> 40) & 0xff] ^ + C3[(int)(m[4] >> 32) & 0xff] ^ + C4[(int)(m[3] >> 24) & 0xff] ^ + C5[(int)(m[2] >> 16) & 0xff] ^ + C6[(int)(m[1] >> 8) & 0xff] ^ + C7[(int)(m[0] ) & 0xff]; + + array_copy64(m, L, 8); +} + +#endif + +static void inplaceXor(uint64_t dst[8], uint64_t src[8]) +{ + dst[0] ^= src[0]; + dst[1] ^= src[1]; + dst[2] ^= src[2]; + dst[3] ^= src[3]; + dst[4] ^= src[4]; + dst[5] ^= src[5]; + dst[6] ^= src[6]; + dst[7] ^= src[7]; +} + +/** + * The core Whirlpool transform. + */ +static void processBuffer(whirlpool_ctx * const ctx) +{ + int i, r; + uint64_t K[8]; /* the round key */ + uint64_t block[8]; /* mu(buffer) */ + uint64_t state[8]; /* the cipher state */ + uint64_t L[8]; + uint8_t *buffer = ctx->buffer; + + /* + * map the buffer to a block: + */ + for (i = 0; i < 8; i++, buffer += 8) { + block[i] = + (((uint64_t)buffer[0] ) << 56) ^ + (((uint64_t)buffer[1] & 0xffL) << 48) ^ + (((uint64_t)buffer[2] & 0xffL) << 40) ^ + (((uint64_t)buffer[3] & 0xffL) << 32) ^ + (((uint64_t)buffer[4] & 0xffL) << 24) ^ + (((uint64_t)buffer[5] & 0xffL) << 16) ^ + (((uint64_t)buffer[6] & 0xffL) << 8) ^ + (((uint64_t)buffer[7] & 0xffL) ); + } + + /* + * compute and apply K^0 to the cipher state: + */ + array_copy64(K, ctx->hash, 8); + array_copy64(state, block, 8); + inplaceXor(state, K); + + /* + * iterate over all rounds: + */ + for (r = 1; r <= R; r++) { + /* + * compute K^r from K^{r-1}: + */ + transformMatrix(K); + K[0] ^= rc[r]; + + /* + * apply the r-th round transformation: + */ + transformMatrix(state); + inplaceXor(state, K); + } + /* + * apply the Miyaguchi-Preneel compression function: + */ + inplaceXor(ctx->hash, state); + inplaceXor(ctx->hash, block); +} + +/** + * Initialize the hashing state. + */ +void cryptonite_whirlpool_init(struct whirlpool_ctx * const ctx) +{ + int i; + + memset(ctx->bitLength, 0, 32); + ctx->bufferBits = ctx->bufferPos = 0; + ctx->buffer[0] = 0; /* it's only necessary to cleanup buffer[bufferPos] */ + for (i = 0; i < 8; i++) { + ctx->hash[i] = 0L; /* initial value */ + } +} + +/** + * Delivers input data to the hashing algorithm. + * + * @param source plaintext data to hash. + * @param sourceBits how many bits of plaintext to process. + * + * This method maintains the invariant: bufferBits < DIGESTBITS + */ +void cryptonite_whirlpool_update(struct whirlpool_ctx * const ctx, const uint8_t * const source, uint32_t sourceBytes) +{ + /* + sourcePos + | + +-------+-------+------- + ||||||||||||||||||||| source + +-------+-------+------- + +-------+-------+-------+-------+-------+------- + |||||||||||||||||||||| buffer + +-------+-------+-------+-------+-------+------- + | + bufferPos + */ + int sourceBits = sourceBytes * 8; + int sourcePos = 0; /* index of leftmost source uint8_t containing data (1 to 8 bits). */ + int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */ + int bufferRem = ctx->bufferBits & 7; /* occupied bits on buffer[bufferPos]. */ + int i; + uint32_t b, carry; + uint8_t *buffer = ctx->buffer; + uint8_t *bitLength = ctx->bitLength; + int bufferBits = ctx->bufferBits; + int bufferPos = ctx->bufferPos; + + /* + * tally the length of the added data: + */ + uint64_t value = sourceBits; + for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) { + carry += bitLength[i] + ((uint32_t)value & 0xff); + bitLength[i] = (uint8_t)carry; + carry >>= 8; + value >>= 8; + } + /* + * process data in chunks of 8 bits (a more efficient approach would be to take whole-word chunks): + */ + while (sourceBits > 8) { + /* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */ + /* + * take a byte from the source: + */ + b = ((source[sourcePos] << sourceGap) & 0xff) | + ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); + /* + * process this byte: + */ + buffer[bufferPos++] |= (uint8_t)(b >> bufferRem); + bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ + if (bufferBits == DIGESTBITS) { + /* + * process data block: + */ + processBuffer(ctx); + /* + * reset buffer: + */ + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = b << (8 - bufferRem); + bufferBits += bufferRem; + /* + * proceed to remaining data: + */ + sourceBits -= 8; + sourcePos++; + } + /* now 0 <= sourceBits <= 8; + * furthermore, all data (if any is left) is in source[sourcePos]. + */ + if (sourceBits > 0) { + b = (source[sourcePos] << sourceGap) & 0xff; /* bits are left-justified on b. */ + /* + * process the remaining bits: + */ + buffer[bufferPos] |= b >> bufferRem; + } else { + b = 0; + } + if (bufferRem + sourceBits < 8) { + /* + * all remaining data fits on buffer[bufferPos], + * and there still remains some space. + */ + bufferBits += sourceBits; + } else { + /* + * buffer[bufferPos] is full: + */ + bufferPos++; + bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */ + sourceBits -= 8 - bufferRem; + /* now 0 <= sourceBits < 8; + * furthermore, all data (if any is left) is in source[sourcePos]. + */ + if (bufferBits == DIGESTBITS) { + /* + * process data block: + */ + processBuffer(ctx); + /* + * reset buffer: + */ + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = b << (8 - bufferRem); + bufferBits += (int)sourceBits; + } + ctx->bufferBits = bufferBits; + ctx->bufferPos = bufferPos; +} + +/** + * Get the hash value from the hashing state. + * + * This method uses the invariant: bufferBits < DIGESTBITS + */ +void cryptonite_whirlpool_finalize(struct whirlpool_ctx * const ctx, uint8_t * const result) +{ + int i; + uint8_t *buffer = ctx->buffer; + uint8_t *bitLength = ctx->bitLength; + int bufferBits = ctx->bufferBits; + int bufferPos = ctx->bufferPos; + uint8_t *digest = result; + + /* + * append a '1'-bit: + */ + buffer[bufferPos] |= 0x80U >> (bufferBits & 7); + bufferPos++; /* all remaining bits on the current uint8_t are set to zero. */ + /* + * pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits: + */ + if (bufferPos > WBLOCKBYTES - LENGTHBYTES) { + if (bufferPos < WBLOCKBYTES) { + memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos); + } + /* + * process data block: + */ + processBuffer(ctx); + /* + * reset buffer: + */ + bufferPos = 0; + } + if (bufferPos < WBLOCKBYTES - LENGTHBYTES) { + memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos); + } + bufferPos = WBLOCKBYTES - LENGTHBYTES; + /* + * append bit length of hashed data: + */ + memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES); + /* + * process data block: + */ + processBuffer(ctx); + /* + * return the completed message digest: + */ + for (i = 0; i < DIGESTBYTES/8; i++) { + digest[0] = (uint8_t)(ctx->hash[i] >> 56); + digest[1] = (uint8_t)(ctx->hash[i] >> 48); + digest[2] = (uint8_t)(ctx->hash[i] >> 40); + digest[3] = (uint8_t)(ctx->hash[i] >> 32); + digest[4] = (uint8_t)(ctx->hash[i] >> 24); + digest[5] = (uint8_t)(ctx->hash[i] >> 16); + digest[6] = (uint8_t)(ctx->hash[i] >> 8); + digest[7] = (uint8_t)(ctx->hash[i] ); + digest += 8; + } + ctx->bufferBits = bufferBits; + ctx->bufferPos = bufferPos; +} diff --git a/cbits/cryptonite_whirlpool.h b/cbits/cryptonite_whirlpool.h new file mode 100644 index 0000000..49a2b0e --- /dev/null +++ b/cbits/cryptonite_whirlpool.h @@ -0,0 +1,31 @@ +#ifndef CRYPTOHASH_WHIRLPOOL_H +#define CRYPTOHASH_WHIRLPOOL_H + +#include + +/* + * Whirlpool-specific definitions. + */ + +#define DIGESTBYTES 64 +#define DIGESTBITS (8*DIGESTBYTES) /* 512 */ + +#define WBLOCKBYTES 64 +#define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */ + +#define LENGTHBYTES 32 +#define LENGTHBITS (8*LENGTHBYTES) /* 256 */ + +typedef struct whirlpool_ctx { + uint8_t bitLength[LENGTHBYTES]; /* global number of hashed bits (256-bit counter) */ + uint8_t buffer[WBLOCKBYTES]; /* buffer of data to hash */ + uint32_t bufferBits; /* current number of bits on the buffer */ + uint32_t bufferPos; /* current (possibly incomplete) byte slot on the buffer */ + uint64_t hash[DIGESTBYTES/8]; /* the hashing state */ +} whirlpool_ctx; + +void cryptonite_whirlpool_init(struct whirlpool_ctx * const ctx); +void cryptonite_whirlpool_update(struct whirlpool_ctx * const ctx, const uint8_t * const source, uint32_t len); +void cryptonite_whirlpool_finalize(struct whirlpool_ctx * const ctx, uint8_t * const result); + +#endif diff --git a/cryptonite.cabal b/cryptonite.cabal index a46d315..3243190 100644 --- a/cryptonite.cabal +++ b/cryptonite.cabal @@ -23,6 +23,22 @@ Library Exposed-modules: Crypto.Cipher.ChaCha Crypto.Cipher.Salsa Crypto.MAC.Poly1305 + Crypto.Hash.SHA1 + Crypto.Hash.SHA224 + Crypto.Hash.SHA256 + Crypto.Hash.SHA384 + Crypto.Hash.SHA512 + Crypto.Hash.SHA512t + Crypto.Hash.SHA3 + Crypto.Hash.MD2 + Crypto.Hash.MD4 + Crypto.Hash.MD5 + Crypto.Hash.RIPEMD160 + Crypto.Hash.Skein256 + Crypto.Hash.Skein512 + Crypto.Hash.Tiger + Crypto.Hash.Whirlpool + Other-modules: Crypto.Hash.Internal Build-depends: base >= 4 && < 5 , bytestring , securemem @@ -32,6 +48,18 @@ Library C-sources: cbits/cryptonite_chacha.c , cbits/cryptonite_salsa.c , cbits/cryptonite_poly1305.c + , cbits/cryptonite_sha1.c + , cbits/cryptonite_sha256.c + , cbits/cryptonite_sha512.c + , cbits/cryptonite_sha3.c + , cbits/cryptonite_md2.c + , cbits/cryptonite_md4.c + , cbits/cryptonite_md5.c + , cbits/cryptonite_ripemd.c + , cbits/cryptonite_skein256.c + , cbits/cryptonite_skein512.c + , cbits/cryptonite_tiger.c + , cbits/cryptonite_whirlpool.c if (arch(i386) || arch(x86_64)) CPP-options: -DARCH_IS_LITTLE_ENDIAN diff --git a/tests/KATHash.hs b/tests/KATHash.hs new file mode 100644 index 0000000..04ace7c --- /dev/null +++ b/tests/KATHash.hs @@ -0,0 +1,221 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ViewPatterns #-} +module KATHash + ( tests + ) where + +import Data.Char +import Data.Bits +import Data.Word +import Data.ByteString (ByteString) +import Data.Byteable +import Data.Foldable (foldl') +import Data.Monoid (mconcat) +import qualified Data.ByteString as B +import qualified Data.ByteString.Char8 as BC + +import qualified Crypto.Hash.MD2 as MD2 +import qualified Crypto.Hash.MD4 as MD4 +import qualified Crypto.Hash.MD5 as MD5 +import qualified Crypto.Hash.SHA1 as SHA1 +import qualified Crypto.Hash.SHA224 as SHA224 +import qualified Crypto.Hash.SHA256 as SHA256 +import qualified Crypto.Hash.SHA384 as SHA384 +import qualified Crypto.Hash.SHA512 as SHA512 +import qualified Crypto.Hash.SHA512t as SHA512t +import qualified Crypto.Hash.SHA3 as SHA3 +import qualified Crypto.Hash.RIPEMD160 as RIPEMD160 +import qualified Crypto.Hash.Tiger as Tiger +import qualified Crypto.Hash.Skein256 as Skein256 +import qualified Crypto.Hash.Skein512 as Skein512 +import qualified Crypto.Hash.Whirlpool as Whirlpool + +import Test.Tasty +import Test.Tasty.QuickCheck +import Test.Tasty.HUnit + +v0,v1,v2 :: ByteString +v0 = "" +v1 = "The quick brown fox jumps over the lazy dog" +v2 = "The quick brown fox jumps over the lazy cog" +vectors = [ v0, v1, v2 ] + +instance Arbitrary ByteString where + arbitrary = B.pack `fmap` arbitrary + +data HashFct = HashFct + { fctHash :: (B.ByteString -> B.ByteString) + , fctInc :: ([B.ByteString] -> B.ByteString) } + +hashinc i u f = f . foldl u i + +md2Hash = HashFct { fctHash = MD2.hash, fctInc = hashinc MD2.init MD2.update MD2.finalize } +md4Hash = HashFct { fctHash = MD4.hash, fctInc = hashinc MD4.init MD4.update MD4.finalize } +md5Hash = HashFct { fctHash = MD5.hash, fctInc = hashinc MD5.init MD5.update MD5.finalize } + +sha1Hash = HashFct { fctHash = SHA1.hash, fctInc = hashinc SHA1.init SHA1.update SHA1.finalize } + +sha224Hash = HashFct { fctHash = SHA224.hash, fctInc = hashinc SHA224.init SHA224.update SHA224.finalize } +sha256Hash = HashFct { fctHash = SHA256.hash, fctInc = hashinc SHA256.init SHA256.update SHA256.finalize } + +sha384Hash = HashFct { fctHash = SHA384.hash, fctInc = hashinc SHA384.init SHA384.update SHA384.finalize } +sha512Hash = HashFct { fctHash = SHA512.hash, fctInc = hashinc SHA512.init SHA512.update SHA512.finalize } +sha512_224Hash = HashFct { fctHash = SHA512t.hash 224, fctInc = hashinc (SHA512t.init 224) SHA512t.update SHA512t.finalize } +sha512_256Hash = HashFct { fctHash = SHA512t.hash 256, fctInc = hashinc (SHA512t.init 256) SHA512t.update SHA512t.finalize } + +sha3Hash i = HashFct { fctHash = SHA3.hash i, fctInc = hashinc (SHA3.init i) SHA3.update SHA3.finalize } + +ripemd160Hash = HashFct { fctHash = RIPEMD160.hash, fctInc = hashinc RIPEMD160.init RIPEMD160.update RIPEMD160.finalize } +tigerHash = HashFct { fctHash = Tiger.hash, fctInc = hashinc Tiger.init Tiger.update Tiger.finalize } + +skein256Hash x = HashFct { fctHash = Skein256.hash x, fctInc = hashinc (Skein256.init x) Skein256.update Skein256.finalize } +skein512Hash x = HashFct { fctHash = Skein512.hash x, fctInc = hashinc (Skein512.init x) Skein512.update Skein512.finalize } + +whirlpoolHash = HashFct { fctHash = Whirlpool.hash, fctInc = hashinc Whirlpool.init Whirlpool.update Whirlpool.finalize } + +results :: [ (String, HashFct, [String]) ] +results = [ + ("MD2", md2Hash, [ + "8350e5a3e24c153df2275c9f80692773", + "03d85a0d629d2c442e987525319fc471", + "6b890c9292668cdbbfda00a4ebf31f05" ]), + ("MD4", md4Hash, [ + "31d6cfe0d16ae931b73c59d7e0c089c0", + "1bee69a46ba811185c194762abaeae90", + "b86e130ce7028da59e672d56ad0113df" ]), + ("MD5", md5Hash, [ + "d41d8cd98f00b204e9800998ecf8427e", + "9e107d9d372bb6826bd81d3542a419d6", + "1055d3e698d289f2af8663725127bd4b" ]), + ("SHA1", sha1Hash, [ + "da39a3ee5e6b4b0d3255bfef95601890afd80709", + "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3" ]), + ("SHA224", sha224Hash, [ + "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", + "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525", + "fee755f44a55f20fb3362cdc3c493615b3cb574ed95ce610ee5b1e9b" ]), + ("SHA256", sha256Hash, [ + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", + "e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be" ]), + ("SHA384", sha384Hash, [ + "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", + "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1", + "098cea620b0978caa5f0befba6ddcf22764bea977e1c70b3483edfdf1de25f4b40d6cea3cadf00f809d422feb1f0161b" ]), + ("SHA512", sha512Hash, [ + "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", + "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", + "3eeee1d0e11733ef152a6c29503b3ae20c4f1f3cda4cb26f1bc1a41f91c7fe4ab3bd86494049e201c4bd5155f31ecb7a3c8606843c4cc8dfcab7da11c8ae5045" ]), + + ("SHA512/224", sha512_224Hash, [ + "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4", + "944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37", + "2b9d6565a7e40f780ba8ab7c8dcf41e3ed3b77997f4c55aa987eede5" ]), + ("SHA512/256", sha512_256Hash, [ + "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a", + "dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d", + "cc8d255a7f2f38fd50388fd1f65ea7910835c5c1e73da46fba01ea50d5dd76fb" ]), + ("RIPEMD160", ripemd160Hash, [ + "9c1185a5c5e9fc54612808977ee8f548b2258d31", + "37f332f68db77bd9d7edd4969571ad671cf9dd3b", + "132072df690933835eb8b6ad0b77e7b6f14acad7" ]), + ("Tiger", tigerHash, [ + "3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3", + "6d12a41e72e644f017b6f0e2f7b44c6285f06dd5d2c5b075", + "a8f04b0f7201a0d728101c9d26525b31764a3493fcd8458f" ]) + , ("Skein256-160", skein256Hash 160, [ + "ff800bed6d2044ee9d604a674e3fda50d9b24a72", + "3265703c166aa3e0d7da070b9cf1b1a5953f0a77", + "17b29aa1424b3ec022505bd215ff73fd2e6d1e5a" ]) + , ("Skein256-256", skein256Hash 256, [ + "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba", + "c0fbd7d779b20f0a4614a66697f9e41859eaf382f14bf857e8cdb210adb9b3fe", + "fb2f2f2deed0e1dd7ee2b91cee34e2d1c22072e1f5eaee288c35a0723eb653cd" ]) + , ("Skein512-160", skein512Hash 160, [ + "49daf1ccebb3544bc93cb5019ba91b0eea8876ee", + "826325ee55a6dd18c3b2dbbc9c10420f5475975e", + "7544ec7a35712ec953f02b0d0c86641cae4eb6e5" ]) + , ("Skein512-384", skein512Hash 384, [ + "dd5aaf4589dc227bd1eb7bc68771f5baeaa3586ef6c7680167a023ec8ce26980f06c4082c488b4ac9ef313f8cbe70808", + "f814c107f3465e7c54048a5503547deddc377264f05c706b0d19db4847b354855ee52ab6a785c238c9e710d848542041", + "e06520eeadc1d0a44fee1d2492547499c1e58526387c8b9c53905e5edb79f9840575cbf844e21b1ad1ea126dd8a8ca6f" ]) + , ("Skein512-512", skein512Hash 512, [ + "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a", + "94c2ae036dba8783d0b3f7d6cc111ff810702f5c77707999be7e1c9486ff238a7044de734293147359b4ac7e1d09cd247c351d69826b78dcddd951f0ef912713", + "7f81113575e4b4d3441940e87aca331e6d63d103fe5107f29cd877af0d0f5e0ea34164258c60da5190189d0872e63a96596d2ef25e709099842da71d64111e0f" ]) + , ("Skein512-896", skein512Hash 896, [ + "b95175236c83a459ce7ec6c12b761a838b22d750e765b3fdaa892201b2aa714bc3d1d887dd64028bbf177c1dd11baa09c6c4ddb598fd07d6a8c131a09fc5b958e2999a8006754b25abe3bf8492b7eabec70e52e04e5ac867df2393c573f16eee3244554f1d2b724f2c0437c62007f770", + "3265708553e7d146e5c7bcbc97b3e9e9f5b53a5e4af53612bdd6454da4fa7b13d413184fe34ed57b6574be10e389d0ec4b1d2b1dd2c80e0257d5a76b2cd86a19a27b1bcb3cc24d911b5dc5ee74d19ad558fd85b5f024e99f56d1d3199f1f9f88ed85fab9f945f11cf9fc00e94e3ca4c7", + "3d23d3db9be719bbd2119f8402a28f38d8225faa79d5b68b80738c64a82004aafc7a840cd6dd9bced6644fa894a3d8d7d2ee89525fd1956a2db052c4c2f8d2111c91ef46b0997540d42bcf384826af1a5ef6510077f52d0574cf2b46f1b6a5dad07ed40f3d21a13ca2d079fa602ff02d" ]) + , ("Whirlpool", whirlpoolHash, [ + "19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3", + "b97de512e91e3828b40d2b0fdce9ceb3c4a71f9bea8d88e75c4fa854df36725fd2b52eb6544edcacd6f8beddfea403cb55ae31f03ad62a5ef54e42ee82c3fb35", + "dce81fc695cfea3d7e1446509238daf89f24cc61896f2d265927daa70f2108f8902f0dfd68be085d5abb9fcd2e482c1dc24f2fabf81f40b73495cad44d7360d3"]) + , ("SHA3-224", sha3Hash 224, [ + "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd", + "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe", + "0b27ff3b732133287f6831e2af47cf342b7ef1f3fcdee248811090cd" ]) + , ("SHA3-256", sha3Hash 256, [ + "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15", + "ed6c07f044d7573cc53bf1276f8cba3dac497919597a45b4599c8f73e22aa334" ]) + , ("SHA3-384", sha3Hash 384, [ + "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff", + "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3", + "1cc515e1812491058d8b8b226fd85045e746b4937a58b0111b6b7a39dd431b6295bd6b6d05e01e225586b4dab3cbb87a" ]) + , ("SHA3-512", sha3Hash 512, [ + "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e", + "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609", + "10f8caabb5b179861da5e447d34b84d604e3eb81830880e1c2135ffc94580a47cb21f6243ec0053d58b1124d13af2090033659075ee718e0f111bb3f69fb24cf" ]) + ] + +hexalise s = concatMap (\c -> [ hex $ c `div` 16, hex $ c `mod` 16 ]) s + where hex i + | i >= 0 && i <= 9 = fromIntegral (ord '0') + i + | i >= 10 && i <= 15 = fromIntegral (ord 'a') + i - 10 + | otherwise = 0 + +hexaliseB :: B.ByteString -> B.ByteString +hexaliseB = B.pack . hexalise . B.unpack + +splitB :: Int -> ByteString -> [ByteString] +splitB l b = + if B.length b > l + then + let (b1, b2) = B.splitAt l b in + b1 : splitB l b2 + else + [ b ] + +showHash :: B.ByteString -> String +showHash = map (toEnum.fromEnum) . hexalise . B.unpack + +runhash hash v = showHash $ (fctHash hash) $ v +runhashinc hash v = showHash $ (fctInc hash) $ v + +makeTestAlg (name, hash, results) = testGroup name $ concatMap maketest (zip3 [0..] vectors results) + where + runtest :: ByteString -> String + runtest v = runhash hash v + + runtestinc :: Int -> ByteString -> String + runtestinc i v = runhashinc hash $ splitB i v + + maketest (i, v, r) = + [ testCase (show i ++ " one-pass") (r @=? runtest v) + , testCase (show i ++ " inc 1") (r @=? runtestinc 1 v) + , testCase (show i ++ " inc 2") (r @=? runtestinc 2 v) + , testCase (show i ++ " inc 3") (r @=? runtestinc 3 v) + , testCase (show i ++ " inc 4") (r @=? runtestinc 4 v) + , testCase (show i ++ " inc 5") (r @=? runtestinc 5 v) + , testCase (show i ++ " inc 9") (r @=? runtestinc 9 v) + , testCase (show i ++ " inc 16") (r @=? runtestinc 16 v) + ] + +katTests :: [TestTree] +katTests = map makeTestAlg results + +tests = testGroup "hash" + [ testGroup "KATs" katTests + ] diff --git a/tests/Tests.hs b/tests/Tests.hs index 0e3bfd3..cd47817 100644 --- a/tests/Tests.hs +++ b/tests/Tests.hs @@ -14,6 +14,7 @@ import qualified Crypto.Cipher.Salsa as Salsa import qualified Crypto.MAC.Poly1305 as Poly1305 import qualified KATSalsa +import qualified KATHash b8_128_k0_i0 = "\xe2\x8a\x5f\xa4\xa6\x7f\x8c\x5d\xef\xed\x3e\x6f\xb7\x30\x34\x86\xaa\x84\x27\xd3\x14\x19\xa7\x29\x57\x2d\x77\x79\x53\x49\x11\x20\xb6\x4a\xb8\xe7\x2b\x8d\xeb\x85\xcd\x6a\xea\x7c\xb6\x08\x9a\x10\x18\x24\xbe\xeb\x08\x81\x4a\x42\x8a\xab\x1f\xa2\xc8\x16\x08\x1b\x8a\x26\xaf\x44\x8a\x1b\xa9\x06\x36\x8f\xd8\xc8\x38\x31\xc1\x8c\xec\x8c\xed\x81\x1a\x02\x8e\x67\x5b\x8d\x2b\xe8\xfc\xe0\x81\x16\x5c\xea\xe9\xf1\xd1\xb7\xa9\x75\x49\x77\x49\x48\x05\x69\xce\xb8\x3d\xe6\xa0\xa5\x87\xd4\x98\x4f\x19\x92\x5f\x5d\x33\x8e\x43\x0d" @@ -65,6 +66,7 @@ tests = testGroup "cryptonite" msg = B.pack $ take totalLen $ concat (replicate 10 [1..255]) in Poly1305.auth key msg == Poly1305.finalize (foldr (flip Poly1305.update) (Poly1305.initialize key) (chunks chunkLen msg)) ] + , KATHash.tests ] where chachaRunSimple expected rounds klen nonceLen = let chacha = ChaCha.initialize rounds (B.replicate klen 0) (B.replicate nonceLen 0)