packages feed

raaz 0.1.1 → 0.2.0

raw patch · 79 files changed

+3100/−1169 lines, 79 filesdep +directorydep +filepathdep +hspec-discoverdep −mtldep ~basedep ~raazPVP ok

version bump matches the API change (PVP)

Dependencies added: directory, filepath, hspec-discover, liquidhaskell, optparse-applicative

Dependencies removed: mtl

Dependency ranges changed: base, raaz

API changes (from Hackage documentation)

- Raaz.Core.DH: class DH d where type Secret d :: * type PublicToken d :: * type SharedSecret d :: * where {
- Raaz.Core.DH: publicToken :: DH d => d -> Secret d -> PublicToken d
- Raaz.Core.DH: sharedSecret :: DH d => d -> Secret d -> PublicToken d -> SharedSecret d
- Raaz.Core.DH: type family SharedSecret d :: *;
- Raaz.Core.DH: }
- Raaz.Core.Memory: class (Monad m, MonadIO m) => MonadMemory m
- Raaz.Core.Memory: data MemoryM a
- Raaz.Core.Memory: instance Control.Monad.IO.Class.MonadIO Raaz.Core.Memory.MemoryM
- Raaz.Core.Memory: instance GHC.Base.Applicative Raaz.Core.Memory.MemoryM
- Raaz.Core.Memory: instance GHC.Base.Functor Raaz.Core.Memory.MemoryM
- Raaz.Core.Memory: instance GHC.Base.Monad Raaz.Core.Memory.MemoryM
- Raaz.Core.Memory: instance Raaz.Core.Memory.Memory mem => Raaz.Core.Memory.MonadMemory (Raaz.Core.Memory.MT mem)
- Raaz.Core.Memory: instance Raaz.Core.Memory.MonadMemory Raaz.Core.Memory.MemoryM
- Raaz.Core.Memory: liftSubMT :: (mem -> submem) -> MT submem a -> MT mem a
- Raaz.Core.Memory: runMT :: Memory mem => MT mem a -> MemoryM a
- Raaz.Core.Primitives: instance GHC.Num.Num (Raaz.Core.Primitives.BLOCKS p)
- Raaz.Core.Primitives: instance GHC.Real.Integral (Raaz.Core.Primitives.BLOCKS p)
- Raaz.Core.Primitives: instance GHC.Real.Real (Raaz.Core.Primitives.BLOCKS p)
- Raaz.Random: class Random a
- Raaz.Random: instance (Raaz.Core.Types.Tuple.Dimension d, Data.Vector.Unboxed.Base.Unbox w, Raaz.Random.Random w) => Raaz.Random.Random (Raaz.Core.Types.Tuple.Tuple d w)
- Raaz.Random: instance (Raaz.Random.Random a, Raaz.Random.Random b) => Raaz.Random.Random (a, b)
- Raaz.Random: instance (Raaz.Random.Random a, Raaz.Random.Random b, Raaz.Random.Random c) => Raaz.Random.Random (a, b, c)
- Raaz.Random: instance (Raaz.Random.Random a, Raaz.Random.Random b, Raaz.Random.Random c, Raaz.Random.Random d) => Raaz.Random.Random (a, b, c, d)
- Raaz.Random: instance (Raaz.Random.Random a, Raaz.Random.Random b, Raaz.Random.Random c, Raaz.Random.Random d, Raaz.Random.Random e) => Raaz.Random.Random (a, b, c, d, e)
- Raaz.Random: instance Raaz.Core.Memory.Memory mem => Raaz.Core.Memory.MonadMemory (Raaz.Random.RT mem)
- Raaz.Random: instance Raaz.Random.Random GHC.Int.Int16
- Raaz.Random: instance Raaz.Random.Random GHC.Int.Int32
- Raaz.Random: instance Raaz.Random.Random GHC.Int.Int64
- Raaz.Random: instance Raaz.Random.Random GHC.Int.Int8
- Raaz.Random: instance Raaz.Random.Random GHC.Types.Int
- Raaz.Random: instance Raaz.Random.Random GHC.Types.Word
- Raaz.Random: instance Raaz.Random.Random GHC.Word.Word16
- Raaz.Random: instance Raaz.Random.Random GHC.Word.Word32
- Raaz.Random: instance Raaz.Random.Random GHC.Word.Word64
- Raaz.Random: instance Raaz.Random.Random GHC.Word.Word8
- Raaz.Random: instance Raaz.Random.Random Raaz.Cipher.ChaCha20.Internal.IV
- Raaz.Random: instance Raaz.Random.Random Raaz.Cipher.ChaCha20.Internal.KEY
- Raaz.Random: instance Raaz.Random.Random w => Raaz.Random.Random (Raaz.Core.Types.Endian.BE w)
- Raaz.Random: instance Raaz.Random.Random w => Raaz.Random.Random (Raaz.Core.Types.Endian.LE w)
- Raaz.Random: liftMT :: MT mem a -> RT mem a
- Raaz.Random: unsafeStorableRandom :: (Memory mem, Storable a) => RT mem a
+ Raaz.Core.ByteSource: instance GHC.Classes.Eq a => GHC.Classes.Eq (Raaz.Core.ByteSource.FillResult a)
+ Raaz.Core.ByteSource: instance GHC.Show.Show a => GHC.Show.Show (Raaz.Core.ByteSource.FillResult a)
+ Raaz.Core.CpuSupports: avx :: Bool
+ Raaz.Core.CpuSupports: avx2 :: Bool
+ Raaz.Core.CpuSupports: sse :: Bool
+ Raaz.Core.CpuSupports: sse2 :: Bool
+ Raaz.Core.CpuSupports: sse3 :: Bool
+ Raaz.Core.CpuSupports: sse4_1 :: Bool
+ Raaz.Core.CpuSupports: sse4_2 :: Bool
+ Raaz.Core.Memory: class MemoryThread (mT :: * -> * -> *)
+ Raaz.Core.Memory: doIO :: MemoryThread mT => IO a -> mT mem a
+ Raaz.Core.Memory: instance Raaz.Core.Memory.MemoryThread Raaz.Core.Memory.MT
+ Raaz.Core.Memory: liftMT :: MemoryThread mT => MT mem a -> mT mem a
+ Raaz.Core.Parse.Applicative: skip :: LengthUnit u => u -> Parser ()
+ Raaz.Core.Types: zipWith :: (Unbox a, Unbox b, Unbox c) => (a -> b -> c) -> Tuple dim a -> Tuple dim b -> Tuple dim c
+ Raaz.Hash.Blake2: blake2b :: PureByteSource src => src -> BLAKE2b
+ Raaz.Hash.Blake2: blake2bFile :: FilePath -> IO BLAKE2b
+ Raaz.Hash.Blake2: blake2bSource :: ByteSource src => src -> IO BLAKE2b
+ Raaz.Hash.Blake2: type BLAKE2b = BLAKE2 Word2b
+ Raaz.Hash.Blake2: type BLAKE2s = BLAKE2 Word2s
+ Raaz.Hash.Blake2.Implementation.CPortable: implementation2b :: Implementation BLAKE2b
+ Raaz.Hash.Blake2.Implementation.CPortable: implementation2s :: Implementation BLAKE2s
+ Raaz.Random: class Storable a => RandomStorable a
+ Raaz.Random: fillRandomElements :: (RandomStorable a, Memory mem) => Int -> Ptr a -> RT mem ()
+ Raaz.Random: instance (Raaz.Core.Types.Tuple.Dimension d, Data.Vector.Unboxed.Base.Unbox w, Raaz.Random.RandomStorable w) => Raaz.Random.RandomStorable (Raaz.Core.Types.Tuple.Tuple d w)
+ Raaz.Random: instance Raaz.Core.Memory.MemoryThread Raaz.Random.RT
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Int.Int16
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Int.Int32
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Int.Int64
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Int.Int8
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Types.Int
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Types.Word
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Word.Word16
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Word.Word32
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Word.Word64
+ Raaz.Random: instance Raaz.Random.RandomStorable GHC.Word.Word8
+ Raaz.Random: instance Raaz.Random.RandomStorable Raaz.Cipher.ChaCha20.Internal.IV
+ Raaz.Random: instance Raaz.Random.RandomStorable Raaz.Cipher.ChaCha20.Internal.KEY
+ Raaz.Random: instance Raaz.Random.RandomStorable w => Raaz.Random.RandomStorable (Raaz.Core.Types.Endian.BE w)
+ Raaz.Random: instance Raaz.Random.RandomStorable w => Raaz.Random.RandomStorable (Raaz.Core.Types.Endian.LE w)
+ Raaz.Random: randomiseCell :: RandomStorable a => RT (MemoryCell a) ()
+ Raaz.Random: unsafeFillRandomElements :: (Memory mem, Storable a) => Int -> Ptr a -> RT mem ()
- Raaz.Core.Memory: execute :: (mem -> IO a) -> MT mem a
+ Raaz.Core.Memory: execute :: MemoryThread mT => (mem -> IO a) -> mT mem a
- Raaz.Core.Memory: getCellPointer :: Storable a => MT (MemoryCell a) (Ptr a)
+ Raaz.Core.Memory: getCellPointer :: (MemoryThread mT, Storable a) => mT (MemoryCell a) (Ptr a)
- Raaz.Core.Memory: getMemory :: MT mem mem
+ Raaz.Core.Memory: getMemory :: MemoryThread mT => mT mem mem
- Raaz.Core.Memory: insecurely :: MonadMemory m => m a -> IO a
+ Raaz.Core.Memory: insecurely :: (MemoryThread mT, Memory mem) => mT mem a -> IO a
- Raaz.Core.Memory: modify :: (Initialisable m a, Extractable m b) => (b -> a) -> MT m ()
+ Raaz.Core.Memory: modify :: (Initialisable mem a, Extractable mem b, MemoryThread mT) => (b -> a) -> mT mem ()
- Raaz.Core.Memory: onSubMemory :: (mem -> submem) -> MT submem a -> MT mem a
+ Raaz.Core.Memory: onSubMemory :: MemoryThread mT => (mem -> submem) -> mT submem a -> mT mem a
- Raaz.Core.Memory: securely :: MonadMemory m => m a -> IO a
+ Raaz.Core.Memory: securely :: (MemoryThread mT, Memory mem) => mT mem a -> IO a
- Raaz.Core.Memory: withCellPointer :: Storable a => (Ptr a -> IO b) -> MT (MemoryCell a) b
+ Raaz.Core.Memory: withCellPointer :: (MemoryThread mT, Storable a) => (Ptr a -> IO b) -> mT (MemoryCell a) b
- Raaz.Random: random :: (Random a, Memory mem) => RT mem a
+ Raaz.Random: random :: (RandomStorable a, Memory mem) => RT mem a

Files

+ CHANGELOG.md view
@@ -0,0 +1,70 @@+# Change log for [raaz].++## [0.2.0] - 24 August, 2017++* Some cpu detection builtin for GCC. Would come handy in future for+  selection of primitives are runtime.+* BLAKE2b, BLAKE2s added.+* system entropy: Experimental support for linux getrandom call+* removed depreciated `liftSubMT` from Memory.+* Got rid of the class `MemoryMonad`, instead introduced a more specific+  `MemoryThread`. This allows to treat monads like `RT mem` much like+  `MT mem`, including possibility of running an action on a sub-memory.+* combinator to randomise memory cells.+* hardened the prg so that a compromise on the current prg state will+  not expose previously generated data.+* OpenBSD/NetBSD: fix incorrect arc4random call.+* Basic Unix man-page for the raaz command.+* Windows support is now included. The missing pieces were system+  entropy and memory locking which is now available.++## [0.1.1] - 2nd  March, 2017++* Failing build on big endian machines (#306) fixed.++## [0.1.0] - 28th February, 2017++* Stream cipher chacha20 added.+* Added a PRG that uses chacha20, seeded with system entropy+* Sha1 highly depreciated in view of reported collision.+* We now have super command `raaz` with subcommands+  - `checksum`: as a replacement for the old checksum executable+  - `rand`: for generating random bytes.++Low level changes++* Reworked alignment considerations.++  - New Alignment type++  - Ways for implementations to demand that the input buffer be aligned+	(mainly to facilitate more efficient SIMD implementations).+++* Num instance from LengthUnit removed, Monoid instance added (See+  issue:#247)+++## [0.0.2] - July 25, 2016.++This release comes with very little changes.++* Encoding: translation between formats using the `translate`+  combinator+* Encoding formats: base64+* Bug fix in base16 character verification (Commit: d6eca4c37b0b)+* Dropped `isSuccessful` from export list of Equality.++## [0.0.1] - June 21, 2016.++* Basic cryptographic types.+* Hashes: sha1, sha256, sha512, sha224, sha384 and their HMACs+* Ciphers: AES-CBC with key-sizes 128, 192 and 256+* Encoding formats: base16++[0.0.1]: <http://github.com/raaz-crypto/raaz/releases/tag/v0.0.1>+[0.0.2]: <http://github.com/raaz-crypto/raaz/releases/tag/v0.0.2>+[0.1.0]: <http://github.com/raaz-crypto/raaz/releases/tag/v0.1.0>+[0.1.1]: <http://github.com/raaz-crypto/raaz/releases/tag/v0.1.1>+[0.2.0]: <http://github.com/raaz-crypto/raaz/releases/tag/v0.2.0>+[raaz]:  <http://github.com/raaz-crypto/raaz/>
+ README.md view
@@ -0,0 +1,71 @@+Raaz: A secure cryptographic library+------------------------------------++[![Build Staus][travis-status]][travis-raaz]+[![Build Windows][appveyor-status]][appveyor-raaz]+[![In Progress][waffle-inprogress]][waffle-raaz]+[![Stackage LTS][stackage-lts-raaz-badge]][stackage-lts-raaz]+[![Stackage Nightly][stackage-nightly-raaz-badge]][stackage-nightly-raaz]+[![Hackage][hackage-badge]][hackage]+[![Hackage Dependencies][hackage-deps-badge]][hackage-deps]+++This is the repository of `raaz`, a Haskell library that implements+some standard cryptographic primitives. This library is the basis on+which we plan to build a cryptographic framework in Haskell. For+example, there are plans to implement some common cryptographic+protocols like `ssh`. Thus applications that require cryptographic+security, in particular secure networking applications can be built+out of this.++Raaz is also an attempt to provide better security guarantees by+making use of Haskell's strong typing. Besides, we put a lot of+emphasis on better API design and good documentation which, we+believe, makes the usage of the library secure.++The word `Raaz` (&#x0930;&#x093E;&#x095B;) stands for secret in Hindi.++Hacking and Discussion+----------------------++* For hacking see our [github repository][repo].++* For discussion see our [google groups][emailgroups] mailing list.++* Hangout on irc.freenode.net (channel: #haskell-raaz).++For details please refer to [our wiki][wiki].++## Releasing and reviewing.++The repository also contains the file Releasing.md which contains+checklist for releasing a new version of the library. Any crypto+library should undergo through review by multiple people. In the file+Reviewing.md, we collect some common pitfalls to look for while+reviewing the code. It is good to actively look for some of the+problems suggested there but of course one should also look for other+problems.+++++[wiki]: <https://github.com/raaz-crypto/raaz/wiki> "Raaz Wiki"+[repo]: <https://github.com/raaz-crypto/raaz> "Raaz on github"++[emailgroups]: <https://groups.google.com/forum/#!forum/hraaz> "Raaz on Google groups"+[waffle-raaz]:   <http://waffle.io/raaz-crypto/raaz>+[waffle-inprogress]: <https://badge.waffle.io/raaz-crypto/raaz.svg?label=waffle%3Ain%20progress&title=In%20Progress>+[travis-status]: <https://secure.travis-ci.org/raaz-crypto/raaz.png> "Build status"+[travis-raaz]: <https://travis-ci.org/raaz-crypto/raaz>+[stackage-lts-raaz]: <http://stackage.org/lts/package/raaz>+[stackage-nightly-raaz]: <http://stackage.org/nightly/package/raaz>++[stackage-lts-raaz-badge]: <http://stackage.org/package/raaz/badge/lts>+[stackage-nightly-raaz-badge]: <http://stackage.org/package/raaz/badge/nightly>++[hackage]:       <https://hackage.haskell.org/package/raaz>+[hackage-badge]: <https://img.shields.io/hackage/v/raaz.svg>+[hackage-deps-badge]: <https://img.shields.io/hackage-deps/v/raaz.svg>+[hackage-deps]: <http://packdeps.haskellers.com/feed?needle=raaz>+[appveyor-status]: <https://ci.appveyor.com/api/projects/status/github/raaz-crypto/raaz?branch=master&svg=true>+[appveyor-raaz]: <https://ci.appveyor.com/project/raaz-crypto/raaz>
Raaz/Cipher/AES.hs view
@@ -1,3 +1,4 @@+-- | The AES block cipher. module Raaz.Cipher.AES        ( AES, KEY128, KEY192, KEY256, IV        -- * Some AES cipher modes.
Raaz/Cipher/AES/CBC/Implementation/CPortable.hs view
@@ -2,6 +2,8 @@ {-# LANGUAGE DataKinds                        #-} {-# LANGUAGE MultiParamTypeClasses            #-} {-# LANGUAGE FlexibleInstances                #-}++-- | Portable C implementation of AES ciphers. module Raaz.Cipher.AES.CBC.Implementation.CPortable        ( aes128cbcI, aes192cbcI, aes256cbcI        ) where
Raaz/Cipher/AES/Internal.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE MultiParamTypeClasses            #-} {-# LANGUAGE TypeFamilies                     #-} +-- | Internals of AES. module Raaz.Cipher.AES.Internal        (-- * AES cipher.          AES(..)@@ -56,15 +57,15 @@ instance Encodable KEY192 instance Encodable KEY256 -instance Random KEY128 where-  random = unsafeStorableRandom+instance RandomStorable KEY128 where+  fillRandomElements = unsafeFillRandomElements  -instance Random KEY192 where-  random = unsafeStorableRandom+instance RandomStorable KEY192 where+  fillRandomElements = unsafeFillRandomElements -instance Random KEY256 where-  random = unsafeStorableRandom+instance RandomStorable KEY256 where+  fillRandomElements = unsafeFillRandomElements  -- | Expects in base 16 instance IsString KEY128 where@@ -96,9 +97,10 @@ newtype IV  = IV (TUPLE 4) deriving (Storable, EndianStore)  instance Encodable IV-instance Random IV where-  random = unsafeStorableRandom +instance RandomStorable IV where+  fillRandomElements = unsafeFillRandomElements+ -- | Expects in base16. instance IsString IV where   fromString = fromBase16@@ -177,8 +179,12 @@  --------------  Memory for storing extended keys --------- +-- | Extended key for aes128 newtype EKEY128 = EKEY128 (TUPLE 44) deriving (Storable, EndianStore)+-- | Extended key for aes192 newtype EKEY192 = EKEY192 (TUPLE 52) deriving (Storable, EndianStore)++-- | Extended key for aes256 newtype EKEY256 = EKEY256 (TUPLE 60) deriving (Storable, EndianStore)  instance Initialisable (MemoryCell EKEY128) KEY128 where
Raaz/Cipher/AES/Recommendation.hs view
@@ -16,11 +16,14 @@ import           Raaz.Cipher.AES.Internal import qualified Raaz.Cipher.AES.CBC.Implementation.CPortable as CPCBC +-- | Recommended implementation of AES-128 cbc instance Recommendation (AES 128 'CBC) where          recommended _ = CPCBC.aes128cbcI +-- | Recommended implementation of AES-192 cbc instance Recommendation (AES 192 'CBC) where          recommended _ = CPCBC.aes192cbcI +-- | Recommended implementation of AES-256 cbc instance Recommendation (AES 256 'CBC) where          recommended _ = CPCBC.aes256cbcI
Raaz/Cipher/ChaCha20.hs view
@@ -1,3 +1,4 @@+-- | The Chacha20 cipher. module Raaz.Cipher.ChaCha20        ( ChaCha20, chacha20, KEY, IV, Counter        ) where
Raaz/Cipher/ChaCha20/Implementation/CPortable.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE FlexibleInstances                #-} {-# LANGUAGE DataKinds                        #-} +-- | Portable C implementation of ChaCha20. module Raaz.Cipher.ChaCha20.Implementation.CPortable        ( implementation, chacha20Random        ) where@@ -14,6 +15,7 @@ import Raaz.Cipher.Internal import Raaz.Cipher.ChaCha20.Internal +-- | The portable c implementation of chacha20 cipher. implementation :: SomeCipherI ChaCha20 implementation  = SomeCipherI chacha20Portable 
Raaz/Cipher/ChaCha20/Internal.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE MultiParamTypeClasses            #-} {-# LANGUAGE TypeFamilies                     #-} +-- | The internals of ChaCha20 ciphers. module Raaz.Cipher.ChaCha20.Internal        ( ChaCha20(..), WORD, Counter(..), IV(..), KEY(..), ChaCha20Mem(..)        ) where@@ -49,7 +50,7 @@ instance IsString KEY where   fromString = fromBase16 -+-- | The type associated with the ChaCha20 cipher. data ChaCha20 = ChaCha20  instance Primitive ChaCha20 where
Raaz/Cipher/ChaCha20/Recommendation.hs view
@@ -78,7 +78,7 @@ -- example the Vector256 implementation handles 2-chacha blocks. Set -- this quantity to the maximum supported by all implementations. randomBufferSize :: BLOCKS ChaCha20-randomBufferSize = 4  `blocksOf` ChaCha20+randomBufferSize = 16  `blocksOf` ChaCha20  -- | Implementations are also designed to work with a specific -- alignment boundary. Unaligned access can slow down the primitives
Raaz/Core/ByteSource.hs view
@@ -16,7 +16,7 @@ import qualified Data.ByteString      as B import qualified Data.ByteString.Lazy as L import           Prelude hiding(length)-import           System.IO            (Handle)+import           System.IO            (Handle, hIsEOF)  import           Raaz.Core.MonoidalAction import           Raaz.Core.Types      (BYTES, Pointer, LengthUnit (..))@@ -32,10 +32,7 @@ -- network sockets or might be just a string in the Haskell. To give a -- uniform interfaces for all such inputs, we define the abstract -- concept of a /byte source/. Essentially a byte source is one from--- which we can fill a buffer with bytes. Depending on the nature of--- the source we have two classes: `ByteSource` which captures bounded--- sources and `InfiniteSource` that captures never ending source of--- bytes.+-- which we can fill a buffer with bytes. -- -- Among instances of `ByteSource`, some like for example -- `B.ByteString` are /pure/ in the sense filling a buffer with bytes@@ -45,9 +42,10 @@ --  -- | This type captures the result of a fill operation.-data FillResult a = Remaining a           -- ^ the buffer is filled completely+data FillResult a = Remaining a           -- ^ There is still bytes left.                   | Exhausted (BYTES Int) -- ^ source exhausted with so much                                           -- bytes read.+                    deriving (Show, Eq)  instance Functor FillResult where   fmap f (Remaining a ) = Remaining $ f a@@ -65,6 +63,14 @@  -- | Abstract byte sources. A bytesource is something that you can use -- to fill a buffer.+--+--  __WARNING:__ The source is required to return `Exhausted` in the+-- boundary case where it has exactly the number of bytes+-- requested. In other words, if the source returns @Remaining@ on any+-- particular request, there should be at least 1 additional byte left+-- on the source for the next request. Cryptographic block primitives+-- have do certain special processing for the last block and it is+-- required to know whether the last block has been read or not. class ByteSource src where   -- | Fills a buffer from the source.   fillBytes :: BYTES Int  -- ^ Buffer size@@ -72,9 +78,6 @@             -> Pointer  -- ^ Buffer pointer             -> IO (FillResult src) ---  default fillBytes :: InfiniteSource src => BYTES Int ->  src -> Pointer -> IO (FillResult src)---  fillBytes sz src pointer = Remaining <$> slurp sz src pointer- -- | A version of fillBytes that takes type safe lengths as input. fill :: ( LengthUnit len         , ByteSource src@@ -86,30 +89,6 @@ fill = fillBytes . inBytes {-# INLINE fill #-} -{------ | Never ending stream of bytes. The reads to the stream might get--- delayed but it will always return the number of bytes that were--- asked for.-class InfiniteSource src where-  slurpBytes :: BYTES Int -- ^ bytes to read,-             -> src       -- ^ the source to fill from,-             -> Pointer   -- ^ the buffer source to fill.-             -> IO src----- | A version of slurp that takes type safe lengths as input.-slurp :: ( LengthUnit len-         , InfiniteSource src-         )-       => len-       -> src-       -> Pointer-       -> IO src-slurp = slurpBytes . inBytes----}- -- | Process data from a source in chunks of a particular size. processChunks :: ( MonadIO m, LengthUnit chunkSize, ByteSource src)               => m a                 -- action on a complete chunk,@@ -136,18 +115,19 @@  ----------------------- Instances of byte source ----------------------- +-- | __WARNING:_ The `fillBytes` may block. instance ByteSource Handle where   {-# INLINE fillBytes #-}   fillBytes sz hand cptr = do-            count <- hFillBuf hand cptr sz-            return-              (if count < sz then Exhausted count-                             else Remaining hand)+    count <- hFillBuf hand cptr sz+    eof   <- hIsEOF hand+    if eof then return $ Exhausted count+      else return $ Remaining hand  instance ByteSource B.ByteString where   {-# INLINE fillBytes #-}-  fillBytes sz bs cptr | l < sz    = do unsafeCopyToPointer bs cptr-                                        return $ Exhausted l+  fillBytes sz bs cptr | l <= sz    = do unsafeCopyToPointer bs cptr+                                         return $ Exhausted l                        | otherwise = do unsafeNCopyToPointer sz bs cptr                                         return $ Remaining rest        where l    = length bs@@ -157,7 +137,6 @@   {-# INLINE fillBytes #-}   fillBytes sz bs = fmap (fmap L.fromChunks) . fillBytes sz (L.toChunks bs) - instance ByteSource src => ByteSource (Maybe src) where   {-# INLINE fillBytes #-}   fillBytes sz ma cptr = maybe exhausted fillIt ma@@ -169,9 +148,13 @@   fillBytes sz (x:xs) cptr = do     result <- fillBytes sz x cptr     case result of-      Exhausted rbytes -> let nptr = rbytes <.> cptr-                          in  fillBytes (sz - rbytes) xs nptr       Remaining nx     -> return $ Remaining $ nx:xs+      Exhausted bytesX -> let nptr              = bytesX <.> cptr+                              whenXSExhausted bytesXS = return $ Exhausted $ bytesX + bytesXS+                              whenXSRemains           = return . Remaining+                           in fillBytes (sz - bytesX) xs nptr+                              >>= withFillResult whenXSRemains whenXSExhausted+  --------------------- Instances of pure byte source -------------------- 
Raaz/Core/Constants.hs view
@@ -1,3 +1,4 @@+-- | Some constants used by raaz. module Raaz.Core.Constants        ( l1Cache        ) where
+ Raaz/Core/CpuSupports.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE ForeignFunctionInterface #-}++-- | This module gives functions that check at runtime whether the+-- underlying cpu supports given features. CPU features are+-- architecture specific. However, functions from this module are+-- guaranteed to be defined always -- they return `False` for+-- incompatible architecture. For example, the flag `avx2` is relevant+-- only for a an X86 architecture. So it is defined false, for say the+-- ARM architecture.++module Raaz.Core.CpuSupports+       ( sse, sse2, sse3+       , sse4_1, sse4_2+       , avx, avx2+       ) where++import Foreign.C+import System.IO.Unsafe(unsafePerformIO)++foreign import ccall unsafe "raaz_supports_sse"+  c_sse :: IO CInt++foreign import ccall unsafe "raaz_supports_sse2"+  c_sse2 :: IO CInt++foreign import ccall unsafe "raaz_supports_sse3"+  c_sse3 :: IO CInt+++foreign import ccall unsafe "raaz_supports_sse4_1"+  c_sse4_1 :: IO CInt+++foreign import ccall unsafe "raaz_supports_sse4_2"+  c_sse4_2 :: IO CInt++foreign import ccall unsafe "raaz_supports_avx"+  c_avx :: IO CInt++foreign import ccall unsafe "raaz_supports_avx2"+  c_avx2 :: IO CInt+++{-# NOINLINE gccBuiltInToBool #-}++gccBuiltInToBool :: IO CInt -> Bool+gccBuiltInToBool = unsafePerformIO . fmap (>0)++-- | Check whether the cpu supports sse extension.+sse :: Bool+sse = gccBuiltInToBool c_sse++-- | Check whether the cpu supports sse2 extension.+sse2 :: Bool+sse2 = gccBuiltInToBool c_sse2++-- | Check whether the cpu supports sse3 extension.+sse3 :: Bool+sse3 = gccBuiltInToBool c_sse3++-- | Check whether the cpu supports sse4_1 extension.+sse4_1 :: Bool+sse4_1 = gccBuiltInToBool c_sse4_1++-- | Check whether the cpu supports sse-4.2 extension.+sse4_2 :: Bool+sse4_2 = gccBuiltInToBool c_sse4_2++-- | Check whether the cpu supports avx extension.+avx :: Bool+avx = gccBuiltInToBool c_avx++-- | Check whether the cpu supports avx2 extension.+avx2 :: Bool+avx2 = gccBuiltInToBool c_avx2
− Raaz/Core/DH.hs
@@ -1,23 +0,0 @@--- | This module provides an abstract interface for Diffie Hellman Key Exchange.--{-# LANGUAGE TypeFamilies               #-}--module Raaz.Core.DH-       ( DH(..) ) where---- | The DH (Diffie-Hellman) typeclass provides an interface for key---  exchanges. 'Secret' represents the secret generated by each party---  & known only to itself. 'PublicToken' represents the token---  generated from the 'Secret' which is sent to the other party.--- 'SharedSecret' represents the common secret generated by both---  parties from the respective public tokens. 'publicToken' takes the---  generator of the group and a secret and generates the public token.--- 'sharedSecret' takes the generator of the group, secret of one party---  and public token of the other party and generates the shared secret.-class DH d where-  type Secret d       :: *-  type PublicToken d  :: *-  type SharedSecret d :: *--  publicToken   :: d -> Secret d -> PublicToken d-  sharedSecret  :: d -> Secret d -> PublicToken d -> SharedSecret d
Raaz/Core/Encode.hs view
@@ -1,3 +1,4 @@+-- | Encoding and decoding values to formats. module Raaz.Core.Encode        ( -- * Encoding of binary data.          -- $encodable$@@ -23,19 +24,49 @@ -- operations. There are two main classes that capture the essence of -- encoding. ----- [`Format`] Each encoding supported by this module is an instance of---     this class. For printing and for easy inclusion in source code---     appropriate instances of `Show` and `Data.String.IsString` is---     provided for these types.+-- [`Format`:] The class of all types that are encoding formats to binary+--     data. They are all instances of `Show` and `Data.String.IsString` for+--     ease of printing and inclusion in source code. ----- [`Encodable`] Instances of this class are those that can be encoded---    into any of the available formats. Actual encoding and decoding---    of elements of this class can be done by the combinators---    `encode` and `decode`+-- [`Encodable`:] The class of all types that can be encoded /into/ binary. ----- The raaz library exposes many instances of `Format` which are all--- some form of encoding of binary data.+-- The combinators `encode` and `decode` allows encoding any instance of `Encodable` to+-- any of the instances of `Format`. --+-- == Sample code that makes use of Base16 encoding.+--+-- > theAnswer :: LE Word64+-- > theAnswer = 42+-- >+-- > main = do putStr "The answer to life, universe and everything is:"+-- >           print answserInBase16+-- >    where answerInBase16 :: Base16+-- >          answerInBase16 = encode theAnswer+-- >+-- > checkAnswer :: Base16 -> Bool+-- > checkAnswer = maybe False (==theAnswer) . decode+-- >+-- > checkAnswerBS :: ByteString -> Bool+-- > checkAnswerBS = checkAnswer . fromString+--+-- In the above example, @`LE` Word64@, which captures 64-bit unsigned+-- integers is an instance of Encode (but not Word64). The encode+-- combinator then converts in into the type Base16 that is an+-- instance of `Format`. The print then uses the `Show` instance of+-- Base16 to print it as a sequence of hexadecimal+-- characters. Similarly the decode combinator in @checkAnswer@+-- decodes a base16 before comparing with the answer.+--+-- == Liberal @IsString@ instances+--+-- Certain ascii printable formats like Base16 and Base64 have a more+-- liberal `IsString` instance: they typically allow the use of spaces+-- and newline in the input to the `fromString` function . This allows+-- a more readable representation of these types when using the+-- @OverloadedStrings@ extension. See the documentation of the+-- corresponding instance declarations to see what characters are+-- ignored. However, all `Show` instance of formats are strict in the+-- sense that they do not produce any such extraneous characters.  -- | Encode in a given format. encode :: (Encodable a, Format fmt) => a -> fmt
Raaz/Core/Encode/Base16.hs view
@@ -11,7 +11,7 @@  import Data.ByteString as B import Data.ByteString.Char8 as C8-import Data.ByteString.Internal (c2w )+import Data.ByteString.Internal (c2w)  import Data.ByteString.Unsafe(unsafeIndex) import Data.Monoid@@ -27,34 +27,34 @@ -- `IsString` instance. The combinators `fromBase16` and `showBase16` -- are exposed mainly to make these definitions easy. ----- The base16 encoding only produces valid hex characters. However, to--- aid easy presentation of long hexadecimal strings, a user can add--- add arbitrary amount of spaces, newlines and the character ':'. The--- decoding ignores these characters.+ newtype Base16 = Base16 {unBase16 :: ByteString} deriving (Eq, Monoid)  -- Developers note: Internally base16 just stores the bytestring as -- is. The conversion happens when we do an encode and decode of -- actual base16.+-- + instance Encodable Base16 where   toByteString          = hex . unBase16    fromByteString bs-    | odd (B.length bs) = Nothing-    | badCharacter bs   = Nothing-    | otherwise         = Just $ Base16 $ unsafeFromHex bs-    where badCharacter  = C8.any (not . isHexDigit)--  unsafeFromByteString  = Base16 . unsafeFromHex-+    | B.length bs `mod` 2 /= 0 = Nothing+    | validInput bs            = Just $ Base16 $ unsafeFromHex bs+    | otherwise                = Nothing+    where validInput  = C8.all isHexDigit+  unsafeFromByteString bs+    | B.length bs `mod` 2 /= 0 = error "base16 encoding is always of even size"+    | otherwise                = Base16 $ unsafeFromHex bs  instance Show Base16 where   show = C8.unpack . toByteString +-- | Ignores spaces and ':' (colon). instance IsString Base16 where-  fromString = unsafeFromByteString . fromString-+  fromString = unsafeFromByteString . C8.filter (not . useless) . fromString+    where useless c = isSpace c || c == ':'  instance Format Base16 where   encodeByteString = Base16@@ -63,8 +63,13 @@   decodeFormat     = unBase16   {-# INLINE decodeFormat #-} --- TODO: Since the encoding to base16 is usually used for user interaction+-- Since the encoding to base16 is usually used for user interaction -- we can afford to be slower here.+--+-- TODO (Liquid Haskell)+--+{--@ hex :: inp:ByteString -> { bs : ByteString | bslen bs = 2 * bslen inp } @-}+-- hex :: ByteString -> ByteString hex  bs = fst $ B.unfoldrN (2 * B.length bs) gen 0     where gen i | rm == 0   = Just (hexDigit $ top4 w, i+1)@@ -72,6 +77,10 @@             where (idx, rm) = quotRem i 2                   w         = unsafeIndex bs idx ++++ hexDigit :: Word8 -> Word8 hexDigit x | x < 10    = c2w '0' + x            | otherwise = c2w 'a' + (x - 10)@@ -79,15 +88,9 @@ top4 :: Word8 -> Word8; top4 x  = x `shiftR` 4 bot4 :: Word8 -> Word8; bot4 x  = x  .&. 0x0F -+{-@ unsafeFromHex :: {bs : ByteString | (bslen bs) mod 2 == 0 } -> ByteString @-} unsafeFromHex :: ByteString -> ByteString-unsafeFromHex  = unsafeFromHexP . C8.filter (not . useless)-  where useless c = isSpace c || c == ':'--unsafeFromHexP :: ByteString -> ByteString-unsafeFromHexP bs-  | odd (B.length bs) = error "base16 encoding is always of even size"-  | otherwise         = fst $ B.unfoldrN len gen 0+unsafeFromHex bs = fst $ B.unfoldrN len gen 0   where len   = B.length bs `quot` 2         gen i = Just (shiftL w0 4 .|. w1, i + 1)           where w0 = fromHexWord $ unsafeIndex bs (2 * i)
Raaz/Core/Encode/Base64.hs view
@@ -17,10 +17,7 @@   -- | The type corresponding to the standard padded base-64 binary--- encoding.  The base-64 encoding only produces valid base-64--- characters. However, to aid easy presentation of long base-64--- strings, a user can add add arbitrary amount of spaces and--- newlines. The decoding ignores these characters.+-- encoding. newtype Base64 = Base64 {unBase64 :: ByteString} deriving (Eq, Monoid)  -- Developers note: Internally base16 just stores the bytestring as@@ -33,17 +30,13 @@   fromByteString bs     | B.null bs                = Just $ Base64 B.empty     | B.length bs `rem` 4 /= 0 = Nothing-    | badCharacter bs'         = Nothing-    | not (isB64OrPad pl)      = Nothing-    | not (isB64OrPad pf)      = Nothing-    | otherwise                = Just $ Base64 $ unsafeFromB64 bs-    where pl           = C8.last bs-          pf           = C8.last $ C8.init bs-          bs'          = C8.init $ C8.init bs-          badCharacter = C8.any (not . isB64Char)-          isB64Char c  = isAlpha c || isDigit c || c == '+' || c == '/'-          isB64OrPad c = isB64Char c || c == '='+    | okeyPad                  = Just $ Base64 $ unsafeFromB64 bs+    | otherwise                = Nothing+    where padPart     = C8.dropWhile isB64Char bs+          okeyPad     = padPart == C8.empty || padPart == C8.singleton '=' || padPart == C8.pack "=="+          isB64Char c = isAlpha c || isDigit c || c == '+' || c == '/' +   unsafeFromByteString bs | B.null bs = Base64 B.empty                           | otherwise = Base64 $ unsafeFromB64 bs @@ -51,9 +44,9 @@ instance Show Base64 where   show = C8.unpack . toByteString +-- | Ignores spaces and newlines. instance IsString Base64 where-  fromString = unsafeFromByteString . fromString-+  fromString = unsafeFromByteString . C8.filter (not . isSpace) . fromString  instance Format Base64 where   encodeByteString = Base64@@ -111,8 +104,15 @@         | otherwise                    = error $ "oops unB64:" ++ [w2c w]  --- TODO: Since the encoding to base16 is usually used for user interaction+++-- Since the encoding to base16 is usually used for user interaction -- we can afford to be slower here.++-- TODO (Liquid Haskell)+--+{--@ toB64 :: ByteString -> { bs : ByteString | (bslen bs) mod 4 == 0 @-}+-- toB64 :: ByteString -> ByteString toB64 bs = fst (B.unfoldrN (4*n) gen 0) <> padding     where gen i    = Just (byte i, i + 1)@@ -152,11 +152,7 @@   unsafeFromB64 :: ByteString -> ByteString-unsafeFromB64 = unsafeFromB64P . C8.filter (not . useless)-  where useless = isSpace--unsafeFromB64P :: ByteString -> ByteString-unsafeFromB64P bs = fst (B.unfoldrN (3*n) gen 0) <> unPad+unsafeFromB64 bs = fst (B.unfoldrN (3*n) gen 0) <> unPad   where n         = B.length bs `quot` 4 - 1         gen i     = Just (byte i, i + 1)         at blk i  = unsafeIndex bs $ 4 * blk + i
Raaz/Core/Encode/Internal.hs view
@@ -23,20 +23,30 @@   -- | The type class `Encodable` captures all the types that can be--- encoded into a stream of bytes. By making a type say @Foo@ an--- instance of the `Encodable` class, we get for free methods to--- encode it in any of the supported formats (i.e. instances of the--- class `Format`).+-- encoded into a stream of bytes. For a user defined type say @Foo@,+-- defining an instance `Encodable` is all that is required to make+-- use of `encode` and `decode` for any of the supported encoding+-- formats (i.e. instances of the class `Format`). -- -- Minimum complete definition for this class is `toByteString` and -- `fromByteString`. Instances of `EndianStore` have default -- definitions for both these functions and hence a trivial instance -- declaration is sufficient for such types. --+-- > newtype Foo = Foo (LE Word64) deriving (Storable, EndianStore) -- >+-- > instance EndianStore Foo where+-- >   ...+-- > -- > instance Encodable Foo -- > --+-- In particular, all the endian encoded versions of Haskell's word,+-- i.e types like @`LE` Word32@, @`LE` Word64@ etc, are instances of+-- `Encodable`. Note that the corresponding plain type is /not/ an+-- instance of `Encodable` because encoding of say `Word32` without+-- specifying whether the endianness is meaningless.+-- class Encodable a where   -- | Convert stuff to bytestring   toByteString          :: a           -> ByteString@@ -60,6 +70,7 @@    unsafeFromByteString = fromMaybe (error "fromByteString error") . fromByteString +instance Encodable Word8 instance Encodable (LE Word32) instance Encodable (LE Word64) instance Encodable (BE Word32)
Raaz/Core/Memory.hs view
@@ -20,21 +20,22 @@        -- * The Memory subsystem.        -- $memorysubsystem$ -       -- ** Initialisation and Extraction.-       -- $init-extract$+       -- ** Memory elements.          Memory(..), VoidMemory, copyMemory+       -- *** Initialisation and Extraction.+       -- $init-extract$        , Initialisable(..), Extractable(..)        , InitialisableFromBuffer(..), ExtractableToBuffer(..)        -- *** A basic memory cell.        , MemoryCell, withCellPointer, getCellPointer-       -- *** Actions on memory elements.-       , MT,  execute, getMemory, onSubMemory, liftSubMT,  modify++       -- ** Memory threads.+       , MemoryThread(..), doIO , getMemory, modify, execute+       , MT        -- **** Some low level `MT` actions.         , liftPointerAction-       -- ** Generic memory monads.-       , MonadMemory(..)-       , MemoryM, runMT+        -- ** Memory allocation        ,  Alloc, pointerAlloc        ) where@@ -50,12 +51,15 @@ -- $memorysubsystem$ -- -- Cryptographic operations often need to keep sensitive information--- in its memory space. If this memory is swapped out to the disk,--- this can be dangerous. The primary purpose of the memory subsystem--- is to provide a way to allocate and manage /secure memory/,--- i.e. memory that will not be swapped out during the execution of--- the process and will be wiped clean after use. There are there--- important parts to the memory subsystem:+-- like private keys in its memory space. Such sensitive information+-- can leak to the external would if the memory where the data is+-- stored is swapped out to a disk. What makes this particularly+-- dangerous is that the data can reside on the disk almost+-- permanently and might even survive when the hardware is+-- scrapped. The primary purpose of the memory subsystem is to provide+-- a way to allocate and manage /secure memory/, i.e. memory that will+-- not be swapped out as long as the memory is used and will be wiped+-- clean after use. It consists of the following components: -- -- [The `Memory` type class:] A memory element is some type that holds -- an internal buffer inside it.@@ -65,21 +69,18 @@ -- types gives a high level interface for memory allocation. For a -- memory type `mem`, the type `Alloc mem` can be seen as the -- _allocation strategy_ for mem. For example, one of the things that--- it keeps track of the space required to create an memory element of--- type `mem`. There is a natural applicative instance for `Alloc`+-- it keeps track of is the space required to create an memory element+-- of type `mem`. There is a natural applicative instance for `Alloc` -- which helps build the allocation strategy for a compound memory -- type from its components in a modular fashion _without_ explicit -- size calculation or offset computation. ----- [The `MonadMemory` class:] Instances of these classes are actions--- that use some kind of memory elements, i.e. instances of the class--- `Memory`, inside it. Any such monad can either be run using the--- combinator `securely` or the combinator `insecurely`. If one use--- the combinator `securely`, then all allocations done during the run--- is from a locked memory pool which is wiped clean before--- de-allocation. The types `MT` and `MemoryM` are two instances that--- we expose from this library.---+-- [`MemoryThread`s:] Instances of this class are actions that use+-- some kind of memory elements inside it. Such a thread can be run+-- using the combinator `securely` or the combinator `insecurely`. If+-- one use the combinator `securely`, then the allocation of the+-- memory element to be used by the action is done using a locked+-- memory pool which is wiped clean before de-allocation.  -- $init-extract$ --@@ -91,93 +92,114 @@ -- indicate it with an instance of @`Extractable` mem a@. -- -- There is an inherent danger in initialising and extracting pure--- values out of memory. Pure values are stored on the Haskell stack+-- values out of memory. Pure values are stored on the Haskell heap -- and hence can be swapped out. Consider a memory element @mem@ that -- stores some sensitive information, say for example the unencrypted--- private key. Now suppose that we need to extracting out the key as--- a pure value before its encryption and storage into the key file,--- it is likely that the key is swapped out to the disk as part of the--- haskell heap.+-- private key. Suppose we extract this key out of the memory element+-- as a pure value before its encryption and storage into the key+-- file. It is likely that the key is swapped out to the disk as the+-- extracted key is part of the the haskell heap. -- -- The `InitialiseFromBuffer` (`ExtractableToBuffer`) class gives an -- interface for reading from (writing to) buffers directly minimising -- the chances of inadvertent exposure of sensitive information from -- the Haskell heap due to swapping. --- | A class that captures monads that use an internal memory element.------ Any instance of `MonadMemory` can be executed `securely` in which--- case all allocations are performed from a locked pool of--- memory. which at the end of the operation is also wiped clean--- before deallocation.------ Systems often put tight restriction on the amount of memory a--- process can lock.  Therefore, secure memory is often to be used--- judiciously. Instances of this class /should/ also implement the--- the combinator `insecurely` which allocates all memory from an--- unlocked memory pool.------ This library exposes two instances of `MonadMemory`------ 1. /Memory threads/ captured by the type `MT`, which are a sequence--- of actions that use the same memory element and------ 2. /Memory actions/ captured by the type `MemoryM`.------ /WARNING:/ Be careful with `liftIO`.------ The rule of thumb to follow is that the action being lifted should--- itself never unlock any memory. In particular, the following code--- is bad because the `securely` action unlocks some portion of the--- memory after @foo@ is executed.++-- | An action of type @`MT` mem a@ is an action that uses internally+-- a single memory object of type @mem@ and returns a result of type+-- @a@. All the actions are performed on a single memory element and+-- hence the side effects persist. It is analogues to the @ST@ monad.+newtype MT mem a = MT { unMT :: mem -> IO a }+++instance Functor (MT mem) where+  fmap f mst = MT $ \ m -> f <$> unMT mst m++instance Applicative (MT mem) where+  pure       = MT . const . pure+  mf <*> ma  = MT $ \ m -> unMT mf m <*> unMT ma m++instance Monad (MT mem) where+  return    =  MT . const . return+  ma >>= f  =  MT runIt+    where runIt mem = unMT ma mem >>= \ a -> unMT (f a) mem++-- | __WARNING:__ do not lift a secure memory action.+instance MonadIO (MT mem) where+  liftIO = MT . const++-- | A class that captures abstract "memory threads". A memory thread+-- can either be run `securely` or `insecurely`. Pure IO actions can+-- be run inside a memory thread using the @runIO@.  However, the IO+-- action that is being run /must not/ directly or indirectly run a+-- `secure` action ever. In particular, the following code is bad. ----- >--- >  liftIO $ securely $ foo+-- > -- BAD EXAMPLE: DO NOT USE.+-- > runIO $ securely $ foo -- > -- -- On the other hand the following code is fine -- -- >--- > liftIO $ insecurely $ someMemoryAction+-- > runIO $ insecurely $ someMemoryAction -- > ----- Whether an @IO@ action unlocks memory is difficult to keep track--- of; for all you know, it might be a FFI call that does an--- @memunlock@.--- -- As to why this is dangerous, it has got to do with the fact that -- @mlock@ and @munlock@ do not nest correctly. A single @munlock@ can--- unlock multiple calls of @mlock@ on the same page.+-- unlock multiple calls of @mlock@ on the same page.  Whether a given+-- @IO@ action unlocks memory is difficult to keep track of; for all+-- you know, it might be a FFI call that does an @memunlock@. Hence,+-- currently there is no easy way to enforce this. ---class (Monad m, MonadIO m) => MonadMemory m where-  -- | Perform the memory action where all memory elements are allocated-  -- locked memory. All memory allocated will be locked and hence will-  -- never be swapped out by the operating system. It will also be wiped-  -- clean before releasing.++class MemoryThread (mT :: * -> * -> *) where+  -- | Run a memory action with the internal memory allocated from a+  -- locked memory buffer. This memory buffer will never be swapped+  -- out by the operating system and will be wiped clean before+  -- releasing.   --   -- Memory locking is an expensive operation and usually there would be   -- a limit to how much locked memory can be allocated. Nonetheless,   -- actions that work with sensitive information like passwords should   -- use this to run an memory action.-  securely   :: m a -> IO a+  securely   :: Memory mem => mT mem a -> IO a +  -- | Run a memory action with the internal memory used by the action+  -- being allocated from unlocked memory. Use this function when you+  -- work with data that is not sensitive to security considerations+  -- (for example, when you want to verify checksums of files).+  insecurely :: Memory mem => mT mem a -> IO a -  -- | Perform the memory action where all memory elements are-  -- allocated unlocked memory. Use this function when you work with-  -- data that is not sensitive to security considerations (for example,-  -- when you want to verify checksums of files).-  insecurely :: m a -> IO a+  -- | Lift an actual memory thread.+  liftMT :: MT mem a -> mT mem a  --- | An action of type @`MT` mem a@ is an action that uses internally--- a a single memory object of type @mem@ and returns a result of type--- @a@. All the actions are performed on a single memory element and--- hence the side effects persist. It is analogues to the @ST@--- monad.-newtype MT mem a = MT { unMT :: mem -> IO a }+  -- | Combinator that allows us to run a memory action on a+  -- sub-memory element. A sub-memory of @submem@ of a memory element+  -- @mem@ is given by a projection @proj : mem -> submem@. The action+  -- @onSubMemory proj@ lifts the a memory thread on the sub element+  -- to the compound element.+  --+  onSubMemory :: (mem -> submem) -> mT submem a -> mT mem a ++instance MemoryThread MT where+  securely               = withSecureMemory . unMT+  insecurely             = withMemory . unMT+  liftMT                 = id+  onSubMemory proj mtsub = MT $ unMT mtsub . proj+ ------------- Lifting pointer actions ----------------------------- +-- | Run a given memory action in the memory thread.+execute :: MemoryThread mT => (mem -> IO a) -> mT mem a+execute = liftMT . MT++-- | Perform an IO action inside the memory thread.+doIO :: MemoryThread mT => IO a -> mT mem a+doIO = execute . const+ -- | A pointer action inside a monad @m@ is some function that takes a -- pointer action of type @Pointer -> m a@ and supplies it with an -- appropriate pointer. In particular, memory allocators are pointer@@ -191,95 +213,10 @@  -- TODO: This is a very general pattern needs more exploration. ---- | Run a given memory action in the memory thread.-execute :: (mem -> IO a) -> MT mem a-{-# INLINE execute #-}-execute = MT--getMemory :: MT mem mem+-- | Get the underlying memory element of the memory thread.+getMemory :: MemoryThread mT => mT mem mem getMemory = execute return --- | The combinator @onSubMemory@ allows us to run a memory action on a--- sub-memory element. Given a memory element of type @mem@ and a--- sub-element of type @submem@ which can be obtained from the--- compound memory element of type @mem@ using the projection @proj@,--- then @onSubMemory proj@ lifts the a memory thread of the sub--- element to the compound element.----onSubMemory :: (mem -> submem) -- ^ Projection from the compound element-                               -- to sub memory element.-            -> MT submem a     -- ^ Memory thread of the sub-element.-            -> MT mem    a-onSubMemory proj mt' = execute $ unMT mt' . proj--{-# DEPRECATED liftSubMT "use onSubMemory instead" #-}--- | Alternate name for onSubMemory.-liftSubMT :: (mem -> submem)-          -> MT submem a-          -> MT mem    a-liftSubMT = onSubMemory---instance Functor (MT mem) where-  fmap f mst = MT $ \ m -> f <$> unMT mst m--instance Applicative (MT mem) where-  pure       = MT . const . pure-  mf <*> ma  = MT $ \ m -> unMT mf m <*> unMT ma m--instance Monad (MT mem) where-  return    =  MT . const . return-  ma >>= f  =  MT runIt-    where runIt mem = unMT ma mem >>= \ a -> unMT (f a) mem--instance MonadIO (MT mem) where-  liftIO = MT . const--instance Memory mem => MonadMemory (MT mem) where--  securely   = withSecureMemory . unMT-  insecurely = withMemory       . unMT---- | A runner of a memory state thread.-type    Runner mem b = MT mem b -> IO b---- | A memory action that uses some sort of memory element--- internally.-newtype MemoryM a = MemoryM-   { unMemoryM :: (forall mem b. Memory mem => Runner mem b) -> IO a }---instance Functor MemoryM where-  fmap f mem = MemoryM $ \ runner -> f <$> unMemoryM mem runner--instance Applicative MemoryM where-  pure  x       = MemoryM $ \ _ -> return x-  -- Beware: do not follow the hlint suggestion. The ugly definition-  -- is to avoid usage of impredicative polymorphism.--  memF <*> memA = MemoryM $ \ runner ->  unMemoryM memF runner <*> unMemoryM memA runner--instance Monad MemoryM where-  return = pure-  memA >>= f    = MemoryM $ \ runner -> do a <- unMemoryM memA runner-                                           unMemoryM (f a) runner--instance MonadIO MemoryM where-  liftIO io = MemoryM $ \ _ -> io-  -- Beware: do not follow the hlint suggestion. The ugly definition-  -- is to avoid usage of impredicative polymorphism.--instance MonadMemory MemoryM  where--  securely   mem = unMemoryM mem securely-  insecurely mem = unMemoryM mem insecurely----- | Run the memory thread to obtain a memory action.-runMT :: Memory mem => MT mem a -> MemoryM a-runMT mem = MemoryM $ \ runner -> runner mem- ------------------------ A memory allocator -----------------------  @@ -334,9 +271,10 @@ data VoidMemory = VoidMemory { unVoidMemory :: Pointer  }  instance Memory VoidMemory where-  memoryAlloc      = makeAlloc (0 :: BYTES Int) $ VoidMemory+  memoryAlloc      = makeAlloc (0 :: BYTES Int) VoidMemory   unsafeToPointer  = unVoidMemory + instance ( Memory ma, Memory mb ) => Memory (ma, mb) where     memoryAlloc             = (,) <$> memoryAlloc <*> memoryAlloc     unsafeToPointer (ma, _) =  unsafeToPointer ma@@ -434,8 +372,8 @@ -- > modify f = do b          <- extract -- >               initialise $  f b ---modify :: (Initialisable m a, Extractable m b) =>  (b -> a) -> MT m ()-modify f = extract >>= initialise . f+modify :: (Initialisable mem a, Extractable mem b, MemoryThread mT ) =>  (b -> a) -> mT mem ()+modify f = liftMT $ extract >>= initialise . f  -- | A memory type that can be initialised from a pointer buffer. The initialisation performs -- a direct copy from the input buffer and hence the chances of the@@ -449,7 +387,6 @@ class Memory m => ExtractableToBuffer m where   extractor :: m -> WriteM (MT m) - --------------------- Some instances of Memory --------------------  -- | A memory location to store a value of type having `Storable`@@ -472,15 +409,15 @@  -- | Work with the underlying pointer of the memory cell. Useful while -- working with ffi functions.-withCellPointer :: Storable a => (Ptr a -> IO b) -> MT (MemoryCell a) b+withCellPointer :: (MemoryThread mT, Storable a) => (Ptr a -> IO b) -> mT (MemoryCell a) b {-# INLINE withCellPointer #-} withCellPointer action = execute $ action . actualCellPtr   -- | Get the pointer associated with the given memory cell.-getCellPointer :: Storable a => MT (MemoryCell a) (Ptr a)+getCellPointer :: (MemoryThread mT, Storable a) => mT (MemoryCell a) (Ptr a) {-# INLINE getCellPointer #-}-getCellPointer = actualCellPtr <$> getMemory+getCellPointer = liftMT $ actualCellPtr <$> getMemory  instance Storable a => Initialisable (MemoryCell a) a where   initialise a = execute $ flip pokeAligned a . unMemoryCell
Raaz/Core/Parse/Applicative.hs view
@@ -7,6 +7,7 @@        , parseVector, parseStorableVector        , unsafeParseVector, unsafeParseStorableVector        , parseByteString+       , skip        ) where  import           Data.ByteString           (ByteString)@@ -30,6 +31,10 @@  makeParser :: LengthUnit l => l -> (Pointer -> IO a) -> Parser a makeParser l action = TwistRF (liftToFieldM action) $ inBytes l++-- | Skip over some data.+skip :: LengthUnit u => u -> Parser ()+skip = flip makeParser $ const $ return ()  -- | A parser that fails with a given error message. parseError  :: String -> Parser a
Raaz/Core/Primitives.hs view
@@ -75,7 +75,7 @@                -> BLOCKS prim                -> (Pointer -> IO b)                -> IO b-allocBufferFor imp l  = allocaAligned (bufferStartAlignment imp) l+allocBufferFor imp  = allocaAligned $ bufferStartAlignment imp  -- | Some primitives like ciphers have an encryption/decryption key. This -- type family captures the key associated with a primitive if it has@@ -91,7 +91,7 @@ -- long as they can be converted to bytes. This can avoid a lot of -- tedious and error prone length calculations. newtype BLOCKS p = BLOCKS {unBLOCKS :: Int}-                 deriving (Show, Eq, Ord, Enum, Real, Num, Integral)+                 deriving (Show, Eq, Ord, Enum)  instance Monoid (BLOCKS p) where   mempty      = BLOCKS 0
Raaz/Core/Types/Pointer.hs view
@@ -2,8 +2,8 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE ForeignFunctionInterface   #-}-{-# LANGUAGE CPP                        #-} + -- | This module exposes types that builds in type safety into some of -- the low level pointer operations. The functions here are pretty low -- level and will be required only by developers of the library that@@ -106,13 +106,13 @@ -- | Type safe lengths/offsets in units of bytes. newtype BYTES a  = BYTES a         deriving ( Show, Eq, Equality, Ord, Enum, Integral-                 , Real, Num, Storable+                 , Real, Num, Storable, Bounded                  )  -- | Type safe lengths/offsets in units of bits. newtype BITS  a  = BITS  a         deriving ( Show, Eq, Equality, Ord, Enum, Integral-                 , Real, Num, Storable+                 , Real, Num, Storable, Bounded                  )  -- | Type safe length unit that measures offsets in multiples of word@@ -169,7 +169,7 @@   where n = atLeast l         -- Alignment adjusted to word boundary.         algn = wordAlignment   <> a-        pad  = atLeast $ BYTES  $ unAlignment $ algn+        pad  = atLeast $ BYTES  $ unAlignment algn   -- | Express length unit @src@ in terms of length unit @dest@ rounding@@ -285,6 +285,18 @@ pokeAligned     :: Storable a => Ptr a -> a -> IO () pokeAligned ptr =  poke $ nextAlignedPtr ptr +-------------------------- Allocation  ---------------------------++-- | A less general version of `allocaAligned` where the pointer passed+-- is aligned to word boundary.+allocaBuffer :: LengthUnit l+             => l                  -- ^ buffer length+             -> (Pointer -> IO b)  -- ^ the action to run+             -> IO b+{-# INLINE allocaBuffer #-}+allocaBuffer = allocaAligned wordAlignment++ -- | The expression @allocaAligned a l action@ allocates a local -- buffer of length @l@ and alignment @a@ and passes it on to the IO -- action @action@. No explicit freeing of the memory is required as@@ -300,7 +312,23 @@   where BYTES     b = inBytes l         Alignment a = algn +----------------- Secure allocation --------------------------------- +-- | A less general version of `allocaSecureAligned` where the pointer passed+-- is aligned to word boundary+allocaSecure :: LengthUnit l+             => l+             -> (Pointer -> IO b)+             -> IO b+allocaSecure = allocaSecureAligned wordAlignment++foreign import ccall unsafe "raaz/core/memory.h raazMemorylock"+  c_mlock :: Pointer -> BYTES Int -> IO Int++foreign import ccall unsafe "raaz/core/memory.h raazMemoryunlock"+  c_munlock :: Pointer -> BYTES Int -> IO ()++ -- | This function allocates a chunk of "secure" memory of a given -- size and runs the action. The memory (1) exists for the duration of -- the action (2) will not be swapped during that time and (3) will be@@ -322,15 +350,9 @@                     -> (Pointer -> IO a)                     -> IO a -#ifdef HAVE_MLOCK -foreign import ccall unsafe "sys/mman.h mlock"-  c_mlock :: Pointer -> BYTES Int -> IO Int  -foreign import ccall unsafe "sys/mman.h munlock"-  c_munlock :: Pointer -> BYTES Int -> IO ()- allocaSecureAligned a l action = allocaAligned a l actualAction   where sz = inBytes l         actualAction cptr = let@@ -338,27 +360,6 @@                          when (c /= 0) $ fail "secure memory: unable to lock memory"           releaseIt =  memset cptr 0 l >>  c_munlock cptr sz           in bracket_ lockIt releaseIt $ action cptr--#else-allocaSecureAligned _ _ = fail "memory locking not supported on this platform"--#endif--- | A less general version of `allocaAligned` where the pointer passed--- is aligned to word boundary.-allocaBuffer :: LengthUnit l-             => l                  -- ^ buffer length-             -> (Pointer -> IO b)  -- ^ the action to run-             -> IO b-{-# INLINE allocaBuffer #-}-allocaBuffer = allocaAligned wordAlignment---- | A less general version of `allocaSecureAligned` where the pointer passed--- is aligned to word boundary-allocaSecure :: LengthUnit l-             => l-             -> (Pointer -> IO b)-             -> IO b-allocaSecure = allocaSecureAligned wordAlignment  -- | Creates a memory of given size. It is better to use over -- @`mallocBytes`@ as it uses typesafe length.
Raaz/Core/Types/Tuple.hs view
@@ -9,10 +9,11 @@ {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE TypeOperators         #-} +-- | Tuples of unboxed values with type level length encoding. module Raaz.Core.Types.Tuple        ( -- * Length encoded tuples          Tuple, Dimension, dimension, initial, diagonal-       , repeatM+       , repeatM, zipWith          -- ** Unsafe operations        , unsafeFromList        ) where@@ -29,7 +30,7 @@ import           GHC.TypeLits import           Foreign.Ptr                 ( castPtr, Ptr ) import           Foreign.Storable            ( Storable(..) )-import           Prelude hiding              ( length       )+import           Prelude hiding              ( length, zipWith )   import Raaz.Core.Types.Equality@@ -49,7 +50,6 @@ instance (V.Unbox a, Equality a) => Eq (Tuple dim a) where   (==) = (===) - -- | Function to make the type checker happy getA :: Tuple dim a -> a getA _ = undefined@@ -62,13 +62,18 @@ -- | The constaint on the dimension of the tuple (since base 4.7.0) type Dimension (dim :: Nat) = KnownNat dim +{-@ assume natValInt :: Dimension dim => proxy dim -> { v : Int | v == dim } @-}+natValInt :: Dimension dim => proxy dim -> Int+natValInt = fromEnum . natVal+ -- | This combinator returns the dimension of the tuple.+{-@ dimension :: Dimension dim  => Raaz.Core.Types.Tuple.Tuple dim a -> {n: Int | n == dim } @-} dimension  :: Dimension dim => Tuple dim a -> Int dimensionP :: Dimension dim            => Proxy dim            -> Tuple dim a            -> Int-dimensionP sz _ = fromEnum $ natVal sz+dimensionP sz _ = natValInt sz dimension = dimensionP Proxy  #else@@ -77,8 +82,8 @@ type Dimension (dim :: Nat) = SingI dim  -- | This combinator returns the dimension of the tuple.-dimension  :: (V.Unbox a, Dimension  dim) => Tuple dim a -> Int-dimensionP :: (Dimension dim, V.Unbox a)+dimension  :: Dimension dim => Tuple dim a -> Int+dimensionP :: Dimension dim            => Sing dim            -> Tuple dim a            -> Int@@ -133,16 +138,19 @@  -- | Construct a tuple by repeating a monadic action. repeatM :: (Functor m, Monad m, V.Unbox a, Dimension dim) => m a -> m (Tuple dim a)-repeatM action = result-  where result = Tuple <$> V.replicateM sz action-        sz     = dimension $ getTup result-        getTup :: (Monad m, Dimension n)=> m (Tuple n a) -> Tuple n a-        getTup _ = undefined+repeatM = mkTupM undefined+  where mkTupM :: (Functor m, V.Unbox a, Monad m, Dimension dim) => Tuple dim a -> m a -> m (Tuple dim a)+        mkTupM uTup action = Tuple <$> V.replicateM (dimension uTup) action + -- | Construct a tuple out of the list. This function is unsafe and -- will result in run time error if the list is not of the correct -- dimension.+{-@ unsafeFromList :: (V.Unbox a, Dimension dim)+                   => { xs:[a] | len xs = dim }+                   -> Raaz.Core.Types.Tuple.Tuple dim a +@-} unsafeFromList :: (V.Unbox a, Dimension dim) => [a] -> Tuple dim a unsafeFromList xs   | dimension tup == L.length xs = tup@@ -152,15 +160,28 @@  -- | Computes the initial fragment of a tuple. No length needs to be given -- as it is infered from the types.+{-@ lazy initial @-} initial ::  (V.Unbox a, Dimension dim0)          => Tuple dim1 a          -> Tuple dim0 a-initial tup = tup0-  where tup0 = Tuple $ V.take (dimension tup0) $ unTuple tup+initial = mkTuple undefined+  where mkTuple :: (V.Unbox a, Dimension dim0) => Tuple dim0 a -> Tuple dim1 a  -> Tuple dim0 a+        mkTuple uTup tup = Tuple $ V.take (dimension uTup) $ unTuple tup  -- TODO: Put a constraint that dim0 <= dim1  -- | The @diagonal a@ gives a tuple, all of whose entries is @a@. diagonal :: (V.Unbox a, Dimension dim) => a -> Tuple dim a-diagonal a = tup-  where tup = Tuple $ V.replicate (dimension tup) a+diagonal = mkTup undefined+  where mkTup :: (V.Unbox a, Dimension dim) => Tuple dim a -> a -> Tuple dim a+        mkTup uTup a = Tuple $ V.replicate (dimension uTup) a+++-- | A zipwith function for tuples++zipWith :: (V.Unbox a, V.Unbox b, V.Unbox c)+        => (a -> b -> c)+        -> Tuple dim a+        -> Tuple dim b+        -> Tuple dim c+zipWith f (Tuple at) (Tuple bt)= Tuple $ V.zipWith f at bt
Raaz/Hash.hs view
@@ -18,7 +18,7 @@        , HMAC, hmac, hmacFile, hmacSource          -- * Exposing individual hashes.          -- $individualHashes$-+       , module Raaz.Hash.Blake2        , module Raaz.Hash.Sha224        , module Raaz.Hash.Sha256        , module Raaz.Hash.Sha384@@ -28,6 +28,8 @@        ) where  -- import Raaz.Hash.Blake256++import Raaz.Hash.Blake2 import Raaz.Hash.Sha224 import Raaz.Hash.Sha256 import Raaz.Hash.Sha384@@ -38,12 +40,7 @@  -- $computingHash$ ----- === NOTE: SHA1 is broken. ----- SHA1 is no more available form this module, its use is highly--- depreciated. If you want to use it for transition please import--- Raaz.Hash.Sha1 specifically- -- The cryptographic hashes provided by raaz give the following -- guarantees: --@@ -60,6 +57,13 @@ -- The functions `hash`, `hashFile`, and `hashSource` provide a rather -- high level interface for computing hashes. For hmacs the associated -- functions are `hmac`, `hmacFile`, and `hmacSource`+--+-- === NOTE: SHA1 is broken.+--+-- SHA1 is no more available form this module, its use is highly+-- depreciated. If you want to use it for transition please import+-- Raaz.Hash.Sha1 specifically+  -- $encoding$ --
+ Raaz/Hash/Blake2.hs view
@@ -0,0 +1,39 @@+{-|++This module exposes combinators to compute the BLAKE2b hash and the+associated HMAC for some common types.++-}++module Raaz.Hash.Blake2+       ( -- * The BLAKE2 cryptographic hashes+         BLAKE2b, BLAKE2s+       , blake2b, blake2bFile, blake2bSource+       ) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L++import Raaz.Core++import Raaz.Hash.Internal        ( hashSource, hash, hashFile       )+import Raaz.Hash.Blake2.Internal+import Raaz.Hash.Blake2.Recommendation()++-- | Compute the blake2b hash of an instance of `PureByteSource`. Use+-- this for computing the sha1 hash of a strict or lazy byte string.+blake2b       :: PureByteSource src => src -> BLAKE2b+blake2b       = hash+++{-# SPECIALIZE blake2b :: B.ByteString -> BLAKE2b #-}+{-# SPECIALIZE blake2b :: L.ByteString -> BLAKE2b #-}+++-- | Compute the blake2b hash of a file.+blake2bFile   :: FilePath -> IO BLAKE2b+blake2bFile   = hashFile++-- | Compute the blake2b hash of a general byte source.+blake2bSource :: ByteSource src => src -> IO BLAKE2b+blake2bSource = hashSource
+ Raaz/Hash/Blake2/Implementation/CPortable.hs view
@@ -0,0 +1,98 @@+{-# LANGUAGE ForeignFunctionInterface   #-}+-- | The portable C-implementation of SHA1+module Raaz.Hash.Blake2.Implementation.CPortable+       ( implementation2b+       , implementation2s+       ) where++import Foreign.Ptr              ( Ptr )+import Data.Word+import Raaz.Core+import Raaz.Hash.Internal+import Raaz.Hash.Blake2.Internal++-- | The portable C implementation of BLAKE2b.+implementation2b :: Implementation BLAKE2b+implementation2b =  SomeHashI cPortable2b++-- | The portable C implementation of BLAKE2s.+implementation2s :: Implementation BLAKE2s+implementation2s =  SomeHashI cPortable2s+++cPortable2b :: HashI BLAKE2b Blake2bMem+cPortable2b = blake2bImplementation+              "blake2b-cportable"+              "BLAKE2b Implementation using portable C and Haskell FFI"+              compressIt+              c_blake2b_last+  where compressIt ptr = c_blake2b_compress ptr . fromEnum+++cPortable2s :: HashI BLAKE2s Blake2sMem+cPortable2s = blake2sImplementation+              "blake2s-cportable"+              "BLAKE2s Implementation using portable C and Haskell FFI"+              compressIt+              c_blake2s_last+  where compressIt ptr = c_blake2s_compress ptr . fromEnum++++++------------------------- FFI For Blake2b -------------------------------------++foreign import ccall unsafe+  "raaz/hash/blake2/common.h raazHashBlake2bPortableBlockCompress"+  c_blake2b_compress  :: Pointer+                      -> Int+                      -> Ptr (BYTES Word64)+                      -> Ptr (BYTES Word64)+                      -> Ptr BLAKE2b+                      -> IO ()++foreign import ccall unsafe+  "raaz/hash/blake2/common.h raazHashBlake2bPortableLastBlock"+  c_blake2b_last   :: Pointer+                   -> BYTES Int+                   -> BYTES Word64+                   -> BYTES Word64+                   -> Word64+                   -> Word64+                   -> Ptr BLAKE2b+                   -> IO ()+++------------------------- FFI For Blake2s -------------------------------------+++foreign import ccall unsafe+  "raaz/hash/blake2/common.h raazHashBlake2sPortableBlockCompress"+  c_blake2s_compress  :: Pointer+                      -> Int+                      -> BYTES Word64+                      -> Ptr BLAKE2s+                      -> IO ()++foreign import ccall unsafe+  "raaz/hash/blake2/common.h raazHashBlake2sPortableLastBlock"+  c_blake2s_last   :: Pointer+                   -> BYTES Int+                   -> BYTES Word64+                   -> Word32+                   -> Word32+                   -> Ptr BLAKE2s+                   -> IO ()++{-++void raazHashBlake2bPortableBlockCompress( Block2b *mesg, int nblocks,+					   Word2b *Upper, Word2b *Lower,+					   Blake2b h)++void raazHashBlake2bPortableLastBlock( Block2b mesg, int nbytes,+				       Word2b upper, Word2b lower,+				       Word2b f0 , Word2b f1,+				       Blake2b h)+-}
+ Raaz/Hash/Blake2/Internal.hs view
@@ -0,0 +1,272 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE RecordWildCards            #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE ForeignFunctionInterface   #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# CFILES raaz/hash/sha1/portable.c    #-}++-- | Internal types and function for blake2 hashes.+module Raaz.Hash.Blake2.Internal+       ( -- * The blake2 types+         BLAKE2, BLAKE2b, BLAKE2s+       , Blake2bMem, Blake2sMem+       , blake2Pad, blake2bImplementation+       , blake2sImplementation+       ) where++import           Control.Applicative+import           Control.Monad.IO.Class+import           Data.Bits           ( xor, complement )+import           Data.Monoid+import           Data.String+import           Data.Word+import           Foreign.Ptr         ( Ptr          )+import           Foreign.Storable    ( Storable(..) )+import           Prelude      hiding ( zipWith      )++import           Raaz.Core+import           Raaz.Core.Transfer+import           Raaz.Hash.Internal++----------------------------- The blake2 type ---------------------------------++-- | The BLAKE2 type.+newtype BLAKE2 w = BLAKE2 (Tuple 8 w)+               deriving (Eq, Equality, Storable, EndianStore)++-- | Word type for Blake2b+type Word2b = LE Word64++-- | Word type for Blake2s+type Word2s = LE Word32++-- | The BLAKE2b hash type.+type BLAKE2b = BLAKE2 Word2b++-- | The BLAKE2s hash type.+type BLAKE2s = BLAKE2 Word2s++instance Encodable BLAKE2b+instance Encodable BLAKE2s+++instance IsString BLAKE2b where+  fromString = fromBase16++instance IsString BLAKE2s where+  fromString = fromBase16++instance Show BLAKE2b where+  show =  showBase16++instance Show BLAKE2s where+  show =  showBase16++instance Primitive BLAKE2b where+  blockSize _ = BYTES 128+  type Implementation BLAKE2b = SomeHashI BLAKE2b++instance Hash BLAKE2b where+  additionalPadBlocks _ = toEnum 1++instance Primitive BLAKE2s where+  blockSize _ = BYTES 64+  type Implementation BLAKE2s = SomeHashI BLAKE2s++instance Hash BLAKE2s where+  additionalPadBlocks _ = toEnum 1++-- | The initial value to start the blake2b hashing. This is equal to+-- the iv `xor` the parameter block.+hash2b0 :: BLAKE2b+hash2b0 = BLAKE2 $ unsafeFromList [ 0x6a09e667f3bcc908 `xor` 0x01010040+                                  , 0xbb67ae8584caa73b+                                  , 0x3c6ef372fe94f82b+                                  , 0xa54ff53a5f1d36f1+                                  , 0x510e527fade682d1+                                  , 0x9b05688c2b3e6c1f+                                  , 0x1f83d9abfb41bd6b+                                  , 0x5be0cd19137e2179+                                  ]++-- | The initial value to start the blake2b hashing. This is equal to+-- the iv `xor` the parameter block.+hash2s0 :: BLAKE2s+hash2s0 = BLAKE2 $ unsafeFromList [ 0x6a09e667 `xor` 0x01010020+                                  , 0xbb67ae85+                                  , 0x3c6ef372+                                  , 0xa54ff53a+                                  , 0x510e527f+                                  , 0x9b05688c+                                  , 0x1f83d9ab+                                  , 0x5be0cd19+                                  ]++---------------------------------- Memory element for BLAKE2b -----------------------++-- | Memory element for BLAKE2b implementations.+data Blake2bMem = Blake2bMem { blake2bCell :: MemoryCell BLAKE2b+                             , uLengthCell :: MemoryCell (BYTES Word64)+                             , lLengthCell :: MemoryCell (BYTES Word64)+                             }+++instance Memory Blake2bMem where+  memoryAlloc     = Blake2bMem <$> memoryAlloc <*> memoryAlloc <*> memoryAlloc+  unsafeToPointer = unsafeToPointer . blake2bCell++instance Initialisable Blake2bMem () where+  initialise _ = do onSubMemory blake2bCell  $ initialise hash2b0+                    onSubMemory uLengthCell  $ initialise (0 :: BYTES Word64)+                    onSubMemory lLengthCell  $ initialise (0 :: BYTES Word64)++instance Extractable Blake2bMem BLAKE2b where+  extract = onSubMemory blake2bCell extract++---------------------------------- Memory element for BLAKE2b -----------------------++-- | Memory element for BLAKE2s implementations.+data Blake2sMem = Blake2sMem { blake2sCell :: MemoryCell BLAKE2s+                             , lengthCell  :: MemoryCell (BYTES Word64)+                             }++instance Memory Blake2sMem where+  memoryAlloc     = Blake2sMem <$> memoryAlloc <*> memoryAlloc+  unsafeToPointer = unsafeToPointer . blake2sCell++instance Initialisable Blake2sMem () where+  initialise _ = do onSubMemory blake2sCell $ initialise hash2s0+                    onSubMemory lengthCell  $ initialise (0 :: BYTES Word64)++instance Extractable Blake2sMem BLAKE2s where+  extract = onSubMemory blake2sCell extract++----------------------- Padding for Blake code ------------------------------++-- | The generic blake2 padding algorithm.+blake2Pad :: (Primitive prim, MonadIO m)+          => prim      -- ^ the primitive (BLAKE2b or BLAKE2s).+          -> BYTES Int -- ^ length of the message+          -> WriteM m+blake2Pad prim = padWrite 0 (blocksOf 1 prim) . skipWrite++++----------------------- Create a blake2b implementation ---------------------+type Compress2b =  Pointer            -- ^ Buffer+                -> BLOCKS BLAKE2b     -- ^ number of blocks+                -> Ptr (BYTES Word64) -- ^ Upper count+                -> Ptr (BYTES Word64) -- ^ Lower+                -> Ptr BLAKE2b+                -> IO ()++type Last2b =  Pointer+            -> BYTES Int+            -> BYTES Word64 -- Upper+            -> BYTES Word64 -- Lower+            -> Word64       -- f0+            -> Word64       -- f1+            -> Ptr BLAKE2b+            -> IO ()+++-- | Create a hash implementation form BLAKE2b given a compression+-- function and the last block function.+blake2bImplementation :: String  -- ^ Name+                      -> String  -- ^ Description+                      -> Compress2b+                      -> Last2b+                      -> HashI BLAKE2b Blake2bMem+blake2bImplementation nm descr compress2b last2b+  = HashI { hashIName              = nm+          , hashIDescription       = descr+          , compress               = comp+          , compressFinal          = final+          , compressStartAlignment = 32  --  Allow gcc to use vector instructions+          }+  where comp buf blks = do uPtr   <- onSubMemory uLengthCell getCellPointer+                           lPtr   <- onSubMemory lLengthCell getCellPointer+                           hshPtr <- onSubMemory blake2bCell getCellPointer+                           liftIO $ compress2b buf blks uPtr lPtr hshPtr++        lastBlock buf r = do u      <- onSubMemory uLengthCell extract+                             l      <- onSubMemory lLengthCell extract+                             hshPtr <- onSubMemory blake2bCell getCellPointer+                             let f0 = complement 0+                                 f1 = 0+                               in  liftIO $ last2b buf r u l f0 f1 hshPtr++        final buf nbytes = unsafeWrite blake2bPad buf >> finalPadded buf nbytes+          where blake2bPad = blake2Pad (undefined :: BLAKE2b) nbytes++        finalPadded buf nbytes+          | nbytes == 0 = lastBlock buf 0  -- only when actual input is empty.+          | otherwise   = let+              (blks,r)       =  bytesQuotRem nbytes+              blksToCompress = if r == 0 then blks <> toEnum (-1) else blks+              remBytes       = if r > 0 then r else inBytes $ blocksOf 1 (undefined :: BLAKE2b)+              lastBlockPtr   = buf `movePtr` blksToCompress+              in do comp buf blksToCompress+                    lastBlock lastBlockPtr remBytes++------------------------- Implementations of blake2s ---------------------------------------------++type Compress2s =  Pointer            -- ^ Buffer+                -> BLOCKS BLAKE2s     -- ^ number of blocks+                -> BYTES Word64       -- ^ length of the message so far+                -> Ptr BLAKE2s        -- ^ Hash pointer+                -> IO ()++type Last2s =  Pointer+            -> BYTES Int+            -> BYTES Word64+            -> Word32       -- f0+            -> Word32       -- f1+            -> Ptr BLAKE2s+            -> IO ()++-- | Create a hash implementation form BLAKE2s given a compression+-- function and the last block function.+blake2sImplementation :: String  -- ^ Name+                      -> String  -- ^ Description+                      -> Compress2s+                      -> Last2s+                      -> HashI BLAKE2s Blake2sMem+blake2sImplementation nm descr compress2s last2s+  = HashI { hashIName              = nm+          , hashIDescription       = descr+          , compress               = comp+          , compressFinal          = final+          , compressStartAlignment = 32  --  Allow gcc to use vector instructions+          }+  where comp buf blks = do len    <- onSubMemory lengthCell  extract    -- extract current length++                           hshPtr <- onSubMemory blake2sCell getCellPointer+                           liftIO $ compress2s buf blks len hshPtr++                           let increment :: BYTES Word64+                               increment = fromIntegral $ inBytes blks -- update the length by blks+                               in onSubMemory lengthCell $ modify (+increment)+++        lastBlock buf r = do len    <- onSubMemory lengthCell extract+                             hshPtr <- onSubMemory blake2sCell getCellPointer+                             let f0 = complement 0+                                 f1 = 0+                               in liftIO $ last2s buf r len f0 f1 hshPtr++        final buf nbytes = unsafeWrite blake2sPad buf >> finalPadded buf nbytes+          where blake2sPad = blake2Pad (undefined :: BLAKE2s) nbytes++        finalPadded buf nbytes+          | nbytes == 0 = lastBlock buf 0  -- only when actual input is empty.+          | otherwise   = let+              (blks,r)       =  bytesQuotRem nbytes+              blksToCompress = if r == 0 then blks <> toEnum (-1) else blks+              remBytes       = if r > 0 then r else inBytes $ blocksOf 1 (undefined :: BLAKE2s)+              lastBlockPtr   = buf `movePtr` blksToCompress+              in do comp buf blksToCompress+                    lastBlock lastBlockPtr remBytes
+ Raaz/Hash/Blake2/Recommendation.hs view
@@ -0,0 +1,22 @@+-- | This sets up the recommended implementation of Sha1.+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE FlexibleInstances #-}+--+-- The orphan instance declaration separates the implementation and+-- setting the recommended instances. Therefore, we ignore the warning.+--++module Raaz.Hash.Blake2.Recommendation where++import Raaz.Core+import Raaz.Hash.Blake2.Internal+import qualified Raaz.Hash.Blake2.Implementation.CPortable as CPortable+++-- | Recommended implementation for blake2b.+instance Recommendation BLAKE2b where+  recommended _ = CPortable.implementation2b++-- | Recommended implementation for balke2s.+instance Recommendation BLAKE2s where+  recommended _ = CPortable.implementation2s
Raaz/Hash/Internal.hs view
@@ -36,6 +36,7 @@  import qualified Data.ByteString      as B import qualified Data.ByteString.Lazy as L+import           Data.Monoid import           Data.Word import           Foreign.Storable import           System.IO@@ -236,8 +237,8 @@     comp                = compress ptr bufSize     finish bytes        = compressFinal ptr bytes >> extract     in processChunks comp finish src bufSize ptr-  where bufSize             = atLeast l1Cache + 1-        totalSize           = bufSize + additionalPadBlocks undefined+  where bufSize             = atLeast l1Cache <> toEnum 1+        totalSize           = bufSize <> additionalPadBlocks undefined         allocate            = liftPointerAction $ allocBufferFor (SomeHashI imp) totalSize  ----------------------- Hash memory ----------------------------------
Raaz/Hash/Internal/HMAC.hs view
@@ -88,8 +88,8 @@   load             = peek   adjustEndian _ _ = return () -instance (Hash h, Recommendation h) => Random (HMACKey h) where-  random = unsafeStorableRandom+instance (Hash h, Recommendation h) => RandomStorable (HMACKey h) where+  fillRandomElements = unsafeFillRandomElements  instance (Hash h, Recommendation h) => Encodable (HMACKey h) @@ -130,18 +130,18 @@ {-# SPECIALIZE hmac :: (Hash h, Recommendation h) => Key (HMAC h) -> B.ByteString -> HMAC h #-} {-# SPECIALIZE hmac :: (Hash h, Recommendation h) => Key (HMAC h) -> L.ByteString -> HMAC h #-} --- | Compute the hash of file.+-- | Compute the hmac of file. hmacFile :: (Hash h, Recommendation h)-         => Key (HMAC h)-         -> FilePath  -- ^ File to be hashed+         => Key (HMAC h) -- ^ Key to use for mac-ing+         -> FilePath     -- ^ File to be hashed          -> IO (HMAC h) hmacFile key fileName = withBinaryFile fileName ReadMode $ hmacSource key {-# INLINEABLE hmacFile #-} --- | Compute the hash of a generic byte source.+-- | Compute the hmac of a generic byte source. hmacSource :: ( Hash h, Recommendation h, ByteSource src )-           => Key (HMAC h)-           -> src  -- ^ Message+           => Key (HMAC h)  -- ^ key to use for mac-ing.+           -> src           -- ^ Message            -> IO (HMAC h) hmacSource = go undefined   where go :: (Hash h, Recommendation h, ByteSource src)@@ -152,7 +152,7 @@ {-# SPECIALIZE hmacSource :: (Hash h, Recommendation h) => Key (HMAC h) -> Handle -> IO (HMAC h) #-}  --- | Compute the hash of a pure byte source like, `B.ByteString`.+-- | Compute the hmac of a pure byte source like, `B.ByteString`. hmac' :: ( Hash h, Recommendation h, PureByteSource src )       => Implementation h       -> Key (HMAC h)@@ -174,7 +174,7 @@   #-}  --- | Compute the hash of file.+-- | Compute the hmac of file. hmacFile' :: (Hash h, Recommendation h)          => Implementation h          -> Key (HMAC h)@@ -183,7 +183,7 @@ hmacFile' impl key fileName = withBinaryFile fileName ReadMode $ hmacSource' impl key {-# INLINEABLE hmacFile' #-} -+-- | Compute the hmac of a generic ByteSource using a given implementation. hmacSource' :: (Hash h, Recommendation h, ByteSource src)             => Implementation h             -> Key (HMAC h)@@ -196,7 +196,7 @@     initialise ()     allocate $ \ ptr -> do       liftIO $ unsafeCopyToPointer innerFirstBlock ptr-      compress hI ptr 1+      compress hI ptr $ toEnum 1      -- Finish it by hashing the source.     innerHash <- completeHashing hI src@@ -206,12 +206,12 @@     initialise ()     allocate $ \ ptr -> do       liftIO $ unsafeCopyToPointer outerFirstBlock ptr-      compress hI ptr 1+      compress hI ptr $ toEnum 1      -- Finish it with hashing the  hash computed above     HMAC <$> completeHashing hI (toByteString innerHash) -  where allocate = liftPointerAction $ allocBufferFor imp $ 1 `asTypeOf` (theBlock key)+  where allocate = liftPointerAction $ allocBufferFor imp $ (toEnum 1) `asTypeOf` (theBlock key)         innerFirstBlock = B.map (xor 0x36) $ hmacAdjustKey key         outerFirstBlock = B.map (xor 0x5c) $ hmacAdjustKey key         theBlock :: Key (HMAC h) -> BLOCKS h
Raaz/Hash/Sha/Util.hs view
@@ -2,10 +2,9 @@ {-# LANGUAGE FlexibleContexts           #-} {-# LANGUAGE ConstraintKinds            #-} +-- | Some utility functions useful for all Sha hashes. module Raaz.Hash.Sha.Util        ( shaImplementation-       -- ** Writing message lengths.-       -- $lengthwrites$        , length64Write        , length128Write        , Compressor
Raaz/Hash/Sha1/Internal.hs view
@@ -53,4 +53,4 @@   type Implementation SHA1 = SomeHashI SHA1  instance Hash SHA1 where-  additionalPadBlocks _ = 1+  additionalPadBlocks _ = toEnum 1
Raaz/Hash/Sha1/Recommendation.hs view
@@ -11,5 +11,6 @@ import Raaz.Hash.Sha1.Internal import qualified Raaz.Hash.Sha1.Implementation.CPortable as CPortable +-- | Recommended implementation for SHA1. instance Recommendation SHA1 where   recommended _ = CPortable.implementation
Raaz/Hash/Sha224/Implementation/CPortable.hs view
@@ -42,4 +42,4 @@ implementation =  SomeHashI cPortable  cPortable :: HashI SHA224 SHA224Memory-cPortable = truncatedI fromIntegral unSHA224Mem SHA256I.cPortable+cPortable = truncatedI (toEnum . fromEnum) unSHA224Mem SHA256I.cPortable
Raaz/Hash/Sha224/Internal.hs view
@@ -15,7 +15,6 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {-# CFILES raaz/hash/sha1/portable.c    #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}- module Raaz.Hash.Sha224.Internal        ( SHA224(..)        ) where@@ -46,4 +45,4 @@   type Implementation SHA224 = SomeHashI SHA224  instance Hash SHA224 where-  additionalPadBlocks _ = 1+  additionalPadBlocks _ = toEnum 1
Raaz/Hash/Sha224/Recommendation.hs view
@@ -11,5 +11,6 @@ import Raaz.Hash.Sha224.Internal import qualified Raaz.Hash.Sha224.Implementation.CPortable as CPortable +-- | Recommended implementation for SHA224. instance Recommendation SHA224 where   recommended _ = CPortable.implementation
Raaz/Hash/Sha256/Implementation/CPortable.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ForeignFunctionInterface   #-}--- | The portable C-implementation of SHA1+-- | The portable C-implementation of SHA256. module Raaz.Hash.Sha256.Implementation.CPortable        ( implementation, cPortable        ) where@@ -14,6 +14,9 @@ implementation :: Implementation SHA256 implementation =  SomeHashI cPortable +-- | The Hash implementation, i.e. `HashI` associated with the+-- portable C implementation for the hash SHA256. This can be used to+-- define an implementation of truncated hashes like SHA224. cPortable :: HashI SHA256 (HashMemory SHA256) cPortable = shaImplementation             "sha256-cportable"
Raaz/Hash/Sha256/Internal.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {-# CFILES raaz/hash/sha1/portable.c    #-} +-- | Internals of Sha256. module Raaz.Hash.Sha256.Internal        ( SHA256(..)        ) where@@ -49,4 +50,4 @@   type Implementation SHA256 = SomeHashI SHA256  instance Hash SHA256 where-  additionalPadBlocks _ = 1+  additionalPadBlocks _ = toEnum 1
Raaz/Hash/Sha256/Recommendation.hs view
@@ -11,5 +11,6 @@ import Raaz.Hash.Sha256.Internal import qualified Raaz.Hash.Sha256.Implementation.CPortable as CPortable +-- | Recommended implementation for SHA256. instance Recommendation SHA256 where   recommended _ = CPortable.implementation
Raaz/Hash/Sha384/Implementation/CPortable.hs view
@@ -44,4 +44,4 @@ implementation =  SomeHashI cPortable  cPortable :: HashI SHA384 SHA384Memory-cPortable = truncatedI fromIntegral unSHA384Mem SHA512I.cPortable+cPortable = truncatedI (toEnum . fromEnum) unSHA384Mem SHA512I.cPortable
Raaz/Hash/Sha384/Internal.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE MultiParamTypeClasses      #-} {-# CFILES raaz/hash/sha1/portable.c    #-} +-- | Internals of Sha384. module Raaz.Hash.Sha384.Internal        ( SHA384(..)        ) where@@ -36,4 +37,4 @@   type Implementation SHA384 = SomeHashI SHA384  instance Hash SHA384 where-  additionalPadBlocks _ = 1+  additionalPadBlocks _ = toEnum 1
Raaz/Hash/Sha384/Recommendation.hs view
@@ -11,5 +11,6 @@ import Raaz.Hash.Sha384.Internal import qualified Raaz.Hash.Sha384.Implementation.CPortable as CPortable +-- | Recommended implementation for SHA384. instance Recommendation SHA384 where   recommended _ = CPortable.implementation
Raaz/Hash/Sha512/Implementation/CPortable.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ForeignFunctionInterface   #-}--- | The portable C-implementation of SHA1+-- | The portable C-implementation of SHA512 module Raaz.Hash.Sha512.Implementation.CPortable        ( implementation, cPortable        ) where@@ -14,6 +14,9 @@ implementation :: Implementation SHA512 implementation =  SomeHashI cPortable +-- | The Hash implementation, i.e. `HashI` associated with the+-- portable C implementation for the hash SHA512. This can be used+-- to implement truncated implementation like SHA384. cPortable :: HashI SHA512 (HashMemory SHA512) cPortable = shaImplementation             "sha512-cportable"
Raaz/Hash/Sha512/Internal.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE DataKinds                  #-} {-# CFILES raaz/hash/sha1/portable.c    #-} +-- | Internals of Sha512. module Raaz.Hash.Sha512.Internal (SHA512(..)) where  @@ -49,4 +50,4 @@                                   ]  instance Hash SHA512 where-  additionalPadBlocks _ = 1+  additionalPadBlocks _ = toEnum 1
Raaz/Hash/Sha512/Recommendation.hs view
@@ -11,5 +11,6 @@ import Raaz.Hash.Sha512.Internal import qualified Raaz.Hash.Sha512.Implementation.CPortable as CPortable +-- | Recommend implementation for SHA512. instance Recommendation SHA512 where   recommended _ = CPortable.implementation
Raaz/Random.hs view
@@ -3,14 +3,16 @@ module Raaz.Random        ( -- * Cryptographically secure randomness.          -- $randomness$-         RandM, RT, liftMT+         RT, RandM        , randomByteString+       , random, randomiseCell        -- ** Types that can be generated randomly-       , Random(..)+       , RandomStorable(..), unsafeFillRandomElements          -- * Low level access to randomness.        , fillRandomBytes-       , unsafeStorableRandom        , reseed+       -- * Internals+       -- $internals$        ) where  import Control.Applicative@@ -33,23 +35,25 @@ -- $randomness$ -- -- The raaz library gives a relatively high level interface to--- randomness. The monad `RandM` captures a batch of actions that--- generate/use cryptographically secure random bytes. In particular,--- you can use the functions `random` and `randomByteString` to--- actually generate random elements.---+-- cryptographically secure randomness. The combinator `random`+-- generates pure value of certain types where as a sequence of random+-- bytes can be generated using the combinator+-- `randomByteString`. Both these combinators returns actions in the+-- `RandM`, the monad that captures actions that generate/use+-- cryptographically secure random bytes. -- -- = Running a random action ----- Depending on whether the random bytes generated are sensitive or--- not, you can use either of the combinators `securely` or--- `insecurely`.  The combinator `securely` ensures that the seed of--- the PRG is stored in a locked memory and hence will not be swapped--- out to the disk. A use case for this is when you use the random--- bytes to generate say a long term public key. On the other hand--- locked memory is limited on most systems. So for cases where the--- secrecy of the bytes are not important, we would recommend using--- `insecurely`.+-- There are two ways to run an `RandM` action, either `securely` or+-- `insecurely`. The only difference in these two is how they store+-- their seed in memory. The combinator `securely` ensures that the+-- seed of the CS-PRG is in a locked memory which is wiped clean after+-- the action is done. It is only needed in certain special cases+-- where the generated bytes needs to be kept secret, like for example+-- when generating long term keys. Even in those special cases, we+-- need to take extra precautions to ensure that no data is leaked+-- (details follow). For almost all other cases, we just need to use+-- `insecurely` as demonstrated below. -- -- > -- Generate a pair of random Word8's -- > import Raaz@@ -70,65 +74,189 @@ -- >         who = randomByteString 10 -- > ----- Some times you need additional memory to keep track of other--- stuff. The monad @`RT` mem@ is meant for such uses. It should be--- seen as the analogue of the monad @`MT` mem@ which in addition--- allows you to pick cryptographically secure random data. In fact,--- the combinator `liftMT` allows you to lift an `MT` action to the--- corresponding `RT` action.+-- = Generating sensitive data ----- = Internal details+-- The pseudo-random generator exposed here is cryptographically+-- strong enough to be used in generating long term private key for a+-- PKI system. However, special care is to be taken when generating+-- such data as we do not want the data to be swapped out of the+-- memory. The `securely` combinator is precisely for this+-- scenario. However, it is not enough to just wrap a `RandM` action+-- in `securely` to avoid leaking sensitive data. The use of+-- `securely` instead of `insecurely` in the following code gives us+-- /no additional security/. --+-- > -- Could as well use insecurely+-- > genWord64 :: IO Word64+-- > genWord64 = securely random+-- >+-- > -- Could as well use insecurely+-- > genRandomPassword :: IO ByteString+-- > genRandomPassword = securely $ randomByteString 42+--+-- Running a random action like `randomByteString`, using the+-- combinator `securely` only guarantees the seed is kept in locked+-- memory whereas the generated pure value resides in the unlocked+-- Haskell heap.  It is not feasible to ensure that the value is+-- stored in locked memory as the garbage collector often moves values+-- around. In general, it is not good to generate sensitive values as+-- a pure Haskell values. The solution we now describe gets into the+-- guts of the memory system of raaz. We recommend users who are not+-- developers of raaz or crypto-protocols on top of the raaz library,+-- to look for more high level solutions that hopefully raaz will+-- export.+--+-- The monad `RandM` is a specialisation of the more general random+-- monad @`RT` mem@ which captures a random actions that use an+-- additional memory element of type @mem@ (See the `Raaz.Core.Memory`+-- module for a description of the memory subsystem of raaz). The main+-- idea is to generate the random data directly into the additional+-- memory used by the action. A typical situation is to generate a+-- random element into a memory cell. This can be achieved by using+-- `randomiseCell` which, together with appropriate uses of+-- `onSubMemory`, should take care of most use cases of generating+-- sensitive data. Here is an example where we generate a key and iv+-- at randomly and perform an action with it.+--+-- > type SensitiveInfo = (MemoryCell Key, Memory IV)+-- >+-- > main :: IO ()+-- > main = securely $ do+-- >+-- >     -- Initialisation+-- >     onSubMemory fst randomiseCell -- randomise key+-- >     onSubMemory snd randomiseCell -- randomise iv+-- >+-- >     doSomethingWithKeyIV+--+-- More complicated interactions might require direct use of low level+-- buffer filling operations `fillRandomBytes` and+-- `fillRandomElements`. We recommend that this be avoided as much as+-- possible as they are prone to all the problems with pointer+-- functions.+--+--++-- $internals$+--+-- __Note:__ Only for developers and reviewers.+-- -- Generating unpredictable stream of bytes is one task that has burnt -- the fingers of a lot of programmers. Unfortunately, getting it--- correct is something of a black art.  Raaz uses a stream cipher--- (chacha20), initialised with a starting random key/iv. The starting--- seed is then drawn from the system entropy pool.+-- correct is something of a black art. We give the internal details+-- of the cryptographic pseudo-random generator used in raaz. Note+-- that none of the details here are accessible or tuneable by the+-- user. This is a deliberate design choice to insulate the user from+-- things that are pretty easy to mess up. ----- TODO: For system entropy we use @\/dev\/urandom@ on a posix systems--- (no windows support yet). Even on posix systems, depending on--- underlying operating system, there are better options. The--- recommended way to generate randomness on an OpenBSD system is--- through the function `arc4random` (note that arc4random does not--- use rc4 cipher anymore).  Recent Linux kernels support the--- `getrandom` system call which unfortunately is not yet--- popular. These system specific calls are better because they take--- into consideration many edge cases like for example--- @\/dev\/urandom@ not being accessible or protection from interrupts--- Eventually we will be supporting these calls.-+-- The pseudo-random generator in Raaz uses the chacha20 stream+-- cipher. We more or less follow the /fast key erasure technique/+-- (https://blog.cr.yp.to/20170723-random.html) which is used in the+-- arc4random implementation in OpenBSD.  The two main steps in the+-- generation of the required random bytes are the following:+--+-- [Seeding:] Setting the internal state of of the chacha20 cipher,+-- i.e. its key, iv, and counter.+--+-- [Sampling:] Pre-computing a few blocks of the chacha20 key stream+-- in an auxiliary buffer which in turn is used to satisfy the+-- requests for random bytes.+--+-- The internal chacha20 state and auxilary buffer used to cache+-- generated random bytes is part of the memory used in the `RT` monad+-- and hence using `securely` will ensure that they are locked.+--+-- == Seeding.+--+-- We use the /system entropy source/ to seed the (key, iv) of the+-- chacha20 cipher.  Reading the system entropy source is a costly+-- affair as it often involves a system call. Therefore, seeding is+-- done at the beginning of the operation and once every 1G blocks+-- (64GB) of data generated. No direct access to the system entropy is+-- provided to the user except through the `reseed` combinator which+-- itself is not really recommended. This is a deliberate design+-- choice to avoid potential confusion and the resulting error for the+-- user.+--+-- User level libraries have very little access to actual entropy+-- sources and it is very difficult to ascertain the quality of the+-- ones that we do have. Therefore, we believe it is better to rely on+-- the operating system for the entropy needed for seeding. As a+-- result, security of PRG is crucially dependent on the quality of+-- system entropy source. If the seed is predictable then everything+-- till the next seeding (an infrequent event as explained above) is+-- deterministic and hence compromised. Be warned that the entropy in+-- many systems are quite low at certain epochs, like at the time of+-- startup. This can cause the PRG to be compromised. We try to+-- mitigate this by using the best know source for each supported+-- operating system. Given below is the list of our choice of entropy+-- source.+--+-- [OpenBSD/NetBSD:] The arc4random call.+--+-- [Linux:] Defaults to @\/dev\/urandom@ but has experimental support+-- for `getrandom` (needs testing). The `getrandom` call is better but+-- many current systems do not have support for this (needs kernel >+-- 3.17 and libc > 2.25).+--+-- [Other Posix:] Uses @\/dev\/urandom@+--+-- [Windows:] Support using CryptGenRandom from Wincrypt.h.+--+-- == Sampling.+--+-- Instead of running the chacha20 cipher for every request, we+-- generate 16 blocks of ChaCha20 key stream in an auxiliary buffer+-- and satisfy requests for random bytes from this buffer. To ensure+-- that the compromise of the PRG state does not compromise the random+-- data already generated and given out, we do the following.+--+-- 1. At each sampling, we re-initialise the (key,iv) pair using the+--    key size + iv size bytes from the auxiliary buffer. This ensures+--    that there is no way to know which key,iv pairs was used to+--    generate the current contents in the auxiliary buffer.+--+-- 2. Every use of data from the auxiliary buffer, whether it is to+--    satisfy a request for random bytes or to reinitialise the+--    (key,iv) pair in step 1 is wiped out immediately.+--+-- Assuming the security of the chacha20 stream cipher we have the+-- following security guarantee.+--+-- [Security Guarantee:] At any point of time, a compromise of the+-- cipher state (i.e. key iv pair) and/or the auxiliary buffer does+-- not reveal the random data that is given out previously.+--  -- | A batch of actions on the memory element @mem@ that uses some -- randomness.-newtype RT mem a = RT { unMT :: MT (RandomState, mem) a }+newtype RT mem a = RT { unRT :: MT (RandomState, mem) a }                  deriving (Functor, Applicative, Monad, MonadIO) --- | The monad for generating cryptographically secure random data.-type RandM = RT VoidMemory---- | Lift a memory action to the corresponding RT action.-liftMT :: MT mem a -> RT mem a-liftMT = RT . onSubMemory snd- -- | Run a randomness thread. In particular, this combinator takes -- care of seeding the internal prg at the start.-runRT :: RT m a+seedAndRunRT :: RT m a       -> MT (RandomState, m) a-runRT action = onSubMemory fst reseedMT >> unMT action-+seedAndRunRT action = onSubMemory fst reseedMT >> unRT action +-- | The monad for generating cryptographically secure random data.+type RandM = RT VoidMemory -instance Memory mem => MonadMemory (RT mem) where-  insecurely = insecurely . runRT-  securely   = securely   . runRT+instance MemoryThread RT where+  insecurely        = insecurely . seedAndRunRT+  securely          = securely   . seedAndRunRT+  liftMT            = RT . onSubMemory snd+  onSubMemory proj  = RT . onSubMemory projP . unRT+    where projP (rstate, mem) = (rstate, proj mem)+          -- No (misguided) use of functor instance for (,) here.  -- | Reseed from the system entropy pool. There is never a need to -- explicitly seed your generator. The insecurely and securely calls -- makes sure that your generator is seed before -- starting. Furthermore, the generator also reseeds after every few--- GB of random bytes generates. Generating random data from the--- system entropy is usually an order of magnitude slower than using a--- fast stream cipher. Reseeding often can slow your program+-- GB of random bytes that it generates. Generating random data from+-- the system entropy is usually an order of magnitude slower than+-- using a fast stream cipher. Reseeding often can slow your program -- considerably without any additional security advantage. -- reseed :: RT mem ()@@ -139,47 +267,72 @@ fillRandomBytes l = RT . onSubMemory fst . fillRandomBytesMT l  --- | Types that can be generated at random. It might appear that all--- storables should be an instance of this class, after all we know--- the size of the element why not write that many random bytes. In--- fact, this module provides an `unsafeStorableRandom` which does--- exactly that. However, we do not give a blanket definition for all--- storables because for certain refinements of a given type, like for--- example, Word8's modulo 10, `unsafeStorableRandom` introduces--- unacceptable skews.-class Random a where--  random :: Memory mem => RT mem a+-- | Instances of `Storable` which can be randomly generated. It might+-- appear that all instances of the class `Storable` should be+-- be instances of this class, after all we know the size of the+-- element, why not write that many random bytes. In fact, this module+-- provides an `unsafeFillRandomElements` which does that. However, we+-- do not give a blanket definition for all storables because for+-- certain refinements of a given type, like for example, Word8's+-- modulo 10, `unsafeFillRandomElements` introduces unacceptable+-- skews.+class Storable a => RandomStorable a where+  -- | Fill the buffer with so many random elements of type a.+  fillRandomElements :: Memory mem+                     => Int       -- ^ number of elements to fill+                     -> Ptr a     -- ^ The buffer to fill+                     -> RT mem () --- | Generate a random element. The element picked is--- crypto-graphically pseudo-random.+-- TOTHINK:+-- ------- ----- This is a helper function that has been exported to simplify the--- definition of a `Random` instance for `Storable` types. However,--- there is a reason why we do not give a blanket instance for all--- instances `Storable` and why this function is unsafe? This function--- generates a random element of type @a@ by generating @n@ random--- bytes where @n@ is the size of the elements of @a@. For instances--- that range the entire @n@ byte space this is fine. However, if the--- type is actually a refinement of such a type --- consider for--- example, @`Word8`@ modulo @10@ -- this function generates an--- unacceptable skew in the distribution. Hence this function is--- prefixed unsafe.+-- Do we want to give a default definition like ---unsafeStorableRandom :: (Memory mem, Storable a) => RT mem a-unsafeStorableRandom = RT $ onSubMemory fst retA-  where retA = liftPointerAction alloc $ getIt . castPtr+-- > fillRandomElements = unsafeFillRandomElements+--+-- This would will make the instance definitions easier for the+-- Storables types that is spread over its entire range. However, it+-- would lead to a lazy definition which will compromise the quality+-- of the randomness. -        getIt        :: Storable a => Ptr a -> MT RandomState a-        getIt ptr    = unsafePokeManyRandom 1 ptr >> liftIO (peek ptr)-        getElement   :: MT RandomState a -> a+++-- | This is a helper function that has been exported to simplify the+-- definition of a `RandomStorable` instance for `Storable`+-- types. However, there is a reason why we do not give a blanket+-- instance for all instances `Storable` and why this function is+-- unsafe? This function generates a random element of type @a@ by+-- generating @n@ random bytes where @n@ is the size of the elements+-- of @a@. For instances that range the entire @n@ byte space this is+-- fine. However, if the type is actually a refinement of such a type,+-- (consider a @`Word8`@ modulo @10@ for example) this function+-- generates an unacceptable skew in the distribution. Hence this+-- function is prefixed unsafe.+unsafeFillRandomElements :: (Memory mem, Storable a) => Int -> Ptr a -> RT mem ()+unsafeFillRandomElements n ptr = fillRandomBytes totalSz $ castPtr ptr+  where totalSz = fromIntegral n * sizeOf (getElement ptr)+        getElement :: Ptr a -> a         getElement _ = undefined -        algn         = alignment $ getElement retA-        sz           = sizeOf    $ getElement retA -        alloc        = allocaAligned algn sz+-- | Generate a random element from an instance of a RandomStorable+-- element.+random :: (RandomStorable a, Memory mem) => RT mem a+random = RT $ liftPointerAction alloc (getIt . castPtr)+  where getIt ptr    = unRT $ fillRandomElements 1 ptr >> liftIO (peek ptr)+        alloc        :: Storable a => (Pointer -> IO a) -> IO a+        alloc action = allocaAligned algn sz action+          where getElement   :: (Pointer -> IO b) -> b+                getElement _ = undefined+                thisElement  = getElement action+                algn         = alignment thisElement+                sz           = sizeOf    thisElement +-- | Randomise the contents of a memory cell. Equivalent to @`random`+-- >>= liftMT . initialise@ but ensures that no data is transferred to+-- unlocked memory.+randomiseCell :: RandomStorable a => RT (MemoryCell a) ()+randomiseCell = getCellPointer >>= fillRandomElements 1  -- | Generate a random byteString. @@ -190,74 +343,57 @@  ------------------------------- Some instances of Random ------------------------ -instance Random Word8 where-  random = unsafeStorableRandom--instance Random Word16 where-  random = unsafeStorableRandom--instance Random Word32 where-  random = unsafeStorableRandom--instance Random Word64 where-  random = unsafeStorableRandom--instance Random Word where-  random = unsafeStorableRandom--instance Random Int8 where-  random = unsafeStorableRandom--instance Random Int16 where-  random = unsafeStorableRandom+instance RandomStorable Word8 where+  fillRandomElements = unsafeFillRandomElements -instance Random Int32 where-  random = unsafeStorableRandom+instance RandomStorable Word16 where -instance Random Int64 where-  random = unsafeStorableRandom+  fillRandomElements = unsafeFillRandomElements -instance Random Int where-  random = unsafeStorableRandom+instance RandomStorable Word32 where+  fillRandomElements = unsafeFillRandomElements -instance Random KEY where-  random = unsafeStorableRandom+instance RandomStorable Word64 where+  fillRandomElements = unsafeFillRandomElements -instance Random IV where-  random = unsafeStorableRandom+instance RandomStorable Word where+  fillRandomElements = unsafeFillRandomElements +instance RandomStorable Int8 where+  fillRandomElements = unsafeFillRandomElements -instance Random w => Random (LE w) where-  random = littleEndian <$> random+instance RandomStorable Int16 where+  fillRandomElements = unsafeFillRandomElements -instance Random w => Random (BE w) where-  random = bigEndian <$> random+instance RandomStorable Int32 where+  fillRandomElements = unsafeFillRandomElements -instance (Dimension d, Unbox w, Random w) => Random (Tuple d w) where-  random = repeatM random+instance RandomStorable Int64 where+  fillRandomElements = unsafeFillRandomElements --------------------------- Now comes the boring tuples -----------------+instance RandomStorable Int where+  fillRandomElements = unsafeFillRandomElements -instance (Random a, Random b) => Random (a,b) where-  random = (,) <$> random <*> random+instance RandomStorable KEY where+  fillRandomElements = unsafeFillRandomElements -instance (Random a, Random b, Random c) => Random (a,b,c) where-  random = (,,) <$> random <*> random <*> random+instance RandomStorable IV where+  fillRandomElements = unsafeFillRandomElements -instance (Random a, Random b, Random c, Random d) => Random (a,b,c,d) where-  random = (,,,) <$> random <*> random <*> random <*> random+instance RandomStorable w => RandomStorable (LE w) where+  fillRandomElements n = fillRandomElements n . lePtrToPtr+    where lePtrToPtr :: Ptr (LE w) -> Ptr w+          lePtrToPtr = castPtr -instance (Random a, Random b, Random c, Random d, Random e) => Random (a,b,c,d,e) where-  random = (,,,,) <$> random <*> random <*> random <*> random <*> random+instance RandomStorable w => RandomStorable (BE w) where+  fillRandomElements n = fillRandomElements n . bePtrToPtr+    where bePtrToPtr :: Ptr (BE w) -> Ptr w+          bePtrToPtr = castPtr --- | The action @unsafePokeManyRandom n ptr@ pokes @n@ random elements--- at the location starting at ptr.  If the underlying type does not--- saturate its entire binary size (think of say Word8 modulo 5), the--- distribution of elements can be rather skewed . Hence the prefix--- unsafe. This function is exported to simplify the definition--- `Random` instance. Do not use it unwisely.-unsafePokeManyRandom :: Storable a => Int -> Ptr a -> MT RandomState ()-unsafePokeManyRandom n ptr = fillRandomBytesMT totalSz $ castPtr ptr-  where totalSz = fromIntegral n * sizeOf (getElement ptr)-        getElement :: Ptr a -> a-        getElement _ = undefined+instance (Dimension d, Unbox w, RandomStorable w) => RandomStorable (Tuple d w) where+  fillRandomElements n ptr = fillRandomElements (n * sz) $ tupPtrToPtr ptr+    where getTuple    :: Dimension d => Ptr (Tuple d w) -> Tuple d w+          getTuple _  = undefined+          tupPtrToPtr ::  Ptr (Tuple d w) -> Ptr w+          tupPtrToPtr = castPtr+          sz         = dimension $ getTuple ptr
Raaz/Random/ChaCha20PRG.hs view
@@ -48,36 +48,55 @@   memoryAlloc     = RandomState <$> memoryAlloc <*> memoryAlloc <*> memoryAlloc   unsafeToPointer = unsafeToPointer  . chacha20State +-------------------------------- The PRG operations ---------------------------------------------++-- | The overall idea is to generate a key stream into the auxilary+-- buffer using chacha20 and giving out bytes from this buffer. This+-- operation we call sampling. A portion of the sample is used for+-- resetting the key and iv to make the prg safe against backward+-- prediction, i.e. even if one knows the current seed (i.e. key iv+-- pair) one cannot predict the random values generated before.+++ -- | This fills in the random block with some new randomness newSample :: MT RandomState ()-newSample = do setRemainingBytes $ inBytes randomBufferSize-               onSubMemory chacha20State seedIfReq-               withAuxBuffer $ onSubMemory chacha20State . flip chacha20Random randomBufferSize+newSample = do+  seedIfReq+  withAuxBuffer $ onSubMemory chacha20State . flip chacha20Random randomBufferSize -- keystream+  setRemainingBytes $ inBytes randomBufferSize -- Total bytes generated in one go+  fillKeyIVWith fillExistingBytes + -- | See the PRG from system entropy.-seed :: MT ChaCha20Mem ()-seed = do onSubMemory counterCell $ initialise (0 :: Counter)-          onSubMemory keyCell getCellPointer >>= void . getEntropy keySize . castPtr-          onSubMemory ivCell  getCellPointer >>= void . getEntropy ivSize  . castPtr-  where keySize = sizeOf (undefined :: KEY)-        ivSize  = sizeOf (undefined :: IV)+seed :: MT RandomState ()+seed = do onSubMemory (counterCell . chacha20State) $ initialise (0 :: Counter)+          fillKeyIVWith getEntropy  -- | Seed if we have already generated maxCounterVal blocks of random -- bytes.-seedIfReq :: MT ChaCha20Mem ()-seedIfReq = do c <- onSubMemory counterCell extract-               when (c > maxCounterVal) $ seed+seedIfReq :: MT RandomState ()+seedIfReq = do c <- onSubMemory (counterCell . chacha20State) extract+               when (c > maxCounterVal) seed +-- | Fill the iv and key from a filling function.+fillKeyIVWith :: (BYTES Int -> Pointer -> MT RandomState a) -- ^ The function used to fill the buffer+              -> MT RandomState ()+fillKeyIVWith filler = let+  keySize = sizeOf (undefined :: KEY)+  ivSize  = sizeOf (undefined :: IV)+  in do onSubMemory (keyCell . chacha20State) getCellPointer >>= void . filler keySize . castPtr+        onSubMemory (ivCell  . chacha20State) getCellPointer >>= void . filler ivSize  . castPtr ---------------------------- DANGEROUS CODE ---------------------------------------   --- remaining bytes, this can produce a lot of nonsense. +--------------------------- DANGEROUS CODE ---------------------------------------+ -- | Reseed the prg. reseedMT :: MT RandomState ()-reseedMT = onSubMemory chacha20State seed >> newSample+reseedMT = seed >> newSample  -- NONTRIVIALITY: Picking up the newSample is important when we first -- reseed.@@ -87,12 +106,10 @@ fillRandomBytesMT :: LengthUnit l => l -> Pointer -> MT RandomState () fillRandomBytesMT l = go (inBytes l)   where go m ptr-          | m  <= 0    = return ()   -- Nothing to do-          | otherwise  = do-              mGot <- fillExistingBytes m ptr   -- Fill some-              go-                (m - mGot)          -- bytes yet to get.-                $ movePtr ptr mGot  -- Shift by what is already got.+            | m > 0  = do mGot <- fillExistingBytes m ptr   -- Fill from the already generated buffer.+                          when (mGot <= 0) newSample        -- We did not get any so sample.+                          go (m - mGot) $ movePtr ptr mGot  -- Get the remaining.+            | otherwise = return ()   -- Nothing to do   -- | Fill from already existing bytes. Returns the number of bytes@@ -100,24 +117,20 @@ -- min(r,m) bytes into the buffer, and return the number of bytes -- filled. fillExistingBytes :: BYTES Int -> Pointer -> MT RandomState (BYTES Int)-fillExistingBytes m ptr = do+fillExistingBytes req ptr = withAuxBuffer $ \ sptr -> do   r <- getRemainingBytes-  withAuxBuffer $ \ sptr -> do-    if r <= m then do memcpy (destination ptr) (source sptr) r -- read the entire stuff.-                      newSample-                      return r-      else let leftOver = r - m                 -- Bytes leftover-               tailPtr  = movePtr sptr leftOver -- We read the last m bytes.-           in do memcpy (destination ptr) (source tailPtr) m-                 setRemainingBytes leftOver-                 return m----- The function fillExisting bytes reads from the end. See the picture--- below---------    ------------------------------------------------------------------------    |   (r - m) remaining bytes        |     m bytes consumed           |---    ------------------------------------------------------------------------+  let m  = min r req            -- actual bytes filled.+      l  = r - m                -- leftover+      tailPtr = movePtr sptr l+    in do+    -- Fills the source ptr from the end.+    --  sptr                tailPtr+    --   |                  |+    --   V                  V+    --   -----------------------------------------------------+    --   |   l              |    m                           |+    --   -----------------------------------------------------+    memcpy (destination ptr) (source tailPtr) m -- transfer the bytes to destination+    memset tailPtr 0 m                          -- wipe the bytes already transfered.+    setRemainingBytes l                         -- set leftover bytes.+    return m
+ Releasing.md view
@@ -0,0 +1,57 @@+# Checklist for releasing.++## Pre-release checklist.++Suppose that the release that one wants to do is version A.B.C. We+assume that the current master has all the necessary changes except+the release specific ones. The workflow is to start with a release+branch which we will call release-A.B.C.++* The first step is to update travis.yml to start building on the+  release-A.B.C This should be done before actually creating the+  release branch because we want all the release specific changes that+  are pushed to be built by travis. This is done on the master branch.+  push this change to the main repository++* Create a fresh branch titled release-A.B.C.++* Go over the bug-tracker for bugs to be addressed for this release.+  mark them.++* A pending change log entry should already be there for this entry.+  Please review it.++* Hack and get the project to shape.++* When ready merge to the master as a non-ff merge.++## Candidate release.++Hackage supports candidate releases which we should be making use of.+Here is a set of steps that can be done with a candidate release that+can help in doing a high quality release++1. Make sure to trigger a documentation build for the candidate on+   hackage.  This is currently not automated but would likely be the+   case.++2. The package build matrix is likely to be operational for candidate+   packages as well. This gives good package compatibility hints for+   high quality release.+++3. Get down-stream packagers to make an experimental upload of the+   package into their CI system. Distributions like Debian often do+   have multi-arch builds and also add builds across other platforms+   like Hurd, kFreeBSD etc. Successful builds+++## Post release++* Upload the release on hackage.++* Tag the release branch. Put the change log in the tag message.++* Bump up the release version.++* Create a pending entry for the next release in the Change log.
+ Reviewing.md view
@@ -0,0 +1,132 @@+# Checklist for reviewing code.++## Reviewing Haskell code++### Timing safe equality.++All cryptographically sensitive data types should have timing safe+equality comparison. The class `Equality` is the timing safe+counterpart of the `Eq` class. All such sensitive types should define+the `Equality` instance first using the `eq` and the monoid instance+of the `Result` type. The `Eq` type should then be a simple use of+`(===)`.++Good example.++```haskell++data GoodSensitiveType = ...++instance Equality GoodSensitiveType where+	eq a b = ...++instance Eq GoodSensitiveType where+	(==) = (===)++```++Here are some other example of a good definition.++```haskell++-- makes use of the Equality instance for pair.+newtype AnotherGoodType = AGT (Foo,Bar) deriving Equality++instance Eq AnotherGoodType where+	(==) = (===)++-- | Makes use of the Equality and Eq instances of tuple types.+newtype Foo = Foo (Tuple 42 Word32) deriving (Equality, Eq)+++```++A bad example. The deriving clause makes the (==) timing dependent+even if `Foo` and `Bar` have timing safe equality.++```haskell+data BadSensitiveType = BadSensitiveType Foo Bar deriving Eq++```+++### Dangerous modules++We document here some of the Haskell modules that do dangerous stuff+so that they can be audited more carefully. The exact dangers are+documented in the module.+++1. Raaz.Cipher.ChaCha20.Recommendation.++2. Raaz.Cipher.ChaCha20.Implementation.CPortable+++## Reviewing C code.++For speed, the block primitives are written in C. Most primitives have+a default word type (64-bit unsigned int for `sha512` for+example). They also have a block that is essentially an array of such+words (for `sha512` it is 16. So it will be common to see declarations+of the following kind.++```C++typedef uint64_t   Word;  /* basic unit of sha512 hash  */+#define HASH_SIZE  8      /* Number of words in a Hash  */+#define BLOCK_SIZE 16     /* Number of words in a block */++typedef Word Hash [ HASH_SIZE  ];+typedef Word Block[ BLOCK_SIZE ];++```++In such a setting, we often have a loop that goes over all the+blocks. This would typically look like the following.++```C++void foo(Block *ptr, int nblocks, ...)+{+	/* Other stuff here */++	while(nblocks > 0) /* looping over all blocks */+	{++       doSomethingOn((*ptr)[i]); /* do something on the ith word in the current block */++       -- nblocks; ++ ptr; /* move to the next block ensure these are+                            * on the same line+	                        */++	}+}++```++We would like to follow the above convention be cause it reduces the+chance of incorrect pointer arithmetic. The bugs are concentrated on+the definition of the block and word types. So if one is reviewing+such low level code, it is better to get familiarised with this+programming pattern.+++## Stuff that effects both C and Haskell.++## Alignment and restrict for block primitives++GCC can perform brutal optimisations even to Portable C+implementations if the right argument is qualified with restrict and+the alignment is matched to the associated vector operations. But these+features are Dangerous++1. Make sure that the alignment that you provide at the Haskell end+   when you define the Implementation is the same as (or a multiple+   of) that at the C side.++2. Since we expect to call these functions as an ffi it is relatively+   safe to assume that the buffer is not aliased. So restrict can also+   be given.++Be careful with ChaCha20 implementation where the alignment is also+used for the PRG buffer (See the dangerous modules subsection).
benchmarks/BenchPrimitives.hs view
@@ -20,6 +20,7 @@ import Raaz.Hash.Internal import Raaz.Random +import qualified Raaz.Hash.Blake2.Implementation.CPortable    as Blake2CP import qualified Raaz.Hash.Sha1.Implementation.CPortable      as Sha1CP import qualified Raaz.Hash.Sha256.Implementation.CPortable    as Sha256CP import qualified Raaz.Hash.Sha512.Implementation.CPortable    as Sha512CP@@ -34,6 +35,12 @@ import qualified Raaz.Cipher.ChaCha20.Implementation.Vector256 as ChaCha20V256 # endif ++#if !MIN_VERSION_criterion(1,2,0)+toBenchmarkable :: (Int64 -> IO ()) -> Benchmarkable+toBenchmarkable = Benchmarkable+#endif+ -- The total data processed nBytes :: BYTES Int nBytes = 32 * 1024@@ -49,15 +56,15 @@ allBench =    [ memsetBench, randomnessBench ]            ++ chacha20Benchs            ++ aesBenchs+           ++ blake2Benchs            ++ sha1Benchs            ++ sha256Benchs            ++ sha512Benchs  main :: IO ()-main = do results <- mapM runRaazBench allBench-          putStrLn $ "Buffer Size = " ++ show (fromIntegral nBytes :: Int)+main = do putStrLn $ "Buffer Size = " ++ show (fromIntegral nBytes :: Int)           putStrLn $ "Iterations  = " ++ show nRuns-          putStrLn $ render $ vcat results+          mapM_ runRaazBench allBench   pprMeasured :: Measured -> Doc@@ -80,7 +87,7 @@ -------------  All benchmarks ---------------------------------------------  memsetBench :: RaazBench-memsetBench = ("memset", Benchmarkable $ memBench . fromIntegral )+memsetBench = ("memset", toBenchmarkable $ memBench . fromIntegral )   where memBench count = allocaBuffer nBytes $ \ ptr -> replicateM_ count (memset ptr 42 nBytes)  @@ -93,6 +100,10 @@ sha512Benchs :: [ RaazBench ] sha512Benchs = [ hashBench Sha512CP.implementation ] +blake2Benchs :: [ RaazBench ]+blake2Benchs = [ hashBench Blake2CP.implementation2b+               , hashBench Blake2CP.implementation2s+               ]  aesBenchs     :: [ RaazBench ] aesBenchs      = [ encryptBench AesCbcCP.aes128cbcI@@ -116,36 +127,35 @@ --------------------------- Helper functions ---------------------------------------------------------------------------  encryptBench :: Cipher c => Implementation c -> RaazBench-encryptBench si@(SomeCipherI impl) = (nm , Benchmarkable $ encrBench . fromIntegral)+encryptBench si@(SomeCipherI impl) = (nm , toBenchmarkable $ encrBench . fromIntegral)   where encrBench count = allocBufferFor si sz $ \ ptr -> insecurely $ replicateM_ count $ encryptBlocks impl ptr sz         nm = name si ++ "-encrypt"         sz = atLeast nBytes   decryptBench :: Cipher c => Implementation c -> RaazBench-decryptBench si@(SomeCipherI impl) = (nm , Benchmarkable $ decrBench . fromIntegral)+decryptBench si@(SomeCipherI impl) = (nm , toBenchmarkable $ decrBench . fromIntegral)   where decrBench count = allocBufferFor si sz $ \ ptr -> insecurely $ replicateM_ count $ decryptBlocks impl ptr sz         nm = name si ++ "-decrypt"         sz = atLeast nBytes  hashBench :: Hash h => Implementation h -> RaazBench-hashBench hi@(SomeHashI impl) = (nm, Benchmarkable $ compressBench . fromIntegral )+hashBench hi@(SomeHashI impl) = (nm, toBenchmarkable $ compressBench . fromIntegral )   where compressBench count = allocBufferFor hi sz $ \ ptr -> insecurely $ replicateM_ count $ compress impl ptr sz         nm = name hi ++ "-compress"         sz = atLeast nBytes  randomnessBench :: RaazBench-randomnessBench = ("random", Benchmarkable $ rand . fromIntegral)+randomnessBench = ("random", toBenchmarkable $ rand . fromIntegral)   where rand count = allocaBuffer nBytes $ insecurely . replicateM_ count . fillIt         fillIt :: Pointer -> RandM ()         fillIt = fillRandomBytes nBytes -runRaazBench :: RaazBench -> IO Doc+runRaazBench :: RaazBench -> IO () runRaazBench (nm, bm) = do-  hPutStr  stderr $ "running " ++ nm ++ " ..."   (memt,x) <- measure bm nRuns-  hPutStrLn stderr $ "done."-  return $ text nm $+$ nest 8 (pprMeasured memt)+  putStrLn $ render $ text nm $+$ nest 8 (pprMeasured memt)+  hFlush stdout  -------------------------- Humanise output ----------------------------------- 
+ bin/Command/Checksum.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE GADTs              #-}+{-# LANGUAGE RankNTypes         #-}+{-# LANGUAGE RecordWildCards    #-}+{-# LANGUAGE ConstraintKinds    #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE CPP                #-}++module Command.Checksum ( checksum )  where++import Control.Monad+import Data.Char                ( toLower )+import Data.Monoid+import Data.String+import Options.Applicative+import Raaz+import System.Exit+import System.IO+++------------------------- Supported checksum algorithm -------------------------------++-- You can add new hash algorithms by adding a constructor for the+-- GADT, Algorithm h. You should also enable the command by adding a mkCmd line in the checksum+++checksum :: Parser (IO ())+#if MIN_VERSION_optparse_applicative(0,13,0)+checksum = subparser $ commandGroup "Checksum Computation"+#else+checksum = subparser $ mempty+#endif+           <> mkCmd Blake2b+           <> mkCmd Blake2s+           <> mkCmd Sha512+           <> mkCmd Sha256+           -- Add the mkCmd here and also add an appropriate+           -- constructor for the Algorithm type. If you add a hash+           -- Foo then the associated command will be foosum.++-- | The hash algorithm to use.+data Algorithm h  where+  Blake2b  :: Algorithm BLAKE2b+  Blake2s  :: Algorithm BLAKE2s+  Sha256   :: Algorithm SHA256+  Sha512   :: Algorithm SHA512+  -- Add new hash algorithm here.+++deriving instance Show (Algorithm h)+           -- Add a mkCmd here for the new hash algorithm++mkCmd :: Digest h => Algorithm h -> Mod CommandFields (IO ())+mkCmd algo = command cmd inf+  where inf = info (helper <*> opts) $ fullDesc <> hdr <> desc+        opts     = run algo <$> optParse+        algoname = map toLower $ show algo+        cmd      = algoname ++ "sum"+        hdr      = header $ unwords [ "raaz", cmd, "- File checksums using", algoname]+        desc     = progDesc $ "Compute or verify the file checksums using " ++ algoname+++------------------------ Types and constriants -------------------------------------+++-- | This constraint class consolidates the constraints on the checksum algorithms.+type Digest h = (Hash h, Recommendation h, Show h, IsString h)++++data Option = Option { checkDigest   :: Bool -- ^ true if we need verification.+                     , reportOkey    :: Bool -- ^ whether to print success+                     , reportFailure :: Bool -- ^ whether to print failure+                     , inputFiles    :: [FilePath]+                     }++--------------------- The checksum type ----------------------------------------++data Checksum h  = Checksum {filePath :: FilePath, fileDigest  :: h}+++instance Show h => Show (Checksum h) where+  show (Checksum{..}) = show fileDigest ++ "  " ++ filePath++parse :: Digest h => Algorithm h -> String -> Checksum h+parse algo inp = Checksum { filePath   = drop 2 rest+                          , fileDigest = parseDigest algo digest+                          }+  where parseDigest    :: Digest h => Algorithm h -> String -> h+        parseDigest _  = fromString+        (digest, rest) = break (==' ') inp -- break at the space.++-- | Parse the lines into checksum.+parseMany :: Digest h => Algorithm h -> String -> [Checksum h]+parseMany algo = map (parse algo) . lines++---------- The main combinators that does the actual work -------------++-- | The workhorse for this command.+run :: Digest h => Algorithm h -> Option -> IO ()+run algo opt@(Option{..})+  | checkDigest = runVerify algo opt+  | otherwise   = runCompute algo inputFiles+++--------------------------- Compute mode ---------------------------------------++runCompute :: Digest h+           => Algorithm h    -- Algorithm to use+           -> [FilePath]     -- files for which checksums need to be computed.+           -> IO ()+runCompute algo files+  | null files = computeStdin algo >>= print  -- No files means compute it for stdin.+  | otherwise  = mapM_ printToken files       -- Print the token for each file.+  where printToken = compute algo >=> print++++-- | Compute the checksum of a file.+compute :: Digest h+        => Algorithm h  -- ^ The hashing algorithm to use.+        -> FilePath     -- ^ The file to compute the token for.+        -> IO (Checksum h)+compute _ fp = Checksum fp <$> hashFile fp+++-- | Compute the checksum of standard input+computeStdin :: Digest h => Algorithm h -> IO (Checksum h)+computeStdin _ = Checksum "-" <$> hashSource stdin++----------------------------------- Verify Mode ---------------------------------------++runVerify :: Digest h => Algorithm h -> Option -> IO ()+runVerify algo opt@(Option{..}) = do+  nFails <- if null inputFiles then getContents >>= verifyLines+            else sum <$> mapM verifyFile inputFiles++  when reportFailure $ putStrLn $ show nFails ++ " failures."+  when (nFails > 0)  exitFailure+  where+    verifyLines     = verifyList opt . parseMany algo+    verifyFile fp   = withFile fp ReadMode $ hGetContents  >=> verifyLines+++verify :: Digest h+       => Option+       -> Checksum  h+       -> IO Bool+verify (Option{..}) (Checksum{..}) = do+  digest <- hashFile filePath+  let result = digest == fileDigest+      okey   = when reportOkey    $ putStrLn $ filePath ++ ": OK"+      failed = when reportFailure $ putStrLn $ filePath ++ ": FAILED"+    in do if result then okey else failed+          return result++verifyList :: Digest h+           => Option+           -> [Checksum h]+           -> IO Int+verifyList opt   = fmap countFailures . mapM (verify opt)+  where countFailures = Prelude.length . filter not+++----------------------------- Option parsers ----------------------------------++optParse   :: Parser Option+optParse  =  verbosityOpt <*> (Option <$> checkOpt <*> pure True <*> pure True <*> files)++  where checkOpt = switch+                   $  long "check"+                   <> short 'c'+                   <> help "Verify the input checksums instead of compute"+        files = many $ argument str $ metavar "FILE.."+++verbosityOpt :: Parser (Option -> Option)+verbosityOpt = (.) <$> statusOpt <*> quietOpt+  where statusOnly opt = opt { reportOkey = False, reportFailure = False }+        quietMode  opt = opt { reportOkey = False }++        statusOpt = flag id statusOnly+                    $  short 's'+                    <> long  "status"+                    <> help "Do not print anything, only return the verification status"++        quietOpt  = flag id quietMode+                    $  short 'q'+                    <> long "quite"+                    <> help "Do not print OK, print only failures"
− bin/Command/Checksum.lhs
@@ -1,320 +0,0 @@-Introduction---------------This command supports a generalised version of-sha1sum/sha256sum/sha512sum programs that are available on a standard-linux system. It supports generating checksum files and verifying them-for all the hashes exposed by the raaz library. The purpose of writing-this application is the following.--1. To give an example of of a non-trivial program written to use the-   raaz library.--2. To make sure that the implementations of hashes in this library are-   not too off in terms of performance.--The command line options of this command is similar to that of sha1sum-and hence can be used as a replacement.--This file is a literate haskell file and hence can be compiled-directly. The text is in markdown and hence you should be able to-produce the documentation for--We start by enabling some pragmas and importing some stuff which can-be ignored.--> {-# LANGUAGE GADTs           #-}-> {-# LANGUAGE RankNTypes      #-}-> {-# LANGUAGE RecordWildCards #-}-> {-# LANGUAGE ConstraintKinds #-}--> module Command.Checksum ( checksum ) where->-> import Control.Applicative-> import Control.Monad-> import Data.List             (intercalate)-> import Data.Monoid-> import Data.String-> import Data.Version          (showVersion)-> import System.Environment-> import System.Exit-> import System.IO             (stdin, stderr, hPutStrLn)-> import System.Console.GetOpt--> import Raaz     hiding (Result)-> import Raaz.Hash.Sha1---Verification Tokens----------------------Programs like sha1sum is typically used to verify that the contents of-a set of files have not been modified or corrupted. This program does-the following:--1. In compute mode it computes a set of verification tokens which-   uniquely identify the contents of the file.--2. In verification mode it takes a set of tokens are verify them.--Verification tokens are computed using the cryptographic hash. We-allow the use of any of the hashes exposed by the raaz library. Thus-for us, any hash that satisfies the constraint `TokenHash` should be-usable in computing and verifying tokens.---> type TokenHash h = (Hash h, Recommendation h, Show h, IsString h)->--The verification token is defined below. To make it opaque, we-existentially quantify over the underlying digest.-->-> data Token  = forall h . TokenHash h->             => Token { tokenFile    :: FilePath->                      , tokenDigest  :: h->                      }->---A token can be verified easily. First we define the result type--> type Result = Either FilePath FilePath->-> verify :: Token -> IO Result-> verify (Token{..}) = do c <- (==tokenDigest) <$> hashFile tokenFile->                         return $ if c then Right tokenFile else Left tokenFile---Computing tokens.--------------------To compute the verification token, we need a way to specify the-algorithm.  The following proxy helps us in this.--> data Algorithm h   = Algorithm--Here `h` varies over all the hashes supported by the library. We now-need an easy way to tabulate all the hash algorithm that we-support. Existential types comes to the rescue once more.--> data SomeAlgorithm = forall h . TokenHash h => SomeAlgorithm (Algorithm h)--Here is the table of algorithms that we support currently.--> algorithms :: [(String, SomeAlgorithm)]-> algorithms =  [ ("broken-sha1"  , SomeAlgorithm (Algorithm :: Algorithm SHA1)   )->               , ("sha256", SomeAlgorithm (Algorithm :: Algorithm SHA256) )->               , ("sha512", SomeAlgorithm (Algorithm :: Algorithm SHA512) )->               -- Add new algorithms here.->               ]--We now define the computation function. There are two variants, one for arbitrary files-and the other for standard input.--> -- | Compute the token using a given algorithm.-> token :: TokenHash h->       => Algorithm h  -- ^ The hashing algorithm to use.->       -> FilePath     -- ^ The file to compute the token for.->       -> IO Token-> token algo fp = Token fp <$> hashIt algo->   where hashIt :: TokenHash h => Algorithm h -> IO h->         hashIt _ = hashFile fp->-> tokenStdin :: TokenHash h => Algorithm h -> IO Token-> tokenStdin algo = Token "-" <$> hashIt algo->   where hashIt :: TokenHash h => Algorithm h -> IO h->         hashIt _ = hashSource stdin->---Printed form of tokens-------------------------To inter-operate with programs like sha1sum, we follow the same-printed notation. The appropriate show instances for token is the-following. The format is `line := digest space mode filename`. The mode-has something to do with whether it is binary or text (we always put-a space for it).--> instance Show Token where->   show (Token{..}) = show tokenDigest ++ "  " ++ tokenFile--We also define the associated parsing function which has to take the-the underlying algorithm as a parameter.--> parse :: TokenHash h => Algorithm h -> String -> Token-> parse algo str = Token { tokenFile   = drop 2 rest->                        , tokenDigest = parseDigest algo digest->                        }->   where parseDigest    :: TokenHash h => Algorithm h -> String -> h->         parseDigest _  = fromString->         (digest, rest) = break (==' ') str -- break at the space.---The main function.---------------------The overall structure of the code is clear the details follow.--> checksum :: [String] -> IO ()-> checksum =  parseOpts >=> handleArgs--> handleArgs :: (Options, [FilePath])->            -> IO ()-> handleArgs (opts@Options{..}, files) = do->   when optHelp printHelp       -- When the help option is given print it and exit->   flip (either badAlgorithm) optAlgo $ \ algo -> do->     if optCheck  -- if asked to check.->       then verifyMode opts  algo files >>= optPrintCount->       else computeMode      algo files---> badAlgorithm :: String -> IO ()-> badAlgorithm name = errorBailout ["Bad hash algorithm " ++ name]---The compute mode.--------------------There are two important modes of operation for this program, _the-compute mode_ and the _verify mode_. In the compute mode, we are given-an a set of files and we need to print out the verification tokes for-those files.--> computeMode :: SomeAlgorithm  -- The algorithm to use->             -> [FilePath]     -- files for which tokes need to be->                               -- computed.->             -> IO ()-> computeMode (SomeAlgorithm algo) files->   | null files = tokenStdin algo >>= print  -- No files means compute it for stdin.->   | otherwise  = mapM_ printToken files     -- Print the token for each file.->   where printToken = token algo >=> print---The verification mode of the algorithm is a bit more complicated than-the compute mode. Given a list of tokens let us first read-them. Recall the tokens are listed, one per line with the digest-followed by a space followed by the filename.---> verifyMode :: Options->            -> SomeAlgorithm->            -> [FilePath]->            -> IO Int-> verifyMode (Options{..}) algo files = verifyFiles algo files >>= foldM fldr (0 :: Int)->   where fldr n = either whenFailed whenOkey->           where whenOkey    :: FilePath -> IO Int->                 whenOkey    = optOkey   >=> const (return n)     -- when okey do the okey action and keep the count->                 whenFailed  = optFailed >=> const (return (n+1)) -- when failed do the failed action and increment--This function verify the token list given in a list of files. Each-file contains a list of tokens and each of these tokens have to be-verified.--> verifyFiles :: SomeAlgorithm->             -> [FilePath]->             -> IO [Result]->-> verifyFiles (SomeAlgorithm algo) files->   | null files = getContents >>= verifyTokenList->   | otherwise  = concat <$> mapM verifyFile files->   where->     verifyFile      = readFile >=> verifyTokenList->     verifyTokenList = mapM mapper . lines->     mapper          = verify . parse algo---This function prints the help for the program.--> printHelp :: IO ()-> printHelp = do putStrLn $ usage []->                exitSuccess---Command line parsing-----------------------The options supported by the program is given by the following data-type. Fields should be self explanatory.--> data Options =->   Options { optHelp    :: Bool->           , optCheck   :: Bool->           , optAlgo    :: Either String SomeAlgorithm->           , optOkey    :: FilePath -> IO () -- ^ handle successful tokens->           , optFailed  :: FilePath -> IO () -- ^ handle failed tokens.->           , optPrintCount   :: Int -> IO () -- ^ print failure counts.->           }---The default options for the command is as follows.--> defaultOpts =->   Options { optHelp       = False->           , optCheck      = False->           , optAlgo       = Right sha512Algorithm->           , optOkey       = \ fp -> putStrLn (fp ++ ": OK")->           , optFailed     = \ fp -> putStrLn (fp ++ ": FAILED")->           , optPrintCount = printCount->           }->   where sha512Algorithm = SomeAlgorithm (Algorithm :: Algorithm SHA512)->         printCount n  = when (n > 0) $ do->           putStrLn $ show n ++ " failures."->           exitFailure->--We use the getOpts library to parse the command lines.  The options-are summarised in the following list. The `Endo` monoid helps in-summarising the changes to the option set.--> options :: [OptDescr (Endo Options)]-> options =->   [ Option ['h'] ["help"]    (NoArg setHelp)    "print the help"->   , Option ['c'] ["check"]   (NoArg setCheck)   "check instead of compute"->   , Option ['q'] ["quiet"]   (NoArg setQuiet)   "print failure only"->   , Option ['s'] ["status"]  (NoArg setStatusOnly)->     "no output only return status"->   , Option ['a'] ["algo"]    (ReqArg setAlgo "HASH")->     $ "hash algorithm to use " ++ "[" ++ algOpts ++ "]. Default sha512"->   ]->   where setHelp      = Endo $ \ opt -> opt { optHelp    = True }->         setCheck     = Endo $ \ opt -> opt { optCheck   = True }->         setAlgo  str = Endo $ \ opt -> opt { optAlgo    = a    }->                  where a = maybe (Left str) Right $ lookup str algorithms->         algOpts          = intercalate "|" $ map fst algorithms->         setQuiet      = Endo $ \ opt ->  opt { optOkey   = noPrint }->         setStatusOnly = Endo $ \ opt ->  opt { optFailed      = noPrint->                                              , optOkey        = noPrint->                                              , optPrintCount  = returnStatus->                                              }->         noPrint           = const $ return ()->         returnStatus n->           | n > 0         = exitFailure->           | otherwise     = exitSuccess->----The usage message for the program.--> usage :: [String] -> String-> usage errs->       | null errs = usageInfo header options->       | otherwise = "raaz checksum: " ++ unlines errs ++ usageInfo header options->   where header ="Usage: raaz checksum [OPTIONS] FILE1 FILE2 ..."---Parsing the options.--> parseOpts :: [String] -> IO (Options, [FilePath])-> parseOpts args = case getOpt Permute options args of->                    (o,n,[])   -> return (appEndo (mconcat o) defaultOpts, n)->                    (_,_,errs) -> errorBailout errs--Bail out with an error message.--> errorBailout :: [String]-> IO a-> errorBailout errs = do->   hPutStrLn stderr $ usage errs->   exitFailure
+ bin/Command/CpuInfo.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE CPP #-}+module Command.CpuInfo where++import Data.Monoid+import Options.Applicative++import Raaz.Core.CpuSupports as CpuSupports++display :: (Bool, String) -> String+display (True, cap) = unwords ["+", cap]+display (_,cap)     = unwords ["-", cap]++cpuInfo :: Parser (IO ())+++#if MIN_VERSION_optparse_applicative(0,13,0)+cpuInfo = subparser $ commandGroup "CPU capabilities" <> cpuInfoCmd <> metavar "cpuinfo"+#else+cpuInfo = subparser $ cpuInfoCmd <> metavar "cpuinfo"+#endif+  where cpuInfoCmd = command "cpuinfo" $ info (helper <*> opts) $ fullDesc+                     <> header "raaz cpuinfo - CPU capabilities detected at runtime."+                     <> progDesc "Shows the capabilities understood/detected by raaz at runtime. Recommended implementations depend on this."++        opts = pure $ mapM_ (putStrLn . display) [ (CpuSupports.sse, "sse")+                                                 , (CpuSupports.sse2, "sse2")+                                                 , (CpuSupports.sse3, "sse3")+                                                 , (CpuSupports.sse4_1, "sse4.1")+                                                 , (CpuSupports.sse4_2, "sse4.2")+                                                 , (CpuSupports.avx,    "avx")+                                                 , (CpuSupports.avx2,   "avx2")+                                                 ]
bin/Command/Rand.lhs view
@@ -1,18 +1,17 @@-This command that spits out never ending stream of-cryptographically secure bytes. Other than being a replacement to-Yo-Yo Honey Singh (random > /dev/audio), it is used to test the-quality of the randomnes produced.+This command spits out never ending stream of cryptographically secure+bytes. Apart from replacing Yo-Yo Honey Singh (`raaz rand >+/dev/audio), it is used to test the quality of the randomnes produced.  +> {-# LANGUAGE CPP #-} > module Command.Rand ( rand ) where  > import Control.Applicative > import Control.Monad.IO.Class(liftIO)-> import System.Exit-> import System.IO-> import Text.Read-> import Prelude+> import Data.Monoid+> import Options.Applicative > import Raaz+> import System.IO  So much bytes generated in one go before writing to stdout. @@ -20,45 +19,31 @@ > bufSize = 32 * 1024  -The usage message for the program.+> opts :: Parser (IO ())+> opts =   nRandomBytes . toEnum <$> argument auto (metavar "NUMBER_OF_BYTES")+>      <|> pure infinteBytes+>   where nRandomBytes n = withBuffer $ insecurely  . genBytes n+>         infinteBytes = withBuffer $ insecurely  . genInfiniteBytes+>         withBuffer = allocaBuffer bufSize -> usage :: [String] -> String-> usage errs | null errs = body->            | otherwise = "raaz: " ++ unlines errs ++ body->   where body = unlines $ [ "Usage: raaz random [N]"->                          , "       raaz random [-h|--help]"->                          , ""->                          , "Generates never ending stream of cryptographically secure random bytes."->                          , "With the option integral argument N, stops after generating N bytes."->                          , "   -h\t--help\tprint this help"->                          ]  -The main stuff. -> rand :: [String] -> IO ()-> rand args = case args of->               ["-h"]     -> printHelp->               ["--help"] -> printHelp->               [n]        -> maybe (badArgs n) gen $ readNBytes n->               []         -> withBuffer $ insecurely . genInfiniteBytes->               _          -> tooManyArgs->   where readNBytes     :: String -> Maybe (BYTES Int)->         readNBytes   x = (toEnum <$> readMaybe x) >>= onlyPositive->         onlyPositive x->           | x >= 0     = Just x->           | otherwise  = Nothing->         badArgs n      = errorBailout ["Bar argument " ++ n ++ " expected integer (no of bytes)"]->         tooManyArgs    = errorBailout ["too many args"]->         gen n          = withBuffer $ insecurely . genBytes n->         withBuffer = allocaBuffer bufSize+> rand :: Parser (IO ()) +#if MIN_VERSION_optparse_applicative(0,13,0)+> rand = subparser $ commandGroup "Randomness" <> randCmd <> metavar "rand"+#else+> rand = subparser $ randCmd <> metavar "rand"+#endif -> printHelp :: IO ()-> printHelp = do putStrLn $ usage []->                exitSuccess+>   where randCmd = command "rand" $ info (helper <*> opts) $ fullDesc+>           <> header "raaz rand - Cryptographically secure pseudo random bytes."+>           <> progDesc "Generate cryptographically secure pseudo random bytes onto the stdout."  ++ > genInfiniteBytes :: Pointer -> RandM () > genInfiniteBytes ptr = goForEver >   where goForEver = emitRand bufSize ptr >> goForEver@@ -70,12 +55,6 @@ > genBytes n ptr = go n >   where go m | m >= bufSize = do emitRand bufSize ptr; go (m - bufSize) >              | otherwise    =    emitRand m ptr---Bail out of errors--> errorBailout errs = do hPutStrLn stderr $ usage errs->                        exitFailure   -- Emit so may random bytes.
bin/Main.hs view
@@ -3,84 +3,39 @@ -- The main function that drives other commands. -- -import Control.Monad+ import Data.Version          (showVersion) import Data.Monoid+import Options.Applicative import Raaz                  (version)-import System.Console.GetOpt-import System.Environment-import System.Exit-import System.IO ---import Command.Checksum-import Command.Rand----- The commands know to raaz executable.-commands :: [(String, [String] -> IO ())]-commands = [ ("checksum", checksum)-           , ("rand"    , rand    )-           ]--------------------- Command line parsing ---------------------------------------data Options = Options { optVersion :: Bool-                       , optHelp    :: Bool-                       }--defaultOpts :: Options-defaultOpts = Options { optVersion    = False, optHelp  = False }--options :: [OptDescr (Endo Options)]-options = [ Option ['v'] ["version"] (NoArg setVersion) "print the version"-          , Option ['h'] ["help"]    (NoArg setHelp)    "print the help"-          ]-  where setVersion   = Endo $ \ opt -> opt { optVersion = True }-        setHelp      = Endo $ \ opt -> opt { optHelp    = True }+import           Command.Checksum+import           Command.CpuInfo+import           Command.Rand  --- | parse options-parseOpts :: [String] -> IO Options-parseOpts args = case getOpt Permute options args of-  (o,[],[])  -> return $ appEndo (mconcat o) defaultOpts-  (_,_,errs) -> errorBailout errs+data Option = ShowVersion+             | RunCommand (IO ()) --- The usage message for the program.-usage :: [String] -> String-usage errs | null errs = usageInfo header options-           | otherwise = "raaz: " ++ unlines errs ++ usageInfo header options-  where header = unlines $ [ "Usage: raaz [COMMAND] [OPTIONS]"-                           , "       raaz [OPTIONS]"-                           , ""-                           , "Supported Commands: "-                           ] ++ cmds-        cmds     = map (("\t"++) . fst) commands+progOption  :: Parser Option+progOption = flag ShowVersion ShowVersion versionMods+             <|> RunCommand <$> rand+             <|> RunCommand <$> checksum+             <|> RunCommand <$> cpuInfo +  where versionMods = short 'v'+                      <> long "version"+                      <> help "Print the version of the raaz library used"  ---------------------- The main function and stuff --------------------------------main :: IO ()-main = do args <- getArgs-          case args of-            (c:restArgs) -> maybe (noCommand args) (runCmd restArgs) $ lookup c commands-            _ -> errorBailout ["empty command line"]-     where runCmd    = flip ($)-           noCommand = parseOpts >=> run--run :: Options -> IO ()-run (Options{..}) = do-  when optVersion $ printVersion-  when optHelp    $ printHelp-  where printHelp    = putStrLn $ usage []-        printVersion = putStrLn $ "raaz: " ++ showVersion version+run :: Option -> IO ()+run ShowVersion      = putStrLn $ "raaz version " ++ showVersion version+run (RunCommand cmd) = cmd  --- | Bail out on error-errorBailout :: [String]-> IO a-errorBailout errs = do-  hPutStrLn stderr $ usage errs-  exitFailure+main :: IO ()+main = execParser opts >>= run+  where opts = info (helper <*> progOption) $+               fullDesc+               <> header "raaz - A command line interface to the raaz cryptographic library."+               <> footer "Homepage: http://github.com/raaz-crypto"
+ bin/Usage.hs view
@@ -0,0 +1,25 @@+module Usage( usage, errorBailout ) where++import System.Console.GetOpt+import System.IO+import System.Exit++-- | The usage message for the program.+usage :: [OptDescr a]  -- ^ options+      -> String        -- ^ Header+      -> [String]      -- ^ errors+      -> String+usage options header errs+  | null errs = usageInfo header options+  | otherwise = "raaz: " ++ unlines errs ++ usageInfo header options++++-- | Bail out on error+errorBailout :: [OptDescr a] -- ^ Options+             -> String       -- ^ Header+             -> [String]     -- ^ Errors+             -> IO b+errorBailout opts str errs = do+  hPutStrLn stderr $ usage opts str errs+  exitFailure
cbits/raaz/cipher/chacha20/cportable.c view
@@ -64,18 +64,11 @@  */ -# ifdef __GNUC__ -typedef Block MyBlock __attribute__ ((aligned (32))); -void raazChaCha20Block(MyBlock * msg, int nblocks, const Key key, const IV iv, Counter  *ctr)--# else+# pragma GCC optimize "tree-vectorize"  void raazChaCha20Block(Block * msg, int nblocks, const Key key, const IV iv, Counter  *ctr)--#endif- {     register Word x0,  x1,  x2, x3;     register Word x4,  x5,  x6, x7;
+ cbits/raaz/core/cpusupports.c view
@@ -0,0 +1,42 @@+/*++This module exposes runtime checks for cpu flags. Works only with GCC.++ */+++# define GCC_VERSION (__GNUC__ * 10 + __GNUC_MINOR__)++/* Check an x86_64 feature */++# ifdef ARCH_X86_64+#     define X86_64_SUPPORTS(x) { __builtin_cpu_init(); return __builtin_cpu_supports((x)); }+# else+#     define X86_64_SUPPORTS(x) { return 0; }+# endif++# if GCC_VERSION >= 48 && !defined(__clang__)+# pragma GCC push_options+# pragma GCC optimize ("O0")++int raaz_supports_sse()   { X86_64_SUPPORTS("sse");     }+int raaz_supports_sse2()  { X86_64_SUPPORTS("sse2");    }+int raaz_supports_sse3()  { X86_64_SUPPORTS("sse3");    }+int raaz_supports_sse4_1(){ X86_64_SUPPORTS("sse4.1");  }+int raaz_supports_sse4_2(){ X86_64_SUPPORTS("sse4.2");  }+int raaz_supports_avx()   { X86_64_SUPPORTS("avx");     }+int raaz_supports_avx2()  { X86_64_SUPPORTS("avx2");    }++# pragma GCC pop_options++# else++int raaz_supports_sse()   { return 0;}+int raaz_supports_sse2()  { return 0;}+int raaz_supports_sse3()  { return 0;}+int raaz_supports_sse4_1(){ return 0;}+int raaz_supports_sse4_2(){ return 0;}+int raaz_supports_avx()   { return 0;}+int raaz_supports_avx2()  { return 0;}++#endif
cbits/raaz/core/endian.c view
@@ -1,13 +1,5 @@ #include <raaz/core/endian.h>-#ifdef __RAAZ_REQUIRE_PORTABLE_ENDIAN__ -/* We were not able to detect the optimised platform specific versions- * of the low level endian functions. We now proceed to define a- * portable variant so that the extern declarations is satisfied.- */--- /*  *  These are declared as macros because they will work for both  *  32-bit as well as 64-bit cases.@@ -21,13 +13,7 @@                        /* This function swaps the ith and jth bytes and sets other bytes to 0 */  -uint32_t raaz_bswap32(uint32_t a){ return (SWAP(a,0,3) | SWAP(a,1,2)); }-uint64_t raaz_bswap64(uint64_t a){ return (SWAP(a,0,7) | SWAP(a,1,6)  | SWAP(a,2,5) | SWAP(a,3,4)); } ---- # define TO32(x)     ((uint32_t)(x)) # define TO64(x)     ((uint64_t)(x)) @@ -42,6 +28,16 @@     ((a) <<  56  | (b) << 48   | (c) << 40 | (d) << 32	| (e) << 24   | (f) << 16   | (g) << 8  | (h))  +#ifdef __RAAZ_REQUIRE_PORTABLE_SWAP__++uint32_t raaz_bswap32(uint32_t a){ return (SWAP(a,0,3) | SWAP(a,1,2)); }+uint64_t raaz_bswap64(uint64_t a){ return (SWAP(a,0,7) | SWAP(a,1,6)  | SWAP(a,2,5) | SWAP(a,3,4)); }++#endif+++#ifdef __RAAZ_REQUIRE_PORTABLE_ENDIAN__+ uint32_t raaz_tobe32(uint32_t x) {     uint8_t *ptr = (uint8_t *) &x;@@ -71,9 +67,8 @@ 		B64(ptr,3), B64(ptr,2), B64(ptr,1), B64(ptr,0)); } -- #endif+  /* Finally we define the functions that are called by Haskell as FFI  * routines for their endian store instances. These should not be
cbits/raaz/core/endian.h view
@@ -1,59 +1,68 @@ # pragma once # include <stdint.h> -/* These are the C functions that are exported for FFI calls to- * Haskell. Their definitions are available in endian.c- */+/* This header file does the following -extern uint32_t raazSwap32      (uint32_t a);-extern uint64_t raazSwap64      (uint64_t a);-extern void     raazSwap32Array (uint32_t *ptr, int n);-extern void     raazSwap64Array (uint64_t *ptr, int n);+1. Declarations of raazSwap* and RaazSwap*Array functions that are the+   C functions for call from Haskell. +2. Endian conversion functions that are used by implementations of+   primitives. -/* This header also give interface to low level byteswap and endian- * conversion in a platform agnostic way to both to the Haskell FFI- * functions declared above as well as to crypto primitives defined in- * other c sources. The should not be used directly for FFI as they- * most likely are defined static inline and included with the source.- */+Note that on the Haskell side endian conversion happens by calling the+swap if required and we do not need the endian functions+here. Therefore, they are declared as static inline whenever possible.  -#ifndef __GNUC__-#define __RAAZ_REQUIRE_PORTABLE_ENDIAN__+We first define functions for byte swapping falling back to portable C+implementation (indicated by defining __RAAZ_REQUIRE_PORTABLE_SWAP__)+available in raaz/core/endian.c. The C-ffi stub functions make use of+these functions. The endian conversions functions also use them if we+can detect the byte order. Otherwise they too have a portable c+implementation (indicated by defining+__RAAZ_REQUIRE_PORTABLE_ENDIAN__) -/*  We are unable to detect if the compiler is gcc or a compatible- *  one. So we declare all the low level functions to be extern and- *  expect their definitions to be in endian.c The above #define line- *  is used to indicate that we are in such a situation+*/++/*+ *         Byte swapping. Use platform specific ones when we know it.  */ -extern uint32_t raaz_bswap32(uint32_t x);-extern uint64_t raaz_bswap64(uint64_t x);+#ifdef PLATFORM_OSX+#  include <libkern/OSByteOrder.h> /* For PLATFORM OSX */ -extern uint32_t raaz_tobe32(uint32_t x);-extern uint64_t raaz_tobe64(uint64_t x);-extern uint32_t raaz_tole32(uint32_t x);-extern uint64_t raaz_tole64(uint64_t x);+   static inline uint32_t raaz_bswap32(uint32_t x){ return OSSwapInt32(x); }+   static inline uint64_t raaz_bswap64(uint64_t x){ return OSSwapInt64(x); } +#elif defined(PLATFORM_WINDOWS)+#  include<stdlib.h>+   static inline uint32_t raaz_bswap32(uint32_t x){ return _byteswap_ulong(x); }+   static inline uint64_t raaz_bswap64(uint64_t x){ return _byteswap_uint64(x); }++#elif defined(PLATFORM_OPENBSD)+#  include <sys/endian.h>+   static inline uint32_t raaz_bswap32(uint32_t x){ return bswap32(x); }+   static inline uint64_t raaz_bswap64(uint64_t x){ return bswap64(x); }++#elif defined(PLATFORM_LINUX) /* All other platforms */+#  include <byteswap.h>+   static inline uint32_t raaz_bswap32(uint32_t x){ return bswap_32(x); }+   static inline uint64_t raaz_bswap64(uint64_t x){ return bswap_64(x); } #else+  /* We do not have platform specific byte swap */+# define __RAAZ_REQUIRE_PORTABLE_SWAP__ -/* We are in GCC, so pick up the relevant platform specific functions- * and wrap it in a static inline declaration. These- */+  extern uint32_t raaz_bswap32(uint32_t x);+  extern uint64_t raaz_bswap64(uint64_t x); -#  ifdef PLATFORM_OSX-#    include <libkern/OSByteOrder.h> /* For PLATFORM OSX */+#endif -     static inline uint32_t raaz_bswap32(uint32_t x){ return OSSwapInt32(x); }-     static inline uint64_t raaz_bswap64(uint64_t x){ return OSSwapInt64(x); } -#  else /* For other systems */-#    include <byteswap.h>-     static inline uint32_t raaz_bswap32(uint32_t x){ return bswap_32(x); }-     static inline uint64_t raaz_bswap64(uint64_t x){ return bswap_64(x); }-#  endif+#ifdef __GNUC__ +/* For GNUC compiler use byte order checks to define efficient endian+ * conversion */+ #  if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__     static inline uint32_t raaz_tobe32(uint32_t x){ return raaz_bswap32(x); }@@ -71,4 +80,21 @@  #  endif /* Byte order */ +#else  /* Not __GNUC__ use portable implementations */+#  define __RAAZ_REQUIRE_PORTABLE_ENDIAN__++   extern uint32_t raaz_tobe32(uint32_t x);+   extern uint64_t raaz_tobe64(uint64_t x);+   extern uint32_t raaz_tole32(uint32_t x);+   extern uint64_t raaz_tole64(uint64_t x);+ #endif++/* These are the C functions that are exported for FFI calls to+ * Haskell. Their definitions are available in endian.c+ */++extern uint32_t raazSwap32      (uint32_t a);+extern uint64_t raazSwap64      (uint64_t a);+extern void     raazSwap32Array (uint32_t *ptr, int n);+extern void     raazSwap64Array (uint64_t *ptr, int n);
+ cbits/raaz/core/memory.c view
@@ -0,0 +1,34 @@+# ifdef PLATFORM_WINDOWS+# include <windows.h>++   typedef BOOL WINAPI (*VirtualFunction)(LPVOID, SIZE_T);++#else /* we assume posix system */++#  include <sys/mman.h>++#endif++/* Locks and Unlocks Memory */+int raazMemorylock(void* ptr, size_t size){+#ifdef PLATFORM_WINDOWS+  VirtualFunction func =+     (VirtualFunction)GetProcAddress(GetModuleHandle(TEXT("kernel32")),+				     "VirtualLock");+  return !func(ptr, size);+#else+    return mlock(ptr,size);+#endif++}++void raazMemoryunlock(void* ptr, size_t size){+#ifdef PLATFORM_WINDOWS+  VirtualFunction func =+     (VirtualFunction)GetProcAddress(GetModuleHandle (TEXT("kernel32")),+				     "VirtualUnlock");+  func(ptr, size);+#else  /* posix */+    munlock(ptr,size);+#endif+}
+ cbits/raaz/hash/blake2/blake2b/constants.h view
@@ -0,0 +1,12 @@+#pragma once++#include <raaz/hash/blake2/common.h>++const Word2b iv2b0 = 0x6a09e667f3bcc908ULL;+const Word2b iv2b1 = 0xbb67ae8584caa73bULL;+const Word2b iv2b2 = 0x3c6ef372fe94f82bULL;+const Word2b iv2b3 = 0xa54ff53a5f1d36f1ULL;+const Word2b iv2b4 = 0x510e527fade682d1ULL;+const Word2b iv2b5 = 0x9b05688c2b3e6c1fULL;+const Word2b iv2b6 = 0x1f83d9abfb41bd6bULL;+const Word2b iv2b7 = 0x5be0cd19137e2179ULL;
+ cbits/raaz/hash/blake2/blake2b/portable.c view
@@ -0,0 +1,290 @@+#include <raaz/hash/blake2/common.h>+#include <raaz/hash/blake2/blake2b/constants.h>++static inline Word2b R(Word2b x, int i)+{+    return (x << (64 - i)) | (x >> i);+}++++++# define G(a,b,c,d,m0,m1)		      \+    {					      \+	a += b + m0  ; d ^= a; d = R(d,32);   \+	c += d       ; b ^= c; b = R(b,24);   \+	a += b + m1  ; d ^= a; d = R(d,16);   \+	c += d       ; b ^= c; b = R(b,63);   \+    }++++/* Definitions for Blake2b */++# define G0(i,j) G(x0, x4, x8,  x12, w##i, w##j);+# define G1(i,j) G(x1, x5, x9,  x13, w##i, w##j);+# define G2(i,j) G(x2, x6, x10, x14, w##i, w##j);+# define G3(i,j) G(x3, x7, x11, x15, w##i, w##j);++# define G4(i,j) G(x0, x5, x10, x15, w##i, w##j);+# define G5(i,j) G(x1, x6, x11, x12, w##i, w##j);+# define G6(i,j) G(x2, x7, x8,  x13, w##i, w##j);+# define G7(i,j) G(x3, x4, x9,  x14, w##i, w##j);++# define ROUND(i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15) \+	{							      \+	    G0( i0,i1 ); G1( i2 ,i3  ); G2( i4 ,i5  ); G3( i6 ,i7  ); \+	    G4( i8,i9 ); G5( i10,i11 ); G6( i12,i13 ); G7( i14,i15 ); \+	}+++/*++This is the block compression algorithm for blake2b. Besides teh usual+suspects there are the following additional parameters.++1. upper  -- The upper 64 bits of the counter+2. lower  -- The lower 64 bits of the counter+3. f0, f1 -- the finalisation flag++*/+++#define LOAD(i) (raaz_tole64((*mesg)[(i)]))++# pragma GCC optimize "tree-vectorize"++void raazHashBlake2bPortableBlockCompress( Block2b *mesg, int nblocks,+					   Word2b *Upper, Word2b *Lower,+					   Blake2b h)+{+    register Word2b x0,  x1,  x2,  x3;  /* row 0  */+    register Word2b x4,  x5,  x6,  x7;  /* row 1  */+    register Word2b x8,  x9,  x10, x11;  /* row 2  */+    register Word2b x12, x13, x14, x15;  /* row 3  */++    /* Input block */+    register Word2b w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;++    /* Variable that contains the hash */+    Word2b  h0, h1, h2, h3, h4, h5, h6, h7;+++    register Word2b upper, lower;+    upper = *Upper;+    lower = *Lower;++    /* Initialisation hash */+    h0 = h[0];+    h1 = h[1];+    h2 = h[2];+    h3 = h[3];+    h4 = h[4];+    h5 = h[5];+    h6 = h[6];+    h7 = h[7];++    while( nblocks > 0)+    {++	/* Initialisation hashes+++	   Normally, we would like to put the length increment at the+	   end of the body; somewhere close to the place where we move+	   to the next block. However, when hashing the i-th block of+	   input, we need to set upto the initial value with the total+	   size of data including the i-th block. So we start with an+	   increment the length counter.++	*/+++	if (lower > UINT64_MAX - sizeof(Block2b)) { ++upper; } /* Increment the counter */+	lower += sizeof(Block2b);+++	x0 = h0;+	x1 = h1;+	x2 = h2;+	x3 = h3;+	x4 = h4;+	x5 = h5;+	x6 = h6;+	x7 = h7;++	/* Initialisation iv  */++	x8  = iv2b0;+	x9  = iv2b1;+	x10 = iv2b2;+	x11 = iv2b3;+	x12 = iv2b4 ^ lower;+	x13 = iv2b5 ^ upper;+	x14 = iv2b6;+	x15 = iv2b7;++	/* Load the block */++	w0  = LOAD(0);+	w1  = LOAD(1);+	w2  = LOAD(2);+	w3  = LOAD(3);+	w4  = LOAD(4);+	w5  = LOAD(5);+	w6  = LOAD(6);+	w7  = LOAD(7);+	w8  = LOAD(8);+	w9  = LOAD(9);+	w10 = LOAD(10);+	w11 = LOAD(11);+	w12 = LOAD(12);+	w13 = LOAD(13);+	w14 = LOAD(14);+	w15 = LOAD(15);+++	ROUND(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15); /* 0 */+	ROUND( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3); /* 1 */+	ROUND( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4); /* 2 */+	ROUND(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8); /* 3 */+	ROUND(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13); /* 4 */+	ROUND(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9); /* 5 */+	ROUND( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11); /* 6 */+	ROUND( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10); /* 7 */+	ROUND(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5); /* 8 */+	ROUND( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0); /* 9 */+++	ROUND(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15); /* 10 */+	ROUND( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3); /* 11 */++	/* Update the hash */++	h0 ^= x0 ^ x8;+	h1 ^= x1 ^ x9;+	h2 ^= x2 ^ x10;+	h3 ^= x3 ^ x11;+	h4 ^= x4 ^ x12;+	h5 ^= x5 ^ x13;+	h6 ^= x6 ^ x14;+	h7 ^= x7 ^ x15;++	/* Move to the next block */+	--nblocks; ++mesg;++    }++    h[0] = h0;+    h[1] = h1;+    h[2] = h2;+    h[3] = h3;+    h[4] = h4;+    h[5] = h5;+    h[6] = h6;+    h[7] = h7;+    *Upper = upper;+    *Lower = lower;+}++/* This is the function for compressing the last block. The nbytes should be <= block size */++#undef  LOAD+#define LOAD(i) (raaz_tole64(mesg[(i)]))+void raazHashBlake2bPortableLastBlock( Block2b mesg, int nbytes,+				       Word2b upper, Word2b lower,+				       Word2b f0 , Word2b f1,+				       Blake2b h)+{++    register Word2b x0,  x1,  x2,  x3;  /* row 0  */+    register Word2b x4,  x5,  x6,  x7;  /* row 1  */+    register Word2b x8,  x9,  x10, x11;  /* row 2  */+    register Word2b x12, x13, x14, x15;  /* row 3  */++    /* Input block */+    register Word2b w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;++    /* Variable that contains the hash */+    Word2b  h0, h1, h2, h3, h4, h5, h6, h7;++    /* Initialisation hashes++       The increment is here for the same reason as in the block+       compression function.++    */+++    if (lower > UINT64_MAX - ((Word2b)nbytes)) { ++upper; } /* Increment the counter */+    lower += nbytes;+++    x0 = h[0];+    x1 = h[1];+    x2 = h[2];+    x3 = h[3];+    x4 = h[4];+    x5 = h[5];+    x6 = h[6];+    x7 = h[7];++    /* Initialisation iv  */++    x8  = iv2b0;+    x9  = iv2b1;+    x10 = iv2b2;+    x11 = iv2b3;+    x12 = iv2b4 ^ lower;+    x13 = iv2b5 ^ upper;+    x14 = iv2b6 ^ f0;+    x15 = iv2b7 ^ f1;++    /* Load the block */++    w0  = LOAD(0);+    w1  = LOAD(1);+    w2  = LOAD(2);+    w3  = LOAD(3);+    w4  = LOAD(4);+    w5  = LOAD(5);+    w6  = LOAD(6);+    w7  = LOAD(7);+    w8  = LOAD(8);+    w9  = LOAD(9);+    w10 = LOAD(10);+    w11 = LOAD(11);+    w12 = LOAD(12);+    w13 = LOAD(13);+    w14 = LOAD(14);+    w15 = LOAD(15);+++    ROUND(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15); /* 0 */+    ROUND( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3); /* 1 */+    ROUND( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4); /* 2 */+    ROUND(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8); /* 3 */+    ROUND(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13); /* 4 */+    ROUND(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9); /* 5 */+    ROUND( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11); /* 6 */+    ROUND( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10); /* 7 */+    ROUND(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5); /* 8 */+    ROUND( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0); /* 9 */+++    ROUND(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15); /* 10 */+    ROUND( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3); /* 11 */++    /* Update the hash */++    h[0] ^= x0 ^ x8;+    h[1] ^= x1 ^ x9;+    h[2] ^= x2 ^ x10;+    h[3] ^= x3 ^ x11;+    h[4] ^= x4 ^ x12;+    h[5] ^= x5 ^ x13;+    h[6] ^= x6 ^ x14;+    h[7] ^= x7 ^ x15;++}
+ cbits/raaz/hash/blake2/blake2s/constants.h view
@@ -0,0 +1,12 @@+#pragma once++#include <raaz/hash/blake2/common.h>++const Word2s iv2s0 = 0x6a09e667UL;+const Word2s iv2s1 = 0xbb67ae85UL;+const Word2s iv2s2 = 0x3c6ef372UL;+const Word2s iv2s3 = 0xa54ff53aUL;+const Word2s iv2s4 = 0x510e527fUL;+const Word2s iv2s5 = 0x9b05688cUL;+const Word2s iv2s6 = 0x1f83d9abUL;+const Word2s iv2s7 = 0x5be0cd19UL;
+ cbits/raaz/hash/blake2/blake2s/portable.c view
@@ -0,0 +1,284 @@+#include <raaz/hash/blake2/common.h>+#include <raaz/hash/blake2/blake2s/constants.h>+++static inline Word2s R(Word2s x, int i)+{+    return (x << (32 - i)) | (x >> i);+}++static inline Word2s  low32(Word2b x)+{+    return ((Word2s) x);+}+++static inline Word2s  high32(Word2b x)+{+    return ((Word2s) (x >> 32));+}++# define G(a,b,c,d,m0,m1)		      \+    {					      \+	a += b + m0 ; d ^= a; d = R(d,16);    \+	c += d      ; b ^= c; b = R(b,12);    \+	a += b + m1 ; d ^= a; d = R(d,8);     \+	c += d      ; b ^= c; b = R(b,7);     \+    }+++/* Definitions for Blake2b */++# define G0(i,j) G(x0, x4, x8,  x12, w##i, w##j);+# define G1(i,j) G(x1, x5, x9,  x13, w##i, w##j);+# define G2(i,j) G(x2, x6, x10, x14, w##i, w##j);+# define G3(i,j) G(x3, x7, x11, x15, w##i, w##j);++# define G4(i,j) G(x0, x5, x10, x15, w##i, w##j);+# define G5(i,j) G(x1, x6, x11, x12, w##i, w##j);+# define G6(i,j) G(x2, x7, x8,  x13, w##i, w##j);+# define G7(i,j) G(x3, x4, x9,  x14, w##i, w##j);++# define ROUND(i0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15) \+    {								      \+	G0( i0,i1 ); G1( i2 ,i3  ); G2( i4 ,i5  ); G3( i6 ,i7  );     \+	G4( i8,i9 ); G5( i10,i11 ); G6( i12,i13 ); G7( i14,i15 );     \+    }+++/*++This is the block compression algorithm for blake2b. Besides teh usual+suspects there are the following additional parameters.++1. upper  -- The upper 64 bits of the counter+2. lower  -- The lower 64 bits of the counter+3. f0, f1 -- the finalisation flag++*/+++#define LOAD(i) (raaz_tole32((*mesg)[(i)]))++# pragma GCC optimize "tree-vectorize"++void raazHashBlake2sPortableBlockCompress( Block2s *mesg, int nblocks, Word2b length, Blake2s h)+{+    register Word2s x0,  x1,  x2,  x3;   /* row 0  */+    register Word2s x4,  x5,  x6,  x7;   /* row 1  */+    register Word2s x8,  x9,  x10, x11;  /* row 2  */+    register Word2s x12, x13, x14, x15;  /* row 3  */++    /* Input block */+    register Word2s w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;++    /* Variable that contains the hash */+    Word2s  h0, h1, h2, h3, h4, h5, h6, h7;++    /* Initialisation hash */+    h0 = h[0];+    h1 = h[1];+    h2 = h[2];+    h3 = h[3];+    h4 = h[4];+    h5 = h[5];+    h6 = h[6];+    h7 = h[7];++    while( nblocks > 0)+    {++	/* Initialisation hashes+++	   Normally, we would like to put the length increment at the+	   end of the body; somewhere close to the place where we move+	   to the next block. However, when hashing the i-th block of+	   input, we need to set upto the initial value with the total+	   size of data including the i-th block. So we start with an+	   increment the length counter.++	*/++	length += sizeof(Block2s);++++	x0 = h0;+	x1 = h1;+	x2 = h2;+	x3 = h3;+	x4 = h4;+	x5 = h5;+	x6 = h6;+	x7 = h7;++	/* Initialisation iv  */++	x8  = iv2s0;+	x9  = iv2s1;+	x10 = iv2s2;+	x11 = iv2s3;+	x12 = iv2s4 ^ low32(length);+	x13 = iv2s5 ^ high32(length);+	x14 = iv2s6;+	x15 = iv2s7;++	/* Load the block */++	w0  = LOAD(0);+	w1  = LOAD(1);+	w2  = LOAD(2);+	w3  = LOAD(3);+	w4  = LOAD(4);+	w5  = LOAD(5);+	w6  = LOAD(6);+	w7  = LOAD(7);+	w8  = LOAD(8);+	w9  = LOAD(9);+	w10 = LOAD(10);+	w11 = LOAD(11);+	w12 = LOAD(12);+	w13 = LOAD(13);+	w14 = LOAD(14);+	w15 = LOAD(15);+++	ROUND(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15); /* 0 */+	ROUND( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3); /* 1 */+	ROUND( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4); /* 2 */+	ROUND(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8); /* 3 */+	ROUND(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13); /* 4 */+	ROUND(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9); /* 5 */+	ROUND( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11); /* 6 */+	ROUND( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10); /* 7 */+	ROUND(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5); /* 8 */+	ROUND( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0); /* 9 */+++	/* Update the hash */++	h0 ^= x0 ^ x8;+	h1 ^= x1 ^ x9;+	h2 ^= x2 ^ x10;+	h3 ^= x3 ^ x11;+	h4 ^= x4 ^ x12;+	h5 ^= x5 ^ x13;+	h6 ^= x6 ^ x14;+	h7 ^= x7 ^ x15;++	/* Move to the next block */+	--nblocks; ++mesg;++    }++    h[0] = h0;+    h[1] = h1;+    h[2] = h2;+    h[3] = h3;+    h[4] = h4;+    h[5] = h5;+    h[6] = h6;+    h[7] = h7;++}+++/* This is the function for compressing the last block. The nbytes should be <= block size */++#undef LOAD+#define LOAD(i) (raaz_tole32(mesg[(i)]))++void raazHashBlake2sPortableLastBlock( Block2s mesg, int nbytes,+				       Word2b length,+				       Word2s f0 , Word2s f1,+				       Blake2s h)+{++    register Word2s x0,  x1,  x2,  x3;  /* row 0  */+    register Word2s x4,  x5,  x6,  x7;  /* row 1  */+    register Word2s x8,  x9,  x10, x11;  /* row 2  */+    register Word2s x12, x13, x14, x15;  /* row 3  */++    /* Input block */+    register Word2s w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;++    /* Variable that contains the hash */+    Word2s  h0, h1, h2, h3, h4, h5, h6, h7;++    /* Initialisation hashes++       The increment is here for the same reason as in the block+       compression function.++    */+++    length += nbytes;+++    x0 = h[0];+    x1 = h[1];+    x2 = h[2];+    x3 = h[3];+    x4 = h[4];+    x5 = h[5];+    x6 = h[6];+    x7 = h[7];++    /* Initialisation iv  */++    x8  = iv2s0;+    x9  = iv2s1;+    x10 = iv2s2;+    x11 = iv2s3;+    x12 = iv2s4 ^ low32(length);+    x13 = iv2s5 ^ high32(length);+    x14 = iv2s6 ^ f0;+    x15 = iv2s7 ^ f1;++    /* Load the block */++    w0  = LOAD(0);+    w1  = LOAD(1);+    w2  = LOAD(2);+    w3  = LOAD(3);+    w4  = LOAD(4);+    w5  = LOAD(5);+    w6  = LOAD(6);+    w7  = LOAD(7);+    w8  = LOAD(8);+    w9  = LOAD(9);+    w10 = LOAD(10);+    w11 = LOAD(11);+    w12 = LOAD(12);+    w13 = LOAD(13);+    w14 = LOAD(14);+    w15 = LOAD(15);+++    ROUND(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15); /* 0 */+    ROUND( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3); /* 1 */+    ROUND( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4); /* 2 */+    ROUND(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8); /* 3 */+    ROUND(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13); /* 4 */+    ROUND(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9); /* 5 */+    ROUND( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11); /* 6 */+    ROUND( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10); /* 7 */+    ROUND(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5); /* 8 */+    ROUND( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0); /* 9 */++++    /* Update the hash */++    h[0] ^= x0 ^ x8;+    h[1] ^= x1 ^ x9;+    h[2] ^= x2 ^ x10;+    h[3] ^= x3 ^ x11;+    h[4] ^= x4 ^ x12;+    h[5] ^= x5 ^ x13;+    h[6] ^= x6 ^ x14;+    h[7] ^= x7 ^ x15;++}
+ cbits/raaz/hash/blake2/common.h view
@@ -0,0 +1,17 @@+#pragma once++#include <raaz/core/endian.h>+#include <stdint.h>++#define HASH_SIZE  8+#define BLOCK_SIZE 16++typedef uint64_t Word2b;  /* basic unit for blake2b */+typedef uint32_t Word2s;  /* basic unit for blake2s */+++typedef Word2b Blake2b[HASH_SIZE];+typedef Word2b Block2b[BLOCK_SIZE];++typedef Word2s Blake2s[HASH_SIZE];+typedef Word2s Block2s[BLOCK_SIZE];
entropy/arc4random/Raaz/Entropy.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE ForeignFunctionInterface         #-}++-- | Entropy based on arc4random_buf (OpenBSD/NetBSD etc). module Raaz.Entropy( getEntropy ) where  import Control.Monad.IO.Class(MonadIO, liftIO)@@ -7,7 +9,7 @@  -- | The getrandom system call. foreign import ccall unsafe-  "arc4random"+  "arc4random_buf"   c_arc4random :: Pointer      -- Message                -> BYTES Int    -- number of bytes                -> IO (BYTES Int)
+ entropy/getrandom/Raaz/Entropy.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE ForeignFunctionInterface         #-}+-- | Entropy based on the getrandom system call on Linux.+module Raaz.Entropy( getEntropy ) where++import Control.Monad.IO.Class(MonadIO, liftIO)+import Raaz.Core.Types++-- | The getrandom system call.+foreign import ccall unsafe+  "getrandom"+  c_getrandom :: Pointer      -- Message+              -> BYTES Int    -- number of bytes to be read.+              -> Int          -- flags+              -> IO (BYTES Int)++-- | Get random bytes from using the @getrandom@ system call on+-- linux. This is only used to seed the PRG and not intended for call+-- by others.+getEntropy :: (MonadIO m, LengthUnit l) => l -> Pointer -> m (BYTES Int)+getEntropy l ptr = liftIO $ c_getrandom ptr lenBytes 0+  where lenBytes = inBytes l
entropy/urandom/Raaz/Entropy.hs view
@@ -1,3 +1,4 @@+-- | Entropy based on `/dev/urandom`. module Raaz.Entropy( getEntropy ) where  import Control.Monad.IO.Class( MonadIO, liftIO)
+ entropy/windows/Raaz/Entropy.hsc view
@@ -0,0 +1,51 @@+{-# LANGUAGE CPP #-}+module Raaz.Entropy( getEntropy ) where++#include <Windows.h>+#include <Wincrypt.h>++##if defined(i386_HOST_ARCH)+## define WINDOWS_CCONV stdcall+##elif defined(x86_64_HOST_ARCH)+## define WINDOWS_CCONV ccall+##else+## error Unknown mingw32 arch+##endif++import Control.Monad.IO.Class( MonadIO, liftIO)+import Control.Monad (when)+import Data.Bits ((.|.))+import Data.Word (Word8(), Word32())+import Foreign.Ptr (Ptr(), nullPtr, castPtr)+import Foreign.Storable (peek)+import Foreign.C.String (CWString())+import Raaz.Core++type HCRYPTPROV = Ptr ()++foreign import WINDOWS_CCONV unsafe "Wincrypt.h CryptGenRandom"+    c_CryptGenRandom :: HCRYPTPROV -> Word32 -> Ptr Word8 -> IO Bool++foreign import WINDOWS_CCONV unsafe "Wincrypt.h CryptAcquireContextW"+    c_CryptAcquireContext :: Ptr HCRYPTPROV -> CWString -> CWString+                          -> Word32 -> Word32 -> IO Bool++foreign import WINDOWS_CCONV unsafe "Wincrypt.h CryptReleaseContext"+    c_CryptReleaseContext :: HCRYPTPROV -> Word32 -> IO Bool++-- | Get cryptographically random bytes from the system.+getEntropy :: (MonadIO m, LengthUnit l) => l -> Pointer -> m (BYTES Int)+getEntropy l ptr = liftIO $ allocaBuffer ptrSize $ \ctx ->+    do let addr = castPtr ctx+       ctx_ok <- c_CryptAcquireContext addr nullPtr nullPtr+                       (#const PROV_RSA_FULL)+                       ((#const CRYPT_VERIFYCONTEXT) .|. (#const CRYPT_SILENT))+       when (not ctx_ok) $ fail "Call to CryptAcquireContext failed."+       ctx'    <- peek addr+       success <- c_CryptGenRandom ctx' (fromIntegral bytes) (castPtr ptr)+       _ <- c_CryptReleaseContext ctx' 0+       if success+          then return $ BYTES bytes+          else fail "Unable to generate entropy. Call to CryptGenRandom failed."+  where BYTES bytes = inBytes l+        ptrSize = BYTES ((#size HCRYPTPROV) :: Int)
+ liquid/LiquidSpec.hs view
@@ -0,0 +1,41 @@+import Control.Monad+import Language.Haskell.Liquid.Liquid+import System.Exit+import System.Directory+import System.FilePath++-- | Liquid haskell is run on these files/directors. If the given name+-- is a directory we recurse on all .hs/.lhs files in that directory.+toCheck :: [FilePath]+toCheck = [ "Raaz/Core/Encode"+          , "Raaz/Core/Types/Tuple.hs"+          , "Raaz/Hash/Sha1"+          , "Raaz/Hash/Sha224"+          , "Raaz/Hash/Sha256"+          , "Raaz/Hash/Sha384"+          , "Raaz/Hash/Sha512"+          ]++main :: IO ()+main = do allHsFiles toCheck >>= liquid+++allHsFiles :: [FilePath] -> IO [FilePath]+allHsFiles = fmap concat . mapM allHsFile++allHsFile :: FilePath -> IO [FilePath]+allHsFile fp = doesFileExist fp >>= handleFile++  where handleFile cond+           | cond && checkHs fp = return [fp]+           | cond               = return []+           | otherwise          = doesDirectoryExist fp >>= handleDir++        handleDir cond+           | cond       = recurse+           | otherwise  = return []++        recurse = listDirectory fp >>= allHsFiles . map (fp</>)++        checkHs fp = ext == ".hs" || ext == ".lhs"+          where ext = takeExtension fp
+ mans/Makefile view
@@ -0,0 +1,14 @@+MAN_PAGES=raaz.1  # Which man pages to generate.+MAN_PAGES_GZ= $(addsuffix .gz, ${MAN_PAGES})+MAN_SOURCES= $(addsuffix .md, ${MAN_PAGES})++.PHONY: all clean++all: ${MAN_PAGES_GZ}+clean:+	rm -f ${MAN_PAGES} ${MAN_PAGES_GZ}++${MAN_PAGES_GZ}:%.gz:%+	gzip $<+${MAN_PAGES}:%:%.md+	pandoc -s  $< -t man -o $@
+ mans/raaz.1.md view
@@ -0,0 +1,104 @@+---+title: RAAZ(1) The Raaz Cryptographic Library | Version 0.2+author: Piyush P Kurur+date: June 22, 2017+---++# NAME++raaz - Command line tool for the Raaz cryptographic library.++# SYNOPSIS++**raaz** **[-v|--version]**++**raaz** **[COMMAND]** **[COMMAND_OPTIONS]** **[ARGUMENTS]**+++# DESCRIPTION++Raaz is a cryptographic library for the Haskell programming+language. One of the important design goal is to use the type system+of Haskell to catch various bugs like buffer overflows and timing+attacks at compile time. Thus, Raaz is meant to be used as+cryptographic library for applications written in Haskell.+Nonetheless, we expose some of the implemented primitives using the+program **raaz** for use in shell scripts.++# OPTIONS AND SUB-COMMANDS+++The program **raaz** exposes the cryptographic primitives as+sub-commands. With no sub-commands **raaz** understands the following+options++**-h**, **--help**+:    Display help message. This option is supported by sub-commands as well+     in which case it displays the brief help of that sub-command.++**-v**, **--version**+:    Display the version of the underlying raaz library++The sub-commands of raaz falls in the following categories.++## Randomness++**raaz** **rand** [BYTES_TO_GENERATE]+++With no arguments this command generates a never ending stream of+cryptographically secure random bytes. For a non-negative integral+argument **N**, this command generates exactly **N** bytes of random+data.+++## File checksums++**raaz** **blake2bsum** [OPTIONS] *FILE1* *FILE2* ...++**raaz** **blake2ssum** [OPTIONS] *FILE1* *FILE2* ...++**raaz** **sha512sum** [OPTIONS] *FILE1* *FILE2* ...++**raaz** **sha256sum** [OPTIONS] *FILE1* *FILE2* ...++Use the above checksum commands to compute/verify file checksums.  All+these commands take the same set of options. One can use these+checksum commands to compute as well as verify the integrity of+files. In *compute mode*, the command prints one line in the format+(DIGEST 2*SPACE FILE) for each input file. The DIGEST is the base16+encoding of the cryptographic hash of the contents of the file. For+example,++```+$ raaz sha256sum /dev/null+e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  /dev/null++$ raaz blake2ssum /dev/null+69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9  /dev/null+```++In *computation mode*, a non-zero exist status indicates some error in+opening one of the input file.  In *verification mode*, **raaz**+returns a non-zero status if the checksum of a file does not match+with its associated input checksum. Thus, these commands can be used+to check the integrity of a set of files.+++These commands provide an alternative to the common unix commands+sha512sum and sha256sum. Therefore, checksums computed by one of these+programs can be verified by **raaz** with the appropriate sub-command+(and vice-versa).+++**Common options for all checksum commands**++**-c**, **--check**+:    *Verify* the checksums present in the input file instead of compute+     the checksum of the arguments.++**-q**, **--quiet**+:    While verifying do not print OK for successful checks. Only print failures.++**-s**, **--status**+:    While verifying do not print anything. Only return the appropriate exit status.
raaz.cabal view
@@ -1,15 +1,13 @@ name:    raaz-version: 0.1.1+version: 0.2.0  synopsis: The raaz cryptographic library. -description: Raaz is a cryptographic network library for Haskell-  designed to use strong typing to eliminate some common errors that-  occur in cryptographic settings like side channel attacks. This-  package implements basic types and cryptographic primitives like-  hashes, macs etc. Actual network protocols are expected to use this-  library. Common abstractions like for example packet parsing should-  be part of this library.+description: Raaz is a cryptographic library for Haskell. The library+  is designed with a special emphasis on using the type system of+  Haskell to eliminate a large set of vulnerabilities like buffer+  overflows, timing attacks etc. It also strives to achieve this+  safety with no compromise on performance.  homepage: http://github.com/raaz-crypto/raaz @@ -22,13 +20,22 @@ build-type:    Simple cabal-version: >=1.10 +extra-source-files: CHANGELOG.md+                  , README.md+                  , Releasing.md+                  , Reviewing.md  bug-reports: https://github.com/raaz-crypto/raaz/issues  -- List of platform specific source files. extra-source-files: entropy/urandom/Raaz/Entropy.hs                     entropy/arc4random/Raaz/Entropy.hs-+                    entropy/getrandom/Raaz/Entropy.hs+                    entropy/windows/Raaz/Entropy.hsc+                    -- The man page in markdown and its+                    -- makefile. Needs pandoc to build+                    mans/raaz.1.md+                    mans/Makefile source-repository head   type: git   location: https://github.com/raaz-crypto/raaz@@ -41,13 +48,6 @@      Default: False      Manual: True --flag opt-vectorise-     Description: Enable vectorisation for gcc. This is not always an optimisation and needs to be benchmarked.-       Also gains are fairly minimal if you do not use opt-natvive.-     Default: False-     Manual: True- flag vector128      Description: Make use of vector instructions with size being 128. Do not enable this unless you have reasons        to. It is better to use opt-native and opt-vectorise and let gcc have a go at the portable implementation@@ -68,6 +68,17 @@      Description: Support avx2 optimisations. Warning: enable only if you are sure of support.      Default: False      Manual: True++flag linux-getrandom+     Description: Use the getrandom for system entropy instead of /dev/urandom. Available only on linux kernel > 3.17.+     Default: False+     Manual: True++flag liquidhaskell+     Description: Use liquid haskell form verifying properties. Only for developers.+     Default: False+     Manual: True+ ----------------------------- The library -----------------------------------------------------  library@@ -77,7 +88,8 @@   exposed-modules: Raaz                  , Raaz.Core                  , Raaz.Core.ByteSource-                 , Raaz.Core.DH+                 , Raaz.Core.CpuSupports+               --  , Raaz.Core.DH                  , Raaz.Core.Encode                  , Raaz.Core.Memory                  , Raaz.Core.MonoidalAction@@ -91,6 +103,8 @@                  --                  , Raaz.Hash                  , Raaz.Hash.Internal+                 , Raaz.Hash.Blake2+                 , Raaz.Hash.Blake2.Implementation.CPortable                  , Raaz.Hash.Sha1                  , Raaz.Hash.Sha1.Implementation.CPortable                  , Raaz.Hash.Sha224@@ -130,6 +144,8 @@                -- Hashes                --                , Raaz.Hash.Internal.HMAC+               , Raaz.Hash.Blake2.Internal+               , Raaz.Hash.Blake2.Recommendation                , Raaz.Hash.Sha.Util                , Raaz.Hash.Sha1.Internal                , Raaz.Hash.Sha1.Recommendation@@ -157,7 +173,6 @@   build-depends: base                           >= 4.6  &&  < 4.11                , bytestring                     >= 0.9  &&  < 0.11                , deepseq                        >= 1.1  &&  < 1.5-               , mtl                            >= 2.1  &&  < 2.3                , vector                         >= 0.7.1 && < 0.13   if impl(ghc < 8)     -- 'transformers' needed for "Control.Monad.IO.Class" only@@ -166,6 +181,8 @@    c-sources: cbits/raaz/core/endian.c            -- hash implementations+           , cbits/raaz/hash/blake2/blake2b/portable.c+           , cbits/raaz/hash/blake2/blake2s/portable.c            , cbits/raaz/hash/sha1/portable.c            , cbits/raaz/hash/sha256/portable.c            , cbits/raaz/hash/sha512/portable.c@@ -174,10 +191,16 @@            , cbits/raaz/cipher/aes/cportable.c            -- chacha20            , cbits/raaz/cipher/chacha20/cportable.c-+           -- memory management+           , cbits/raaz/core/memory.c+           -- cpu support+           , cbits/raaz/core/cpusupports.c   include-dirs: cbits   includes: raaz/core/endian.h-  install-includes: raaz/core/endian.h+  install-includes: cbits/raaz/core/endian.h+                  , cbits/raaz/hash/blake2/common.h+                  , cbits/raaz/hash/blake2/blake2b/constants.h+                  , cbits/raaz/hash/blake2/blake2s/constants.h                   , cbits/raaz/cipher/aes/common.h                   , cbits/raaz/cipher/aes/cportable.h                   , cbits/raaz/cipher/chacha20/common.h@@ -186,8 +209,8 @@   if flag(opt-native)     cc-options: -march=native -  if flag(opt-vectorise)-    cc-options: -ftree-vectorize+  if arch(x86_64)+    cc-options: -DARCH_X86_64    if flag(vector128)      cpp-options: -DHAVE_VECTOR_128@@ -212,25 +235,36 @@    ----------------------- System specific configurations ---------------------------------- -  if !os(windows) -     cpp-options: -DHAVE_MLOCK--     --------------------- Entropy ----------------------------------------------+  if os(linux)+     cc-options: -DPLATFORM_LINUX+  if os(osx)+     cc-options: -DPLATFORM_OSX+  if os(openbsd)+     cc-options: -DPLATFORM_OPENBSD+  if os(windows)+     cc-options: -DPLATFORM_WINDOWS -DUNICODE+     cpp-options: -DPLATFORM_WINDOWS+     extra-libraries: Advapi32, Kernel32+     build-tools: hsc2hs -     if os(openbsd)-        -- Entropy for openbsd using arc4random-        hs-source-dirs: entropy/arc4random+  --------------------- Entropy ---------------------------------------------- -     if !os(openbsd)+  if os(openbsd) || os(netbsd)+    -- Entropy for openbsd using arc4random+    hs-source-dirs: entropy/arc4random+  else+    if os(linux) && flag(linux-getrandom)+        -- Use getentropy on linux+        hs-source-dirs: entropy/getrandom+    if os(windows)+        -- Use CryptGenRandom+        hs-source-dirs: entropy/windows+    else         -- Entropy for generic posix by reading /dev/urandom         hs-source-dirs: entropy/urandom -  if os(osx)-     -- Endian coversion code is different for osx.-     cc-options: -DPLATFORM_OSX - ---------------------------- Executables -------------------------------------------------  executable raaz@@ -239,8 +273,11 @@   main-is: Main.hs   other-modules: Command.Checksum                , Command.Rand+               , Command.CpuInfo+               , Usage   build-depends: base-               , raaz     == 0.1.1+               , optparse-applicative >= 0.10.0+               , raaz   if impl(ghc < 8)     -- 'transformers' needed for "Control.Monad.IO.Class" only     -- starting with base-4.9 we don't need 'transformers' anymore@@ -262,6 +299,9 @@   if flag(vector512)      cpp-options: -DHAVE_VECTOR_512 +  if !os(windows)+     cpp-options: -DHAVE_DEV_NULL+   ghc-options: -Wall    other-modules: Common@@ -272,6 +312,7 @@                , Common.Utils                , Raaz.Cipher.AESSpec                , Raaz.Cipher.ChaCha20Spec+               , Raaz.Core.ByteSourceSpec                , Raaz.Core.EncodeSpec                , Raaz.Core.MemorySpec                , Raaz.Core.Types.WordSpec@@ -282,7 +323,7 @@                , Raaz.Hash.Sha256Spec                , Raaz.Hash.Sha384Spec                , Raaz.Hash.Sha512Spec-               , Raaz.Hash.Blake256Spec+               , Raaz.Hash.Blake2Spec     build-depends: base@@ -290,9 +331,28 @@                , HUnit                          >= 1.2                , QuickCheck                     >= 2.4                , hspec+               , hspec-discover                , transformers-               , raaz                           == 0.1.1+               , raaz                , vector++-------------------------- Liquid haskell verification -------------------------------------++test-Suite liquidspec+  hs-source-dirs: liquid+  default-language: Haskell2010+  main-is: LiquidSpec.hs+  type: exitcode-stdio-1.0+  build-depends: base+++  if flag(liquidhaskell)+    build-depends: liquidhaskell                >=0.8+                 , directory+                 , filepath+    buildable: True+  else+    buildable: False  ---------------------------------------------- Bench marks ----------------------------------------- 
spec/Common/Instances.hs view
@@ -50,6 +50,16 @@ instance Arbitrary SHA384 where   arbitrary = genEncodable +instance Arbitrary BLAKE2b where+  arbitrary = genEncodable++instance Arbitrary BLAKE2s where+  arbitrary = genEncodable++---------------- Parameter block for Blake          -------------++---------------- Arbitrary instaces of encoded data --------------+ instance Arbitrary Base16 where   arbitrary =  (encodeByteString . pack) <$> listOf arbitrary 
spec/Common/Utils.hs view
@@ -78,7 +78,7 @@   -- | Run a property with a given generator.-feed :: Show a => Gen a -> (a -> IO pr) -> Property+feed :: (Testable pr, Show a) => Gen a -> (a -> IO pr) -> Property feed gen pr = monadicIO $ pick gen >>= (run . pr)  repeated :: Monoid m => m -> Int -> m
+ spec/Raaz/Core/ByteSourceSpec.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE CPP #-}+module Raaz.Core.ByteSourceSpec where++import qualified Data.ByteString as B+import           System.IO+import           System.IO.Unsafe++import           Common+++readResult :: ByteSource src => BYTES Int -> src -> IO (FillResult src)+readResult n src = allocaBuffer n $ fillBytes n src++{-# NOINLINE readResultPure #-}+readResultPure :: PureByteSource src => BYTES Int -> src -> FillResult src+readResultPure n src = unsafePerformIO $ readResult n src++devNullExpectation :: Expectation++#ifdef HAVE_DEV_NULL+devNullExpectation =  withBinaryFile "/dev/null" ReadMode (readResult 0) `shouldReturn` (Exhausted 0)+#else+devNullExpectation = pendingWith "Non-posix system needs an equivalent of /dev/null"+#endif+++spec :: Spec+spec = do+  describe "/dev/null" $+    it "should return Exhausted even for a read request of 0" devNullExpectation++  let genL :: [ByteString] ->  Gen (BYTES Int)+      genL bs =  fromIntegral <$> choose (0, sum $ map B.length bs)+    in describe "concatenated source" $+       prop "reading from a list is equivalent to reading from concatenation" $+       \ bs -> forAll (genL bs) $ \ n -> (B.concat <$> readResultPure n bs) == readResultPure n (B.concat bs)
− spec/Raaz/Hash/Blake256Spec.hs
@@ -1,47 +0,0 @@--{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE OverloadedStrings    #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Raaz.Hash.Blake256Spec where--import           Common--{--import qualified Common.Hash as CH---hashesTo :: ByteString -> BLAKE256 -> Spec-hashesTo = GH.hashesTo--}--spec :: Spec-spec = it "Blake tests" $ pendingWith "Blake"-{--spec =  do--  prop "store followed by load returns original value" $ \ (x :: BLAKE256) ->-    storeAndThenLoad x `shouldReturn` x--  prop "checks that the padding string has the same length as padLength" $-    \ w -> padLen w == (RC.length $ pad w)--  prop "length after padding should be an integral multiple of block size" $-    \ w -> (padLen w + bitsQuot w) `rem` blockSz == 0-  ---  -- Some unit tests-  ---  "BLAKE" `hashesTo` "07663e00cf96fbc136cf7b1ee099c95346ba3920893d18cc8851f22ee2e36aa6"--  "Go" `hashesTo` "fd7282ecc105ef201bb94663fc413db1b7696414682090015f17e309b835f1c2"--  "The quick brown fox jumps over the lazy dog" `hashesTo` "7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7"--  "HELP! I'm trapped in hash!" `hashesTo` "1e75db2a709081f853c2229b65fd1558540aa5e7bd17b04b9a4b31989effa711"--  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congu"-    `hashesTo` "af95fffc7768821b1e08866a2f9f66916762bfc9d71c4acb5fd515f31fd6785a"--  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est." `hashesTo`-    "4181475cb0c22d58ae847e368e91b4669ea2d84bcd55dbf01fe24bae6571dd08"--}
+ spec/Raaz/Hash/Blake2Spec.hs view
@@ -0,0 +1,79 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Raaz.Hash.Blake2Spec where++import           Prelude hiding (replicate)++import           Common+import qualified Common.Hash as CH++{--+hashesTo :: ByteString -> BLAKE2b -> Spec+hashesTo = CH.hashesTo++hmacsTo  :: ByteString -> HMAC BLAKE2b -> Key (HMAC BLAKE2b) -> Spec+hmacsTo  = CH.hmacsTo+--}++spec2b :: Spec+spec2b = describe "blake2b" $ do+  basicEndianSpecs (undefined :: BLAKE2b)++  ------------- Unit tests -------------------------+  "" `hashesTo`+    "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"+  "abc" `hashesTo`+    "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"++  where hashesTo :: ByteString -> BLAKE2b -> Spec+        hashesTo = CH.hashesTo+++spec2s :: Spec+spec2s = describe "blake2s" $ do+  basicEndianSpecs (undefined :: BLAKE2s)++  ------------- Unit tests -------------------------+  "" `hashesTo` "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"++  "abc" `hashesTo` "508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"+++  where hashesTo :: ByteString -> BLAKE2s -> Spec+        hashesTo = CH.hashesTo+++spec :: Spec+spec =  spec2b >> spec2s++++  {-+  --+  -- Some unit tests+  --+  "" `hashesTo`+    "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"++  "abc" `hashesTo`+    "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"++  "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" `hashesTo`+    "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"++  "The quick brown fox jumps over the lazy dog" `hashesTo`+    "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6"++  "The quick brown fox jumps over the lazy cog" `hashesTo`+    "3eeee1d0e11733ef152a6c29503b3ae20c4f1f3cda4cb26f1bc1a41f91c7fe4ab3bd86494049e201c4bd5155f31ecb7a3c8606843c4cc8dfcab7da11c8ae5045"++  "The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog" `hashesTo`+    "e489dcc2e8867d0bbeb0a35e6b94951a11affd7041ef39fa21719eb01800c29a2c3522924443939a7848fde58fb1dbd9698fece092c0c2b412c51a47602cfd38"++  -- Some hmac specs+  hmacSpec+++-}