From d96d89e4ba2d1203fddc6f90ccaff458b05912be Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Thu, 9 Apr 2015 07:41:15 +0100 Subject: [PATCH] start cleaning up Camellia --- Crypto/Cipher/Camellia.hs | 4 +-- Crypto/Cipher/Camellia/Primitive.hs | 53 +++++++---------------------- Crypto/Internal/ByteArray.hs | 18 ++++++++++ Crypto/Internal/Words.hs | 17 +++++++++ cryptonite.cabal | 1 + 5 files changed, 50 insertions(+), 43 deletions(-) create mode 100644 Crypto/Internal/Words.hs diff --git a/Crypto/Cipher/Camellia.hs b/Crypto/Cipher/Camellia.hs index d51e21a..985a43d 100644 --- a/Crypto/Cipher/Camellia.hs +++ b/Crypto/Cipher/Camellia.hs @@ -24,5 +24,5 @@ instance Cipher Camellia128 where instance BlockCipher Camellia128 where blockSize _ = 16 - ecbEncrypt (Camellia128 key) = ecbEncryptLegacy encrypt key - ecbDecrypt (Camellia128 key) = ecbDecryptLegacy decrypt key + ecbEncrypt (Camellia128 key) = encrypt key + ecbDecrypt (Camellia128 key) = decrypt key diff --git a/Crypto/Cipher/Camellia/Primitive.hs b/Crypto/Cipher/Camellia/Primitive.hs index 62f3c33..40db84a 100644 --- a/Crypto/Cipher/Camellia/Primitive.hs +++ b/Crypto/Cipher/Camellia/Primitive.hs @@ -1,3 +1,4 @@ + -- | -- Module : Crypto.Cipher.Camellia.Primitive -- License : BSD-style @@ -23,12 +24,10 @@ import qualified Data.ByteString.Unsafe as B import Crypto.Error import Crypto.Internal.ByteArray +import Crypto.Internal.Words data Mode = Decrypt | Encrypt --- should probably use crypto large word ? -data Word128 = Word128 !Word64 !Word64 deriving (Show, Eq) - w128tow64 :: Word128 -> (Word64, Word64) w128tow64 (Word128 w1 w2) = (w1, w2) @@ -66,23 +65,6 @@ w64tow32 w = (fromIntegral (w `shiftR` 32), fromIntegral (w .&. 0xffffffff)) w32tow64 :: (Word32, Word32) -> Word64 w32tow64 (x1, x2) = ((fromIntegral x1) `shiftL` 32) .|. (fromIntegral x2) -w128tow8 :: Word128 -> [Word8] -w128tow8 (Word128 x1 x2) = [t1,t2,t3,t4,t5,t6,t7,t8,u1,u2,u3,u4,u5,u6,u7,u8] - where - (t1, t2, t3, t4, t5, t6, t7, t8) = w64tow8 x1 - (u1, u2, u3, u4, u5, u6, u7, u8) = w64tow8 x2 - -getWord64 :: B.ByteString -> Word64 -getWord64 s = sh 0 56 .|. sh 1 48 .|. sh 2 40 .|. sh 3 32 .|. sh 4 24 .|. sh 5 16 .|. sh 6 8 .|. sh 7 0 - where - sh i l = (fromIntegral (s `B.index` i) `shiftL` l) - -getWord128 :: B.ByteString -> Word128 -getWord128 s = Word128 (getWord64 s) (getWord64 (B.drop 8 s)) - -putWord128 :: Word128 -> B.ByteString -putWord128 = B.pack . w128tow8 - sbox :: Vector Word8 sbox = fromList [112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65 @@ -299,27 +281,16 @@ encryptBlock = doBlock Encrypt decryptBlock :: Camellia -> Word128 -> Word128 decryptBlock = doBlock Decrypt -encryptChunk :: Camellia -> B.ByteString -> B.ByteString -encryptChunk key b = putWord128 $ encryptBlock key $ getWord128 b - -decryptChunk :: Camellia -> B.ByteString -> B.ByteString -decryptChunk key b = putWord128 $ decryptBlock key $ getWord128 b - -doChunks :: (B.ByteString -> B.ByteString) -> B.ByteString -> [B.ByteString] -doChunks f b = - let (x, rest) = B.splitAt 16 b in - if B.length rest >= 16 - then f x : doChunks f rest - else [ f x ] - -- | Encrypts the given ByteString using the given Key -encrypt :: Camellia -- ^ The key to use - -> B.ByteString -- ^ The data to encrypt - -> B.ByteString -encrypt key b = B.concat $ doChunks (encryptChunk key) b +encrypt :: ByteArray ba + => Camellia -- ^ The key to use + -> ba -- ^ The data to encrypt + -> ba +encrypt key = byteArrayMapAsWord128 (encryptBlock key) -- | Decrypts the given ByteString using the given Key -decrypt :: Camellia -- ^ The key to use - -> B.ByteString -- ^ The data to decrypt - -> B.ByteString -decrypt key b = B.concat $ doChunks (decryptChunk key) b +decrypt :: ByteArray ba + => Camellia -- ^ The key to use + -> ba -- ^ The data to decrypt + -> ba +decrypt key = byteArrayMapAsWord128 (decryptBlock key) diff --git a/Crypto/Internal/ByteArray.hs b/Crypto/Internal/ByteArray.hs index 4a2fda9..790afe7 100644 --- a/Crypto/Internal/ByteArray.hs +++ b/Crypto/Internal/ByteArray.hs @@ -25,6 +25,7 @@ module Crypto.Internal.ByteArray , byteArrayFromBS , byteArrayToW64BE , byteArrayToW64LE + , byteArrayMapAsWord128 ) where import Control.Applicative ((<$>), (<*>)) @@ -34,6 +35,7 @@ import Crypto.Internal.Memory import Crypto.Internal.Compat import Crypto.Internal.Endian import Crypto.Internal.Bytes (bufXor, bufCopy) +import Crypto.Internal.Words import Foreign.Ptr import Foreign.Storable import Foreign.ForeignPtr @@ -180,3 +182,19 @@ byteArrayToW64BE bs ofs = unsafeDoIO $ withByteArray bs $ \p -> fromBE64 <$> pee byteArrayToW64LE :: ByteArrayAccess bs => bs -> Int -> Word64 byteArrayToW64LE bs ofs = unsafeDoIO $ withByteArray bs $ \p -> fromLE64 <$> peek (p `plusPtr` ofs) + +byteArrayMapAsWord128 :: ByteArray bs => (Word128 -> Word128) -> bs -> bs +byteArrayMapAsWord128 f bs = + byteArrayAllocAndFreeze len $ \dst -> + withByteArray bs $ \src -> + loop (len `div` 16) dst src + where + len = byteArrayLength bs + loop 0 _ _ = return () + loop i d s = do + w1 <- peek s + w2 <- peek (s `plusPtr` 8) + let (Word128 r1 r2) = f (Word128 (fromBE64 w1) (fromBE64 w2)) + poke d (toBE64 r1) + poke (d `plusPtr` 8) (toBE64 r2) + loop (i-1) (d `plusPtr` 16) (s `plusPtr` 16) diff --git a/Crypto/Internal/Words.hs b/Crypto/Internal/Words.hs new file mode 100644 index 0000000..bd88242 --- /dev/null +++ b/Crypto/Internal/Words.hs @@ -0,0 +1,17 @@ +-- | +-- Module : Crypto.Internal.Words +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- Extra Word size +-- +module Crypto.Internal.Words + ( Word128(..) + ) where + +import Data.Word + +-- should probably use crypto large word ? +data Word128 = Word128 !Word64 !Word64 deriving (Show, Eq) diff --git a/cryptonite.cabal b/cryptonite.cabal index 03a222d..4471a48 100644 --- a/cryptonite.cabal +++ b/cryptonite.cabal @@ -130,6 +130,7 @@ Library Crypto.Internal.Endian Crypto.Internal.Imports Crypto.Internal.Memory + Crypto.Internal.Words Build-depends: base >= 4.3 && < 5 , bytestring , securemem >= 0.1.7