Permalink
Browse files

add skein256 file duplicating their skein512 files

  • Loading branch information...
1 parent 88d21b3 commit 8e42d0f155c3c2c004a6db110cf8d9150672a188 @vincenthz committed Aug 8, 2010
Showing with 368 additions and 1 deletion.
  1. +115 −0 Data/CryptoHash/Skein256.hs
  2. +204 −0 cbits/skein256.c
  3. +45 −0 cbits/skein256.h
  4. +4 −1 cryptohash.cabal
View
@@ -0,0 +1,115 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+-- |
+-- Module : Data.CryptoHash.Skein512
+-- License : BSD-style
+-- Maintainer : Vincent Hanquez <vincent@snarc.org>
+-- Stability : experimental
+-- Portability : unknown
+--
+-- A module containing Skein512 bindings
+--
+module Data.CryptoHash.Skein512 (
+ Ctx(..),
+
+ -- * Incremental hashing Functions
+ init, -- :: Int -> Ctx
+ update, -- :: Ctx -> ByteString -> Ctx
+ finalize, -- :: Ctx -> ByteString
+
+ -- * Single Pass hashing
+ hash, -- :: Int -> ByteString -> ByteString
+ hashlazy -- :: Int -> ByteString -> ByteString
+ ) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import Foreign.C.Types
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCStringLen, unsafeIndex)
+import Data.ByteString.Internal (create)
+
+data Ctx = Ctx !ByteString
+
+sizeCtx :: Int
+sizeCtx = 160
+
+instance Storable Ctx where
+ sizeOf _ = sizeCtx
+ alignment _ = 16
+ poke ptr (Ctx b) = do
+ mapM_ (\i -> poke (ptr `plusPtr` i) (unsafeIndex b i)) [0..(sizeCtx-1)]
+
+ peek ptr = do
+ b <- create sizeCtx (\bptr -> do
+ mapM_ (\i -> do
+ f <- peek (ptr `plusPtr` i) :: IO Word8
+ poke (bptr `plusPtr` i) f
+ ) [0..(sizeCtx-1)]
+ )
+ return $ Ctx b
+
+poke_hashlen :: Ptr Ctx -> IO Int
+poke_hashlen ptr = do
+ a <- peek (ptr `plusPtr` 3)
+ b <- peek (ptr `plusPtr` 2)
+ c <- peek (ptr `plusPtr` 1)
+ d <- peek (ptr `plusPtr` 0)
+ return (sl a 24 .|. sl b 16 .|. sl c 8 .|. sl d 0)
+ where
+ sl :: Word8 -> Int -> Int
+ sl a r = (fromIntegral a) `shiftL` r
+
+foreign import ccall unsafe "skein512.h skein512_init"
+ c_skein512_init :: Ptr Ctx -> CUInt -> IO ()
+
+foreign import ccall "skein512.h skein512_update"
+ c_skein512_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "skein512.h skein512_finalize"
+ c_skein512_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+ unsafeUseAsCStringLen d (\(cs, len) -> c_skein512_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr = do
+ digestSize <- fmap (\x -> (x + 7) `shiftR` 3) $ poke_hashlen ptr
+ allocaBytes digestSize (\cs -> c_skein512_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Int -> Ctx
+init hashlen = unsafePerformIO $ allocInternal $ \ptr -> do (c_skein512_init ptr (fromIntegral hashlen) >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: Int -> ByteString -> ByteString
+hash hashlen d = unsafePerformIO $ allocInternal $ \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 -> L.ByteString -> ByteString
+hashlazy hashlen l = unsafePerformIO $ allocInternal $ \ptr -> do
+ c_skein512_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
View
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2006-2010 Vincent Hanquez <vincent@snarc.org>
+ *
+ * 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 <string.h>
+#include "skein.h"
+#include "skein512.h"
+#include "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] = 0x5555555555555555;
+ 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 skein512_init(struct skein512_ctx *ctx, uint32_t hashlen)
+{
+ uint64_t buf[8];
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->hashlen = cpu_to_le64(hashlen);
+ 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 skein512_update(struct skein512_ctx *ctx, uint8_t *data, uint32_t len)
+{
+ uint32_t to_fill;
+
+ to_fill = 64 - ctx->bufindex;
+
+ /* process partial buffer if there's enough data to make a block */
+ if ((ctx->bufindex & 0x3f) && 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 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 = (le64_to_cpu(ctx->hashlen) + 7) >> 3;
+
+ /* 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 *) 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;
+
+ /* FIXME should be little endian array copy ? */
+ memcpy(out + i*64, ctx->h, n);
+
+ /* restore h[0--7] */
+ for (j = 0; j < 8; j++)
+ ctx->h[j] = x[j];
+ }
+}
View
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006-2010 Vincent Hanquez <vincent@snarc.org>
+ *
+ * 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 <stdint.h>
+
+struct skein512_ctx
+{
+ uint32_t hashlen; /* in bits, typically 384, 512 */
+ 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 skein512_init(struct skein512_ctx *ctx, uint32_t hashlen);
+void skein512_update(struct skein512_ctx *ctx, uint8_t *data, uint32_t len);
+void skein512_finalize(struct skein512_ctx *ctx, uint8_t *out);
+
+#endif
View
@@ -19,7 +19,7 @@ data-files: README
extra-source-files:
cbits/bitfn.h cbits/md2.h cbits/md4.h cbits/md5.h
cbits/ripemd.h cbits/sha1.h cbits/sha256.h cbits/sha512.h
- cbits/skein.h cbits/skein512.h
+ cbits/skein.h cbits/skein256.h cbits/skein512.h
cbits/tiger.h
Flag test
@@ -38,6 +38,7 @@ Library
Data.CryptoHash.MD4
Data.CryptoHash.MD5
Data.CryptoHash.RIPEMD160
+ Data.CryptoHash.Skein256
Data.CryptoHash.Skein512
Data.CryptoHash.Tiger
ghc-options: -Wall -O2 -optc-O3 -fno-cse
@@ -48,6 +49,7 @@ Library
cbits/md4.c
cbits/md5.c
cbits/ripemd.c
+ cbits/skein256.c
cbits/skein512.c
cbits/tiger.c
Include-Dirs: cbits
@@ -62,6 +64,7 @@ Executable Tests
cbits/md4.c
cbits/md5.c
cbits/ripemd.c
+ cbits/skein256.c
cbits/skein512.c
cbits/tiger.c
if flag(test)

0 comments on commit 8e42d0f

Please sign in to comment.