move to memory stuff

This commit is contained in:
Vincent Hanquez 2015-05-09 14:23:32 +01:00
parent 68e3a58be7
commit 9ae9e38ce2
27 changed files with 77 additions and 538 deletions

View File

@ -67,7 +67,7 @@ import Crypto.Error
import Crypto.Cipher.Types
import Crypto.Cipher.Types.Block (IV(..))
import Crypto.Internal.Compat
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, SecureBytes, withByteArray)
import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes, withByteArray)
import qualified Crypto.Internal.ByteArray as B
instance Cipher AES where
@ -107,13 +107,13 @@ ocbMode aes = AEADModeImpl
-- | AES Context (pre-processed key)
newtype AES = AES SecureBytes
newtype AES = AES ScrubbedBytes
-- | AESGCM State
newtype AESGCM = AESGCM SecureBytes
newtype AESGCM = AESGCM ScrubbedBytes
-- | AESOCB State
newtype AESOCB = AESOCB SecureBytes
newtype AESOCB = AESOCB ScrubbedBytes
sizeGCM :: Int
sizeGCM = 80

View File

@ -26,6 +26,7 @@ import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Internal.Words
import Crypto.Internal.WordArray
import Data.Memory.Endian
data Mode = Decrypt | Encrypt
@ -118,7 +119,7 @@ data Camellia = Camellia
setKeyInterim :: ByteArrayAccess key => key -> (Word128, Word128, Word128, Word128)
setKeyInterim keyseed = (w64tow128 kL, w64tow128 kR, w64tow128 kA, w64tow128 kB)
where kL = (B.toW64BE keyseed 0, B.toW64BE keyseed 8)
where kL = (fromBE $ B.toW64BE keyseed 0, fromBE $ B.toW64BE keyseed 8)
kR = (0, 0)
kA = let d1 = (fst kL `xor` fst kR)

View File

@ -20,22 +20,22 @@ module Crypto.Cipher.ChaCha
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BS
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, SecureBytes, withByteArray)
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, ScrubbedBytes, withByteArray)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Internal.Compat
import Crypto.Internal.Imports
import Crypto.Internal.Bytes (bufXor)
import Data.Memory.PtrMethods (memXor)
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.Types
-- | ChaCha context
data State = State Int -- number of rounds
SecureBytes -- ChaCha's state
ByteString -- previous generated chunk
data State = State Int -- number of rounds
ScrubbedBytes -- ChaCha's state
ByteString -- previous generated chunk
-- | ChaCha context for DRG purpose (see Crypto.Random.ChaChaDRG)
newtype StateSimple = StateSimple SecureBytes -- just ChaCha's state
newtype StateSimple = StateSimple ScrubbedBytes -- just ChaCha's state
round64 :: Int -> (Bool, Int)
round64 len
@ -102,7 +102,7 @@ combine prev@(State nbRounds prevSt prevOut) src
withByteArray src $ \srcPtr -> do
-- copy the previous buffer by xor if any
withByteArray prevOut $ \prevPtr ->
bufXor dstPtr srcPtr prevPtr prevBufLen
memXor dstPtr srcPtr prevPtr prevBufLen
-- then create a new mutable copy of state
B.copy prevSt $ \stPtr ->

View File

@ -15,6 +15,7 @@ import Crypto.Cipher.Types
import Crypto.Cipher.DES.Primitive
import Crypto.Internal.ByteArray (ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import Data.Memory.Endian
-- | DES Context
data DES = DES Word64
@ -35,4 +36,4 @@ initDES k
| len == 8 = CryptoPassed $ DES key
| otherwise = CryptoFailed $ CryptoError_KeySizeInvalid
where len = B.length k
key = B.toW64BE k 0
key = fromBE $ B.toW64BE k 0

View File

@ -15,6 +15,7 @@ module Crypto.Cipher.DES.Primitive (encrypt, decrypt, Block(..)) where
import Data.Word
import Data.Bits
import Data.Memory.Endian
newtype Block = Block { unBlock :: Word64 }

View File

@ -23,13 +23,13 @@ module Crypto.Cipher.RC4
import Data.Word
import Foreign.Ptr
import Crypto.Internal.ByteArray (SecureBytes, ByteArray, ByteArrayAccess)
import Crypto.Internal.ByteArray (ScrubbedBytes, ByteArray, ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Internal.Compat
-- | The encryption state for RC4
newtype State = State SecureBytes
newtype State = State ScrubbedBytes
deriving (ByteArrayAccess)
-- | C Call for initializing the encryptor

View File

@ -14,8 +14,8 @@ module Crypto.Cipher.Salsa
) where
import Data.ByteString (ByteString)
import Crypto.Internal.Bytes (bufXor)
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, SecureBytes)
import Data.Memory.PtrMethods (memXor)
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, ScrubbedBytes)
import qualified Crypto.Internal.ByteArray as B
import qualified Data.ByteString.Internal as BS
import qualified Data.ByteString as BS
@ -27,9 +27,9 @@ import Foreign.ForeignPtr
import Foreign.C.Types
-- | Salsa context
data State = State Int -- number of rounds
SecureBytes -- Salsa's state
ByteString -- previous generated chunk
data State = State Int -- number of rounds
ScrubbedBytes -- Salsa's state
ByteString -- previous generated chunk
round64 :: Int -> (Bool, Int)
round64 len
@ -83,7 +83,7 @@ combine prev@(State nbRounds prevSt prevOut) src
B.withByteArray src $ \srcPtr -> do
-- copy the previous buffer by xor if any
B.withByteArray prevOut $ \prevPtr ->
bufXor dstPtr srcPtr prevPtr prevBufLen
memXor dstPtr srcPtr prevPtr prevBufLen
-- then create a new mutable copy of state
B.copy prevSt $ \stPtr ->

View File

@ -17,6 +17,7 @@ import Crypto.Cipher.Types
import Crypto.Cipher.DES.Primitive
import Crypto.Internal.ByteArray (ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import Data.Memory.Endian
-- | 3DES with 3 different keys used all in the same direction
data DES_EEE3 = DES_EEE3 Word64 Word64 Word64
@ -79,11 +80,11 @@ init3DES constr k
| len == 24 = CryptoPassed $ constr k1 k2 k3
| otherwise = CryptoFailed CryptoError_KeySizeInvalid
where len = B.length k
(k1, k2, k3) = (B.toW64BE k 0, B.toW64BE k 8, B.toW64BE k 16)
(k1, k2, k3) = (fromBE $ B.toW64BE k 0, fromBE $ B.toW64BE k 8, fromBE $ B.toW64BE k 16)
init2DES :: ByteArrayAccess key => (Word64 -> Word64 -> a) -> key -> CryptoFailable a
init2DES constr k
| len == 16 = CryptoPassed $ constr k1 k2
| otherwise = CryptoFailed CryptoError_KeySizeInvalid
where len = B.length k
(k1, k2) = (B.toW64BE k 0, B.toW64BE k 8)
(k1, k2) = (fromBE $ B.toW64BE k 0, fromBE $ B.toW64BE k 8)

View File

@ -20,7 +20,6 @@ module Crypto.Data.AFIS
import Crypto.Hash
import Crypto.Random.Types
import Crypto.Internal.Bytes (bufSet, bufCopy)
import Crypto.Internal.Compat
import Control.Monad (forM_, foldM)
import Data.Word
@ -31,6 +30,8 @@ import Foreign.Ptr
import Crypto.Internal.ByteArray (ByteArray, Bytes, MemView(..))
import qualified Crypto.Internal.ByteArray as B
import Data.Memory.PtrMethods (memSet, memCopy)
-- | Split data to diffused data, using a random generator and
-- an hash algorithm.
--
@ -65,7 +66,7 @@ split hashAlg rng expandTimes src
blockSize = B.length src
runOp dstPtr = do
let lastBlock = dstPtr `plusPtr` (blockSize * (expandTimes-1))
bufSet lastBlock 0 blockSize
memSet lastBlock 0 blockSize
let randomBlockPtrs = map (plusPtr dstPtr . (*) blockSize) [0..(expandTimes-2)]
rng' <- foldM fillRandomBlock rng randomBlockPtrs
mapM_ (addRandomBlock lastBlock) randomBlockPtrs
@ -76,7 +77,7 @@ split hashAlg rng expandTimes src
diffuse hashAlg lastBlock blockSize
fillRandomBlock g blockPtr = do
let (rand :: Bytes, g') = randomBytesGenerate blockSize g
B.withByteArray rand $ \randPtr -> bufCopy blockPtr randPtr (fromIntegral blockSize)
B.withByteArray rand $ \randPtr -> memCopy blockPtr randPtr (fromIntegral blockSize)
return g'
-- | Merge previously diffused data back to the original data.
@ -91,7 +92,7 @@ merge hashAlg expandTimes bs
| originalSize <= 0 = error "diffused data null"
| otherwise = B.allocAndFreeze originalSize $ \dstPtr ->
B.withByteArray bs $ \srcPtr -> do
bufSet dstPtr 0 originalSize
memSet dstPtr 0 originalSize
forM_ [0..(expandTimes-2)] $ \i -> do
xorMem (srcPtr `plusPtr` (i * originalSize)) dstPtr originalSize
diffuse hashAlg dstPtr originalSize
@ -122,10 +123,10 @@ diffuse hashAlg src sz = loop src 0
where (full,pad) = sz `quotRem` digestSize
loop s i
| i < full = do h <- hashBlock i s digestSize
B.withByteArray h $ \hPtr -> bufCopy s hPtr digestSize
B.withByteArray h $ \hPtr -> memCopy s hPtr digestSize
loop (s `plusPtr` digestSize) (i+1)
| pad /= 0 = do h <- hashBlock i s pad
B.withByteArray h $ \hPtr -> bufCopy s hPtr pad
B.withByteArray h $ \hPtr -> memCopy s hPtr pad
return ()
| otherwise = return ()

View File

@ -7,269 +7,8 @@
--
-- Simple and efficient byte array types
--
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Crypto.Internal.ByteArray
(
ByteArray(..)
, ByteArrayAccess(..)
-- * Inhabitants
, Bytes
, SecureBytes
, MemView(..)
-- * methods
, alloc
, allocAndFreeze
, empty
, zero
, copy
, take
, convert
, convertHex
, copyRet
, copyAndFreeze
, split
, xor
, eq
, index
, constEq
, concat
, toBS
, fromBS
, toW64BE
, toW64LE
, mapAsWord64
, mapAsWord128
( module X
) where
import Data.SecureMem
import Crypto.Internal.Memory
import Crypto.Internal.Compat
import Crypto.Internal.Endian
import Crypto.Internal.Bytes (bufXor, bufCopy, bufSet)
import Crypto.Internal.Hex
import Crypto.Internal.Words
import Crypto.Internal.Imports hiding (empty)
import Foreign.Ptr
import Foreign.Storable
import Foreign.ForeignPtr
import Data.ByteString (ByteString)
import qualified Data.ByteString as B (length)
import qualified Data.ByteString.Internal as B
import Prelude (flip, return, div, (*), (-), ($), (==), (/=), (<=), (>=), Int, Bool(..), IO, otherwise, sum, map, fmap, snd, (.), min)
data MemView = MemView !(Ptr Word8) !Int
instance ByteArrayAccess MemView where
length (MemView _ l) = l
withByteArray (MemView p _) f = f (castPtr p)
class ByteArrayAccess ba where
length :: ba -> Int
withByteArray :: ba -> (Ptr p -> IO a) -> IO a
class ByteArrayAccess ba => ByteArray ba where
allocRet :: Int -> (Ptr p -> IO a) -> IO (a, ba)
alloc :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
alloc n f = snd `fmap` allocRet n f
instance ByteArrayAccess Bytes where
length = bytesLength
withByteArray = withBytes
instance ByteArray Bytes where
allocRet = bytesAllocRet
instance ByteArrayAccess ByteString where
length = B.length
withByteArray b f = withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off)
where (fptr, off, _) = B.toForeignPtr b
instance ByteArray ByteString where
allocRet sz f = do
fptr <- B.mallocByteString sz
r <- withForeignPtr fptr (f . castPtr)
return (r, B.PS fptr 0 sz)
instance ByteArrayAccess SecureMem where
length = secureMemGetSize
withByteArray b f = withSecureMemPtr b (f . castPtr)
instance ByteArray SecureMem where
allocRet sz f = do
out <- allocateSecureMem sz
r <- withSecureMemPtr out (f . castPtr)
return (r, out)
allocAndFreeze :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
allocAndFreeze sz f = unsafeDoIO (alloc sz f)
empty :: ByteArray a => a
empty = unsafeDoIO (alloc 0 $ \_ -> return ())
-- | Create a xor of bytes between a and b.
--
-- the returns byte array is the size of the smallest input.
xor :: (ByteArrayAccess a, ByteArrayAccess b, ByteArray c) => a -> b -> c
xor a b =
allocAndFreeze n $ \pc ->
withByteArray a $ \pa ->
withByteArray b $ \pb ->
bufXor pc pa pb n
where
n = min la lb
la = length a
lb = length b
index :: ByteArrayAccess a => a -> Int -> Word8
index b i = unsafeDoIO $ withByteArray b $ \p -> peek (p `plusPtr` i)
split :: ByteArray bs => Int -> bs -> (bs, bs)
split n bs
| n <= 0 = (empty, bs)
| n >= len = (bs, empty)
| otherwise = unsafeDoIO $ do
withByteArray bs $ \p -> do
b1 <- alloc n $ \r -> bufCopy r p n
b2 <- alloc (len - n) $ \r -> bufCopy r (p `plusPtr` n) (len - n)
return (b1, b2)
where len = length bs
take :: ByteArray bs => Int -> bs -> bs
take n bs =
allocAndFreeze m $ \d -> withByteArray bs $ \s -> bufCopy d s m
where
m = min len n
len = length bs
concat :: ByteArray bs => [bs] -> bs
concat [] = empty
concat allBs = allocAndFreeze total (loop allBs)
where
total = sum $ map length allBs
loop [] _ = return ()
loop (b:bs) dst = do
let sz = length b
withByteArray b $ \p -> bufCopy dst p sz
loop bs (dst `plusPtr` sz)
copy :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO ()) -> IO bs2
copy bs f =
alloc (length bs) $ \d -> do
withByteArray bs $ \s -> bufCopy d s (length bs)
f (castPtr d)
copyRet :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
copyRet bs f =
allocRet (length bs) $ \d -> do
withByteArray bs $ \s -> bufCopy d s (length bs)
f (castPtr d)
copyAndFreeze :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO ()) -> bs2
copyAndFreeze bs f =
allocAndFreeze (length bs) $ \d -> do
withByteArray bs $ \s -> bufCopy d s (length bs)
f (castPtr d)
zero :: ByteArray ba => Int -> ba
zero n = allocAndFreeze n $ \ptr -> bufSet ptr 0 n
eq :: (ByteArrayAccess bs1, ByteArrayAccess bs2) => bs1 -> bs2 -> Bool
eq b1 b2
| l1 /= l2 = False
| otherwise = unsafeDoIO $
withByteArray b1 $ \p1 ->
withByteArray b2 $ \p2 ->
loop l1 p1 p2
where
l1 = length b1
l2 = length b2
loop :: Int -> Ptr Word8 -> Ptr Word8 -> IO Bool
loop 0 _ _ = return True
loop i p1 p2 = do
e <- (==) <$> peek p1 <*> peek p2
if e then loop (i-1) (p1 `plusPtr` 1) (p2 `plusPtr` 1) else return False
-- | A constant time equality test for 2 ByteArrayAccess values.
--
-- If values are of 2 different sizes, the function will abort early
-- without comparing any bytes.
--
-- compared to == , this function will go over all the bytes
-- present before yielding a result even when knowing the
-- overall result early in the processing.
constEq :: (ByteArrayAccess bs1, ByteArrayAccess bs2) => bs1 -> bs2 -> Bool
constEq b1 b2
| l1 /= l2 = False
| otherwise = unsafeDoIO $
withByteArray b1 $ \p1 ->
withByteArray b2 $ \p2 ->
loop l1 True p1 p2
where
l1 = length b1
l2 = length b2
loop :: Int -> Bool -> Ptr Word8 -> Ptr Word8 -> IO Bool
loop 0 !ret _ _ = return ret
loop i !ret p1 p2 = do
e <- (==) <$> peek p1 <*> peek p2
loop (i-1) (ret &&! e) (p1 `plusPtr` 1) (p2 `plusPtr` 1)
-- Bool == Bool
(&&!) :: Bool -> Bool -> Bool
True &&! True = True
True &&! False = False
False &&! True = False
False &&! False = False
toBS :: ByteArray bs => bs -> ByteString
toBS bs = copyAndFreeze bs (\_ -> return ())
fromBS :: ByteArray bs => ByteString -> bs
fromBS bs = copyAndFreeze bs (\_ -> return ())
toW64BE :: ByteArrayAccess bs => bs -> Int -> Word64
toW64BE bs ofs = unsafeDoIO $ withByteArray bs $ \p -> fromBE64 <$> peek (p `plusPtr` ofs)
toW64LE :: ByteArrayAccess bs => bs -> Int -> Word64
toW64LE bs ofs = unsafeDoIO $ withByteArray bs $ \p -> fromLE64 <$> peek (p `plusPtr` ofs)
mapAsWord128 :: ByteArray bs => (Word128 -> Word128) -> bs -> bs
mapAsWord128 f bs =
allocAndFreeze len $ \dst ->
withByteArray bs $ \src ->
loop (len `div` 16) dst src
where
len = length 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)
mapAsWord64 :: ByteArray bs => (Word64 -> Word64) -> bs -> bs
mapAsWord64 f bs =
allocAndFreeze len $ \dst ->
withByteArray bs $ \src ->
loop (len `div` 8) dst src
where
len = length bs
loop 0 _ _ = return ()
loop i d s = do
w <- peek s
let r = f (fromBE64 w)
poke d (toBE64 r)
loop (i-1) (d `plusPtr` 8) (s `plusPtr` 8)
convert :: (ByteArrayAccess bin, ByteArray bout) => bin -> bout
convert = flip copyAndFreeze (\_ -> return ())
convertHex :: (ByteArrayAccess bin, ByteArray bout) => bin -> bout
convertHex b =
allocAndFreeze (length b * 2) $ \bout ->
withByteArray b $ \bin ->
toHexadecimal bout bin (length b)
import Data.Memory.ByteArray as X

View File

@ -1,72 +0,0 @@
-- |
-- Module : Crypto.Internal.Bytes
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : unknown
--
-- internal helpers function to manipulate sequence of bytes
-- like ByteString and buffer.
--
module Crypto.Internal.Bytes
( withByteStringPtr
, tempBufCreate
, bufXor
, bufXorWith
, bufCopy
, bufSet
) where
import Crypto.Internal.Imports
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable (peek, poke, pokeByteOff, peekByteOff)
import Foreign.Marshal.Alloc (allocaBytesAligned)
import Data.ByteString (ByteString)
import Data.Bits (xor)
import Data.ByteString.Internal (toForeignPtr)
import Data.ByteString.Internal (memcpy, memset)
withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a
withByteStringPtr b f =
withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off)
where (fptr, off, _) = toForeignPtr b
-- | Create a new temporary buffer
tempBufCreate :: Int -> (Ptr Word8 -> IO a) -> IO a
tempBufCreate size f = allocaBytesAligned size 8 f
-- | xor bytes from source1 and source2 to destination
--
-- d = s1 xor s2
--
-- s1, nor s2 are modified unless d point to s1 or s2
bufXor :: Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
bufXor _ _ _ 0 = return ()
bufXor d s1 s2 n = do
(xor <$> peek s1 <*> peek s2) >>= poke d
bufXor (d `plusPtr` 1) (s1 `plusPtr` 1) (s2 `plusPtr` 1) (n-1)
-- | xor bytes from source with a specific value to destination
--
-- d = replicate (sizeof s) v `xor` s
bufXorWith :: Ptr Word8 -> Word8 -> Ptr Word8 -> Int -> IO ()
bufXorWith d v s n = loop 0
where
loop i
| i == n = return ()
| otherwise = do
(xor v <$> peekByteOff s i) >>= pokeByteOff d i
loop (i+1)
bufCopy :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()
bufCopy dst src n = memcpy dst src (fromIntegral n)
-- | Set @n number of bytes to the same value @v
bufSet :: Ptr Word8 -> Word8 -> Int -> IO ()
bufSet start v n = memset start v (fromIntegral n) >>= \_ -> return ()
{-loop 0
where loop i
| i == n = return ()
| otherwise = pokeByteOff start i v >> loop (i+1)
-}

View File

@ -1,127 +0,0 @@
-- |
-- Module : Crypto.Internal.Memory
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : stable
-- Portability : Good
--
-- Simple and efficient byte array types
--
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Crypto.Internal.Memory
( Bytes
, bytesCopyAndModify
, bytesTemporary
, bytesCopyTemporary
, bytesAlloc
, bytesAllocRet
, bytesLength
, bytesIndex
, withBytes
, SecureBytes
) where
import GHC.Types
import GHC.Prim
import GHC.Word
import GHC.Ptr
import Foreign.Marshal.Utils (copyBytes)
import Data.SecureMem (SecureMem)
import Crypto.Internal.CompatPrim
import Crypto.Internal.Compat (unsafeDoIO)
import Crypto.Internal.Hex (showHexadecimal)
data Bytes = Bytes (MutableByteArray# RealWorld)
type SecureBytes = SecureMem
instance Show Bytes where
show = bytesShowHex
instance Eq Bytes where
(==) = bytesEq
------------------------------------------------------------------------
newBytes :: Int -> IO Bytes
newBytes (I# sz) = IO $ \s ->
case newAlignedPinnedByteArray# sz 8# s of
(# s', mbarr #) -> (# s', Bytes mbarr #)
touchBytes :: Bytes -> IO ()
touchBytes (Bytes mba) = IO $ \s -> case touch# mba s of s' -> (# s', () #)
sizeofBytes :: Bytes -> Int
sizeofBytes (Bytes mba) = I# (sizeofMutableByteArray# mba)
withPtr :: Bytes -> (Ptr p -> IO a) -> IO a
withPtr b@(Bytes mba) f = do
a <- f (Ptr (byteArrayContents# (unsafeCoerce# mba)))
touchBytes b
return a
------------------------------------------------------------------------
bytesCopyAndModify :: Bytes -> (Ptr a -> IO ()) -> IO Bytes
bytesCopyAndModify src f = do
dst <- newBytes sz
withPtr dst $ \d -> do
withPtr src $ \s -> copyBytes (castPtr d) s sz
f d
return dst
where sz = sizeofBytes src
bytesTemporary :: Int -> (Ptr p -> IO a) -> IO a
bytesTemporary sz f = newBytes sz >>= \ba -> withPtr ba f
bytesCopyTemporary :: Bytes -> (Ptr p -> IO a) -> IO a
bytesCopyTemporary src f = do
dst <- newBytes (sizeofBytes src)
withPtr dst $ \d -> do
withPtr src $ \s -> copyBytes (castPtr d) s (sizeofBytes src)
f d
bytesAlloc :: Int -> (Ptr p -> IO ()) -> IO Bytes
bytesAlloc sz f = do
ba <- newBytes sz
withPtr ba f
return ba
bytesAllocRet :: Int -> (Ptr p -> IO a) -> IO (a, Bytes)
bytesAllocRet sz f = do
ba <- newBytes sz
r <- withPtr ba f
return (r, ba)
bytesLength :: Bytes -> Int
bytesLength = sizeofBytes
withBytes :: Bytes -> (Ptr p -> IO a) -> IO a
withBytes = withPtr
bytesEq :: Bytes -> Bytes -> Bool
bytesEq b1@(Bytes m1) b2@(Bytes m2)
| l1 /= l2 = False
| otherwise = unsafeDoIO $ IO $ \s -> loop 0# s
where
!l1@(I# len) = bytesLength b1
!l2 = bytesLength b2
loop i s
| booleanPrim (i ==# len) = (# s, True #)
| otherwise =
case readWord8Array# m1 i s of
(# s', e1 #) -> case readWord8Array# m2 i s' of
(# s'', e2 #) ->
if booleanPrim (eqWord# e1 e2)
then loop (i +# 1#) s''
else (# s', False #)
bytesIndex :: Bytes -> Int -> Word8
bytesIndex (Bytes m) (I# i) = unsafeDoIO $ IO $ \s ->
case readWord8Array# m i s of
(# s', e #) -> (# s', W8# e #)
{-# NOINLINE bytesIndex #-}
bytesShowHex :: Bytes -> String
bytesShowHex b = showHexadecimal (withPtr b) (bytesLength b)
{-# NOINLINE bytesShowHex #-}

View File

@ -15,9 +15,7 @@ module Crypto.Internal.Words
import Data.Word
import Data.Bits
-- should probably use crypto large word ?
data Word128 = Word128 !Word64 !Word64 deriving (Show, Eq)
import Data.Memory.ExtendedWords
w64to32 :: Word64 -> (Word32, Word32)
w64to32 w = (fromIntegral (w `shiftR` 32), fromIntegral w)

View File

@ -27,7 +27,7 @@ import qualified Crypto.MAC.HMAC as HMAC
import Crypto.Internal.ByteArray (ByteArray)
import qualified Crypto.Internal.ByteArray as B (allocAndFreeze, convert, withByteArray)
import Crypto.Internal.Bytes
import Data.Memory.PtrMethods
-- | The PRF used for PBKDF2
type PRF = B.ByteString -- ^ the password parameters
@ -54,7 +54,7 @@ data Parameters = Parameters
generate :: ByteArray ba => PRF -> Parameters -> ba
generate prf params =
B.allocAndFreeze (outputLength params) $ \p -> do
bufSet p 0 (outputLength params)
memSet p 0 (outputLength params)
loop 1 (outputLength params) p
where
!runPRF = prf (password params)
@ -74,7 +74,7 @@ generate prf params =
let applyMany 0 _ = return ()
applyMany i uprev = do
let uData = runPRF uprev
B.withByteArray uData $ \u -> bufXor p p u hLen
B.withByteArray uData $ \u -> memXor p p u hLen
applyMany (i-1) uData
applyMany (iterCounts params) (salt params `B.append` toBS iterNb)
loop (iterNb+1) (len - hLen) (p `plusPtr` hLen)
@ -83,11 +83,11 @@ generate prf params =
let applyMany 0 _ = return ()
applyMany i uprev = do
let uData = runPRF uprev
B.withByteArray uData $ \u -> bufXor tmp tmp u hLen
B.withByteArray uData $ \u -> memXor tmp tmp u hLen
applyMany (i-1) uData
bufSet tmp 0 hLen
memSet tmp 0 hLen
applyMany (iterCounts params) (salt params `B.append` toBS iterNb)
bufCopy p tmp len
memCopy p tmp len
-- big endian encoding of Word32
toBS :: Word32 -> ByteString

View File

@ -24,9 +24,9 @@ module Crypto.MAC.HMAC
import Crypto.Hash hiding (Context)
import qualified Crypto.Hash as Hash (Context)
import Crypto.Hash.IO
import Crypto.Internal.ByteArray (SecureBytes, ByteArray, ByteArrayAccess)
import Crypto.Internal.ByteArray (ScrubbedBytes, ByteArray, ByteArrayAccess)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Internal.Bytes
import Data.Memory.PtrMethods
import Crypto.Internal.Compat
import Crypto.Internal.Imports
@ -61,9 +61,9 @@ initialize secret = unsafeDoIO (doHashAlg undefined)
!withKey <- case B.length secret `compare` blockSize of
EQ -> return $ B.withByteArray secret
LT -> do key <- B.alloc blockSize $ \k -> do
bufSet k 0 blockSize
B.withByteArray secret $ \s -> bufCopy k s (B.length secret)
return $ B.withByteArray (key :: SecureBytes)
memSet k 0 blockSize
B.withByteArray secret $ \s -> memCopy k s (B.length secret)
return $ B.withByteArray (key :: ScrubbedBytes)
GT -> do
-- hash the secret key
ctx <- hashMutableInitWith alg
@ -74,16 +74,16 @@ initialize secret = unsafeDoIO (doHashAlg undefined)
if digestSize < blockSize
then do
key <- B.alloc blockSize $ \k -> do
bufSet k 0 blockSize
B.withByteArray digest $ \s -> bufCopy k s (B.length digest)
return $ B.withByteArray (key :: SecureBytes)
memSet k 0 blockSize
B.withByteArray digest $ \s -> memCopy k s (B.length digest)
return $ B.withByteArray (key :: ScrubbedBytes)
else
return $ B.withByteArray digest
(inner, outer) <- withKey $ \keyPtr ->
(,) <$> B.alloc blockSize (\p -> bufXorWith p 0x36 keyPtr blockSize)
<*> B.alloc blockSize (\p -> bufXorWith p 0x5c keyPtr blockSize)
return $ Context (hashUpdates initCtx [outer :: SecureBytes])
(hashUpdates initCtx [inner :: SecureBytes])
(,) <$> B.alloc blockSize (\p -> memXorWith p 0x36 keyPtr blockSize)
<*> B.alloc blockSize (\p -> memXorWith p 0x5c keyPtr blockSize)
return $ Context (hashUpdates initCtx [outer :: ScrubbedBytes])
(hashUpdates initCtx [inner :: ScrubbedBytes])
where
blockSize = hashBlockSize alg
digestSize = hashDigestSize alg

View File

@ -26,11 +26,11 @@ module Crypto.MAC.Poly1305
import Foreign.Ptr
import Foreign.C.Types
import Data.Word
import Crypto.Internal.ByteArray (ByteArrayAccess, SecureBytes, Bytes)
import Crypto.Internal.ByteArray (ByteArrayAccess, ScrubbedBytes, Bytes)
import qualified Crypto.Internal.ByteArray as B
-- | Poly1305 Context
newtype Ctx = Ctx SecureBytes
newtype Ctx = Ctx ScrubbedBytes
deriving (ByteArrayAccess)
-- | Poly1305 Auth
@ -79,7 +79,7 @@ updates (Ctx prevCtx) d = Ctx $ B.copyAndFreeze prevCtx (loop d)
-- | finalize the context into a digest bytestring
finalize :: Ctx -> Auth
finalize (Ctx prevCtx) = Auth $ B.allocAndFreeze 16 $ \dst -> do
_ <- B.copy prevCtx (\ctxPtr -> c_poly1305_finalize dst (castPtr ctxPtr)) :: IO SecureBytes
_ <- B.copy prevCtx (\ctxPtr -> c_poly1305_finalize dst (castPtr ctxPtr)) :: IO ScrubbedBytes
return ()
{-# NOINLINE finalize #-}
@ -88,7 +88,7 @@ auth :: (ByteArrayAccess key, ByteArrayAccess ba) => key -> ba -> Auth
auth key d
| B.length key /= 32 = error "Poly1305: key length expected 32 bytes"
| otherwise = Auth $ B.allocAndFreeze 16 $ \dst -> do
_ <- B.alloc 84 (onCtx dst) :: IO SecureBytes
_ <- B.alloc 84 (onCtx dst) :: IO ScrubbedBytes
return ()
where
onCtx dst ctxPtr =

View File

@ -28,11 +28,11 @@ import GHC.Ptr
import Crypto.Internal.Compat
import Crypto.Internal.Imports
import Crypto.Internal.ByteArray (ByteArrayAccess, SecureBytes, Bytes, withByteArray)
import Crypto.Internal.ByteArray (ByteArrayAccess, ScrubbedBytes, Bytes, withByteArray)
import qualified Crypto.Internal.ByteArray as B
-- | A Curve25519 Secret key
newtype SecretKey = SecretKey SecureBytes
newtype SecretKey = SecretKey ScrubbedBytes
deriving (Show,Eq,ByteArrayAccess)
-- | A Curve25519 public key
@ -41,7 +41,7 @@ newtype PublicKey = PublicKey Bytes
-- | A Curve25519 Diffie Hellman secret related to a
-- public key and a secret key.
newtype DhSecret = DhSecret SecureBytes
newtype DhSecret = DhSecret ScrubbedBytes
deriving (Show,Eq,ByteArrayAccess)
-- | Try to build a public key from a bytearray

View File

@ -25,13 +25,13 @@ import Foreign.C.Types
import Crypto.Internal.Compat
import Crypto.Internal.Imports
import Crypto.Internal.Memory
--import Crypto.Internal.Memory
import Crypto.Internal.ByteArray
import qualified Crypto.Internal.ByteArray as B
import Crypto.Error
-- | A P256 scalar
newtype Scalar = Scalar SecureBytes
newtype Scalar = Scalar ScrubbedBytes
deriving (Eq,ByteArrayAccess)
-- | A P256 point

View File

@ -30,13 +30,12 @@ import Foreign.C.Types
import Crypto.Internal.Compat
import Crypto.Internal.Imports
import Crypto.Internal.Memory
import Crypto.Internal.ByteArray (ByteArrayAccess, withByteArray)
import Crypto.Internal.ByteArray (ByteArrayAccess, withByteArray, ScrubbedBytes, Bytes)
import qualified Crypto.Internal.ByteArray as B
import Crypto.Error
-- | An Ed25519 Secret key
newtype SecretKey = SecretKey SecureBytes
newtype SecretKey = SecretKey ScrubbedBytes
deriving (Eq,ByteArrayAccess)
-- | An Ed25519 public key

View File

@ -20,11 +20,11 @@ module Crypto.Random
import Crypto.Random.Types
import Crypto.Random.ChaChaDRG
import Crypto.Random.Entropy
import Crypto.Internal.Memory
import Data.Memory.ByteArray (ScrubbedBytes)
import Crypto.Internal.Imports
drgNew :: IO ChaChaDRG
drgNew = initialize <$> (getEntropy 40 :: IO SecureBytes)
drgNew = initialize <$> (getEntropy 40 :: IO ScrubbedBytes)
drgNewTest :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG
drgNewTest = initializeWords

View File

@ -12,7 +12,7 @@ module Crypto.Random.ChaChaDRG
) where
import Crypto.Random.Types
import Crypto.Internal.ByteArray (ByteArray, SecureBytes)
import Crypto.Internal.ByteArray (ByteArray, ScrubbedBytes)
import qualified Crypto.Internal.ByteArray as B
import Data.Word
import Foreign.Storable (pokeElemOff)
@ -35,7 +35,7 @@ initialize seed = ChaChaDRG $ C.initializeSimple seed
-- | Initialize a new ChaCha context from 5-tuple of words64.
-- This interface is useful when creating a RNG out of tests generators (e.g. QuickCheck).
initializeWords :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG
initializeWords (a,b,c,d,e) = initialize (B.allocAndFreeze 40 fill :: SecureBytes)
initializeWords (a,b,c,d,e) = initialize (B.allocAndFreeze 40 fill :: ScrubbedBytes)
where fill s = mapM_ (uncurry (pokeElemOff s)) [(0,a), (1,b), (2,c), (3,d), (4,e)]
generate :: ByteArray output => Int -> ChaChaDRG -> (output, ChaChaDRG)

View File

@ -14,7 +14,7 @@ module Crypto.Random.EntropyPool
import Control.Concurrent.MVar
import Crypto.Random.Entropy.Unsafe
import Crypto.Internal.ByteArray (ByteArray, SecureBytes)
import Crypto.Internal.ByteArray (ByteArray, ScrubbedBytes)
import qualified Crypto.Internal.ByteArray as B
import Data.Word (Word8)
import Data.Maybe (catMaybes)
@ -23,7 +23,7 @@ import Foreign.Ptr (plusPtr, Ptr)
-- | Pool of Entropy. contains a self mutating pool of entropy,
-- that is always guarantee to contains data.
data EntropyPool = EntropyPool [EntropyBackend] (MVar Int) SecureBytes
data EntropyPool = EntropyPool [EntropyBackend] (MVar Int) ScrubbedBytes
-- size of entropy pool by default
defaultPoolSize :: Int

View File

@ -88,7 +88,6 @@ Library
Crypto.Random.Entropy
Crypto.Random.EntropyPool
Crypto.Random.Entropy.Unsafe
Crypto.Internal.ByteArray
Other-modules: Crypto.Cipher.AES.Primitive
Crypto.Cipher.Blowfish.Box
Crypto.Cipher.Blowfish.Primitive
@ -125,13 +124,11 @@ Library
Crypto.Random.ChaChaDRG
Crypto.PubKey.Internal
Crypto.PubKey.ElGamal
Crypto.Internal.ByteArray
Crypto.Internal.Compat
Crypto.Internal.CompatPrim
Crypto.Internal.Bytes
Crypto.Internal.Endian
Crypto.Internal.Hex
Crypto.Internal.Imports
Crypto.Internal.Memory
Crypto.Internal.Words
Crypto.Internal.WordArray
Build-depends: base >= 4.3 && < 5

View File

@ -16,7 +16,7 @@ import Imports
import Data.Maybe
import Crypto.Error
import Crypto.Cipher.Types
import Crypto.Internal.ByteArray as B
import Data.Memory.ByteArray as B
import qualified Data.ByteString as B
------------------------------------------------------------------------

View File

@ -8,7 +8,7 @@ module Hash
import Crypto.Hash
import qualified Data.ByteString as B
import qualified Crypto.Internal.ByteArray as B (convertHex)
import qualified Data.Memory.ByteArray as B (convertHex)
import Imports
v0,v1,v2 :: ByteString

View File

@ -2,7 +2,7 @@
module KAT_Curve25519 ( tests ) where
import qualified Crypto.PubKey.Curve25519 as Curve25519
import Crypto.Internal.ByteArray as B
import Data.Memory.ByteArray as B
import Imports
alicePrivate = either error id $ Curve25519.secretKey ("\x77\x07\x6d\x0a\x73\x18\xa5\x7d\x3c\x16\xc1\x72\x51\xb2\x66\x45\xdf\x4c\x2f\x87\xeb\xc0\x99\x2a\xb1\x77\xfb\xa5\x1d\xb9\x2c\x2a" :: ByteString)

View File

@ -9,7 +9,7 @@ import Imports
import qualified Crypto.Cipher.ChaCha as ChaCha
import qualified Crypto.Cipher.Salsa as Salsa
import qualified Crypto.MAC.Poly1305 as Poly1305
import qualified Crypto.Internal.ByteArray as B (convert)
import qualified Data.Memory.ByteArray as B (convert)
import qualified Hash
import qualified KAT_HMAC