From 92343f856acf0da2fe17b68740fdedaaee382444 Mon Sep 17 00:00:00 2001 From: Vincent Hanquez Date: Wed, 20 May 2015 06:07:31 +0100 Subject: [PATCH] add comments and description --- Crypto/Cipher/AES/Primitive.hs | 2 + Crypto/Cipher/Blowfish/Primitive.hs | 13 ++- Crypto/Cipher/Camellia/Primitive.hs | 3 +- Crypto/Cipher/DES/Primitive.hs | 10 ++- Crypto/Cipher/Types/AEAD.hs | 5 ++ Crypto/Cipher/Types/Block.hs | 1 + Crypto/Cipher/Types/GF.hs | 2 + Crypto/Cipher/Types/Utils.hs | 1 + Crypto/Hash.hs | 5 ++ Crypto/Internal/CompatPrim.hs | 5 ++ Crypto/Internal/Hex.hs | 119 ---------------------------- Crypto/Internal/WordArray.hs | 18 +++++ Crypto/Internal/Words.hs | 2 + Crypto/Number/Basic.hs | 1 + Crypto/Number/Compat.hs | 13 +++ Crypto/Number/F2m.hs | 1 + Crypto/PubKey/ECC/DH.hs | 28 ++++--- Crypto/Random.hs | 9 +++ Crypto/Random/Entropy/Backend.hs | 16 +++- Crypto/Random/Entropy/Unsafe.hs | 8 +- Crypto/Random/Types.hs | 8 ++ cryptonite.cabal | 1 - 22 files changed, 134 insertions(+), 137 deletions(-) delete mode 100644 Crypto/Internal/Hex.hs diff --git a/Crypto/Cipher/AES/Primitive.hs b/Crypto/Cipher/AES/Primitive.hs index 5ae76ec..47bfb62 100644 --- a/Crypto/Cipher/AES/Primitive.hs +++ b/Crypto/Cipher/AES/Primitive.hs @@ -89,6 +89,7 @@ instance BlockCipher128 AES where xtsEncrypt = encryptXTS xtsDecrypt = decryptXTS +-- | Create an AES AEAD implementation for GCM gcmMode :: AES -> AEADModeImpl AESGCM gcmMode aes = AEADModeImpl { aeadImplAppendHeader = gcmAppendAAD @@ -97,6 +98,7 @@ gcmMode aes = AEADModeImpl , aeadImplFinalize = gcmFinish aes } +-- | Create an AES AEAD implementation for OCB ocbMode :: AES -> AEADModeImpl AESOCB ocbMode aes = AEADModeImpl { aeadImplAppendHeader = ocbAppendAAD aes diff --git a/Crypto/Cipher/Blowfish/Primitive.hs b/Crypto/Cipher/Blowfish/Primitive.hs index 207efe8..bd863c3 100644 --- a/Crypto/Cipher/Blowfish/Primitive.hs +++ b/Crypto/Cipher/Blowfish/Primitive.hs @@ -37,8 +37,16 @@ data Context = BF (Int -> Word32) -- p (Int -> Word32) -- sbox2 (Int -> Word32) -- sbox2 -encrypt, decrypt :: ByteArray ba => Context -> ba -> ba +-- | Encrypt blocks +-- +-- Input need to be a multiple of 8 bytes +encrypt :: ByteArray ba => Context -> ba -> ba encrypt = cipher + +-- | Decrypt blocks +-- +-- Input need to be a multiple of 8 bytes +decrypt :: ByteArray ba => Context -> ba -> ba decrypt = cipher . decryptContext decryptContext :: Context -> Context @@ -50,6 +58,9 @@ cipher ctx b | B.length b `mod` 8 /= 0 = error "invalid data length" | otherwise = B.mapAsWord64 (coreCrypto ctx) b +-- | Initialize a new Blowfish context from a key. +-- +-- key need to be between 0 to 448 bits. initBlowfish :: ByteArrayAccess key => key -> CryptoFailable Context initBlowfish key | len > (448 `div` 8) = CryptoFailed $ CryptoError_KeySizeInvalid diff --git a/Crypto/Cipher/Camellia/Primitive.hs b/Crypto/Cipher/Camellia/Primitive.hs index 1d39d97..5a28a12 100644 --- a/Crypto/Cipher/Camellia/Primitive.hs +++ b/Crypto/Cipher/Camellia/Primitive.hs @@ -107,6 +107,7 @@ rotl128 v@(Word128 x1 x2) w (x1high, x1low) = splitBits (x1 `rotateL` w) (x2high, x2low) = splitBits (x2 `rotateL` w) +-- | Camellia context data Camellia = Camellia { k :: Array64 , kw :: Array64 @@ -135,9 +136,9 @@ setKeyInterim keyseed = (w64tow128 kL, w64tow128 kR, w64tow128 kA, w64tow128 kB) in (d4, d3) -- | Initialize a 128-bit key +-- -- Return the initialized key or a error message if the given -- keyseed was not 16-bytes in length. --- initCamellia :: ByteArray key => key -- ^ The key to create the camellia context -> CryptoFailable Camellia diff --git a/Crypto/Cipher/DES/Primitive.hs b/Crypto/Cipher/DES/Primitive.hs index 2da9803..90c86a3 100644 --- a/Crypto/Cipher/DES/Primitive.hs +++ b/Crypto/Cipher/DES/Primitive.hs @@ -11,12 +11,16 @@ ----------------------------------------------------------------------------- -module Crypto.Cipher.DES.Primitive (encrypt, decrypt, Block(..)) where +module Crypto.Cipher.DES.Primitive + ( encrypt + , decrypt + , Block(..) + ) where import Data.Word import Data.Bits -import Data.Memory.Endian +-- | a DES block (64 bits) newtype Block = Block { unBlock :: Word64 } type Rotation = Int @@ -210,12 +214,10 @@ takeDrop n (x:xs) = (x:ys, zs) -- | Basic DES encryption which takes a key and a block of plaintext -- and returns the encrypted block of ciphertext according to the standard. - encrypt :: Word64 -> Block -> Block encrypt = flip des_enc -- | Basic DES decryption which takes a key and a block of ciphertext and -- returns the decrypted block of plaintext according to the standard. - decrypt :: Word64 -> Block -> Block decrypt = flip des_dec diff --git a/Crypto/Cipher/Types/AEAD.hs b/Crypto/Cipher/Types/AEAD.hs index dd22d47..6555fe7 100644 --- a/Crypto/Cipher/Types/AEAD.hs +++ b/Crypto/Cipher/Types/AEAD.hs @@ -16,6 +16,7 @@ import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray) import qualified Crypto.Internal.ByteArray as B import Crypto.Internal.Imports +-- | AEAD Implementation data AEADModeImpl st = AEADModeImpl { aeadImplAppendHeader :: forall ba . ByteArrayAccess ba => st -> ba -> st , aeadImplEncrypt :: forall ba . ByteArray ba => st -> ba -> (ba, st) @@ -29,15 +30,19 @@ data AEAD cipher = forall st . AEAD , aeadState :: st } +-- | Append some header information to an AEAD context aeadAppendHeader :: ByteArrayAccess aad => AEAD cipher -> aad -> AEAD cipher aeadAppendHeader (AEAD impl st) aad = AEAD impl $ (aeadImplAppendHeader impl) st aad +-- | Encrypt some data and update the AEAD context aeadEncrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher) aeadEncrypt (AEAD impl st) ba = second (AEAD impl) $ (aeadImplEncrypt impl) st ba +-- | Decrypt some data and update the AEAD context aeadDecrypt :: ByteArray ba => AEAD cipher -> ba -> (ba, AEAD cipher) aeadDecrypt (AEAD impl st) ba = second (AEAD impl) $ (aeadImplDecrypt impl) st ba +-- | Finalize the AEAD context and return the authentication tag aeadFinalize :: AEAD cipher -> Int -> AuthTag aeadFinalize (AEAD impl st) n = (aeadImplFinalize impl) st n diff --git a/Crypto/Cipher/Types/Block.hs b/Crypto/Cipher/Types/Block.hs index a0d584c..a7f8f86 100644 --- a/Crypto/Cipher/Types/Block.hs +++ b/Crypto/Cipher/Types/Block.hs @@ -58,6 +58,7 @@ instance BlockCipher c => ByteArrayAccess (IV c) where instance Eq (IV c) where (IV a) == (IV b) = B.eq a b +-- | XTS callback type XTS ba cipher = (cipher, cipher) -> IV cipher -- ^ Usually represent the Data Unit (e.g. disk sector) -> DataUnitOffset -- ^ Offset in the data unit in number of blocks diff --git a/Crypto/Cipher/Types/GF.hs b/Crypto/Cipher/Types/GF.hs index ab77dbd..4172a24 100644 --- a/Crypto/Cipher/Types/GF.hs +++ b/Crypto/Cipher/Types/GF.hs @@ -20,6 +20,8 @@ import Foreign.Storable import Foreign.Ptr import Data.Bits +-- | Compute the gfmul with the XTS polynomial +-- -- block size need to be 128 bits. -- -- FIXME: add support for big endian. diff --git a/Crypto/Cipher/Types/Utils.hs b/Crypto/Cipher/Types/Utils.hs index 94f81a1..4ac6b56 100644 --- a/Crypto/Cipher/Types/Utils.hs +++ b/Crypto/Cipher/Types/Utils.hs @@ -12,6 +12,7 @@ module Crypto.Cipher.Types.Utils where import Crypto.Internal.ByteArray (ByteArray) import qualified Crypto.Internal.ByteArray as B +-- | Chunk some input byte array into @sz byte list of byte array. chunk :: ByteArray b => Int -> b -> [b] chunk sz bs = split bs where split b | B.length b <= sz = [b] diff --git a/Crypto/Hash.hs b/Crypto/Hash.hs index 86f13cb..d5090de 100644 --- a/Crypto/Hash.hs +++ b/Crypto/Hash.hs @@ -99,9 +99,14 @@ hashFinalize c = doFinalize undefined (B.copy c) (B.allocAndFreeze) hashInitWith :: HashAlgorithm alg => alg -> Context alg hashInitWith _ = hashInit +-- | Run the 'hash' function but takes an explicit hash algorithm parameter hashWith :: (ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg hashWith _ = hash +-- | Try to transform a bytearray into a Digest of specific algorithm. +-- +-- If the digest is not the right size for the algorithm specified, then +-- Nothing is returned. digestFromByteString :: (HashAlgorithm a, ByteArrayAccess ba) => ba -> Maybe (Digest a) digestFromByteString = from undefined where diff --git a/Crypto/Internal/CompatPrim.hs b/Crypto/Internal/CompatPrim.hs index 5822024..dd514e5 100644 --- a/Crypto/Internal/CompatPrim.hs +++ b/Crypto/Internal/CompatPrim.hs @@ -45,6 +45,8 @@ le32Prim w = w le32Prim = byteswap32Prim #endif +-- | Simple compatibility for byteswap the lower 32 bits of a Word# +-- at the primitive level byteswap32Prim :: Word# -> Word# #if __GLASGOW_HASKELL__ >= 708 byteswap32Prim w = byteSwap32# w @@ -74,6 +76,9 @@ convert4To32 a b c d = or# (or# c1 c2) (or# c3 c4) !c4 = a #endif +-- | Simple wrapper to handle pre 7.8 and future, where +-- most comparaison functions don't returns a boolean +-- anymore. #if __GLASGOW_HASKELL__ >= 708 booleanPrim :: Int# -> Bool booleanPrim v = tagToEnum# v diff --git a/Crypto/Internal/Hex.hs b/Crypto/Internal/Hex.hs deleted file mode 100644 index 5b48c00..0000000 --- a/Crypto/Internal/Hex.hs +++ /dev/null @@ -1,119 +0,0 @@ --- | --- Module : Crypto.Internal.Hex --- License : BSD-style --- Maintainer : Vincent Hanquez --- Stability : experimental --- Portability : unknown --- --- Hexadecimal escaper --- -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE UnboxedTuples #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE BangPatterns #-} -{-# LANGUAGE Rank2Types #-} -module Crypto.Internal.Hex - ( showHexadecimal - , toHexadecimal - , toHexadecimal4 - ) where - -import Crypto.Internal.Compat -import Crypto.Internal.CompatPrim -import Data.Word -import GHC.Prim -import GHC.Types -import GHC.Word -import Control.Monad -import Foreign.Storable -import Foreign.Ptr (Ptr, plusPtr) - -showHexadecimal :: (forall a . (Ptr Word8 -> IO a) -> IO a) -> Int -> String -showHexadecimal withPtr = doChunks 0 - where - doChunks ofs len - | len < 4 = doUnique ofs len - | otherwise = do - let !(W8# a, W8# b, W8# c, W8# d) = unsafeDoIO $ withPtr (read4 ofs) - !(# w1, w2 #) = convertByte a - !(# w3, w4 #) = convertByte b - !(# w5, w6 #) = convertByte c - !(# w7, w8 #) = convertByte d - in wToChar w1 : wToChar w2 : wToChar w3 : wToChar w4 - : wToChar w5 : wToChar w6 : wToChar w7 : wToChar w8 - : doChunks (ofs + 4) (len - 4) - - doUnique ofs len - | len == 0 = [] - | otherwise = - let !(W8# b) = unsafeDoIO $ withPtr (byteIndex ofs) - !(# w1, w2 #) = convertByte b - in wToChar w1 : wToChar w2 : doUnique (ofs + 1) (len - 1) - - read4 :: Int -> Ptr Word8 -> IO (Word8, Word8, Word8, Word8) - read4 ofs p = - liftM4 (,,,) (byteIndex ofs p) (byteIndex (ofs+1) p) - (byteIndex (ofs+2) p) (byteIndex (ofs+3) p) - - wToChar :: Word# -> Char - wToChar w = toEnum (I# (word2Int# w)) - - byteIndex :: Int -> Ptr Word8 -> IO Word8 - byteIndex i p = peekByteOff p i - -toHexadecimal :: Ptr Word8 -> Ptr Word8 -> Int -> IO () -toHexadecimal bout bin n = loop 0 - where loop i - | i == n = return () - | otherwise = do - (W8# w) <- peekByteOff bin i - let (# w1, w2 #) = convertByte w - pokeByteOff bout (i * 2) (W8# w1) - pokeByteOff bout (i * 2 + 1) (W8# w2) - loop (i+1) - --- | convert to hexadecimal going 2 by 2 --- --- experimental. untested -toHexadecimal4 :: Ptr Word32 -> Ptr Word8 -> Int -> IO () -toHexadecimal4 bout bin n = loop 0 - where loop i - | i == n = return () - | otherwise = do - (W8# w1) <- peekByteOff bin i - (W8# w2) <- peekByteOff bin (i+1) - let r = W32# (convertByte4 w1 w2) - poke (bout `plusPtr` (i * 2)) r - loop (i+2) - -convertByte4 :: Word# -> Word# -> Word# -convertByte4 a b = convert4To32 b2 b1 a2 a1 - where - !(# a1, a2 #) = convertByte a - !(# b1, b2 #) = convertByte b - -convertByte :: Word# -> (# Word#, Word# #) -convertByte b = (# r tableHi b, r tableLo b #) - where - r :: Addr# -> Word# -> Word# - r table index = indexWord8OffAddr# table (word2Int# index) - - !tableLo = - "0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef\ - \0123456789abcdef0123456789abcdef"# - !tableHi = - "00000000000000001111111111111111\ - \22222222222222223333333333333333\ - \44444444444444445555555555555555\ - \66666666666666667777777777777777\ - \88888888888888889999999999999999\ - \aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb\ - \ccccccccccccccccdddddddddddddddd\ - \eeeeeeeeeeeeeeeeffffffffffffffff"# -{-# INLINE convertByte #-} diff --git a/Crypto/Internal/WordArray.hs b/Crypto/Internal/WordArray.hs index a8044e4..7bb15ad 100644 --- a/Crypto/Internal/WordArray.hs +++ b/Crypto/Internal/WordArray.hs @@ -40,17 +40,23 @@ import GHC.Prim import GHC.Types import GHC.Word +-- | Array of Word8 data Array8 = Array8 Addr# +-- | Array of Word32 data Array32 = Array32 ByteArray# +-- | Array of Word64 data Array64 = Array64 ByteArray# +-- | Array of mutable Word32 data MutableArray32 = MutableArray32 (MutableByteArray# RealWorld) +-- | Create an array of Word8 aliasing an Addr# array8 :: Addr# -> Array8 array8 = Array8 +-- | Create an Array of Word32 of specific size from a list of Word32 array32 :: Int -> [Word32] -> Array32 array32 (I# n) l = unsafeDoIO $ IO $ \s -> case newAlignedPinnedByteArray# (n *# 4#) 4# s of @@ -67,6 +73,7 @@ array32 (I# n) l = unsafeDoIO $ IO $ \s -> (# st', b #) -> (# st', Array32 b #) {-# NOINLINE array32 #-} +-- | Create an Array of Word64 of specific size from a list of Word64 array64 :: Int -> [Word64] -> Array64 array64 (I# n) l = unsafeDoIO $ IO $ \s -> case newAlignedPinnedByteArray# (n *# 8#) 8# s of @@ -83,6 +90,7 @@ array64 (I# n) l = unsafeDoIO $ IO $ \s -> (# st', b #) -> (# st', Array64 b #) {-# NOINLINE array64 #-} +-- | Create a Mutable Array of Word32 of specific size from a list of Word32 mutableArray32 :: Int -> [Word32] -> IO MutableArray32 mutableArray32 (I# n) l = IO $ \s -> case newAlignedPinnedByteArray# (n *# 4#) 4# s of @@ -95,6 +103,7 @@ mutableArray32 (I# n) l = IO $ \s -> let !st' = writeWord32Array# mb i x st in loop (i +# 1#) st' mb xs +-- | Create a Mutable Array of BE Word32 aliasing an Addr mutableArray32FromAddrBE :: Int -> Addr# -> IO MutableArray32 mutableArray32FromAddrBE (I# n) a = IO $ \s -> case newAlignedPinnedByteArray# (n *# 4#) 4# s of @@ -106,31 +115,40 @@ mutableArray32FromAddrBE (I# n) a = IO $ \s -> let !st' = writeWord32Array# mb i (be32Prim (indexWord32OffAddr# a i)) st in loop (i +# 1#) st' mb +-- | freeze a Mutable Array of Word32 into a immutable Array of Word32 mutableArray32Freeze :: MutableArray32 -> IO Array32 mutableArray32Freeze (MutableArray32 mb) = IO $ \st -> case unsafeFreezeByteArray# mb st of (# st', b #) -> (# st', Array32 b #) +-- | Read a Word8 from an Array arrayRead8 :: Array8 -> Int -> Word8 arrayRead8 (Array8 a) (I# o) = W8# (indexWord8OffAddr# a o) {-# INLINE arrayRead8 #-} +-- | Read a Word32 from an Array arrayRead32 :: Array32 -> Int -> Word32 arrayRead32 (Array32 b) (I# o) = W32# (indexWord32Array# b o) {-# INLINE arrayRead32 #-} +-- | Read a Word64 from an Array arrayRead64 :: Array64 -> Int -> Word64 arrayRead64 (Array64 b) (I# o) = W64# (indexWord64Array# b o) {-# INLINE arrayRead64 #-} +-- | Read a Word32 from a Mutable Array of Word32 mutableArrayRead32 :: MutableArray32 -> Int -> IO Word32 mutableArrayRead32 (MutableArray32 m) (I# o) = IO $ \s -> case readWord32Array# m o s of (# s', e #) -> (# s', W32# e #) {-# INLINE mutableArrayRead32 #-} +-- | Write a Word32 from a Mutable Array of Word32 mutableArrayWrite32 :: MutableArray32 -> Int -> Word32 -> IO () mutableArrayWrite32 (MutableArray32 m) (I# o) (W32# w) = IO $ \s -> let !s' = writeWord32Array# m o w s in (# s', () #) {-# INLINE mutableArrayWrite32 #-} +-- | Write into the Mutable Array of Word32 by combining through xor the current value and the new value. +-- +-- > x[i] = x[i] xor value mutableArrayWriteXor32 :: MutableArray32 -> Int -> Word32 -> IO () mutableArrayWriteXor32 m o w = mutableArrayRead32 m o >>= \wOld -> mutableArrayWrite32 m o (wOld `xor` w) diff --git a/Crypto/Internal/Words.hs b/Crypto/Internal/Words.hs index 363aad0..43f391b 100644 --- a/Crypto/Internal/Words.hs +++ b/Crypto/Internal/Words.hs @@ -17,8 +17,10 @@ import Data.Word import Data.Bits import Data.Memory.ExtendedWords +-- | Split a 'Word64' into the highest and lowest 'Word32' w64to32 :: Word64 -> (Word32, Word32) w64to32 w = (fromIntegral (w `shiftR` 32), fromIntegral w) +-- | Reconstruct a 'Word64' from two 'Word32' w32to64 :: (Word32, Word32) -> Word64 w32to64 (x1, x2) = ((fromIntegral x1) `shiftL` 32) .|. (fromIntegral x2) diff --git a/Crypto/Number/Basic.hs b/Crypto/Number/Basic.hs index 02c0f21..a49c6d9 100644 --- a/Crypto/Number/Basic.hs +++ b/Crypto/Number/Basic.hs @@ -65,6 +65,7 @@ gcde a b = onGmpUnsupported (gmpGcde a b) $ areEven :: [Integer] -> Bool areEven = and . map even +-- | Compute the binary logarithm of a integer log2 :: Integer -> Int log2 n = onGmpUnsupported (gmpLog2 n) $ imLog 2 n where diff --git a/Crypto/Number/Compat.hs b/Crypto/Number/Compat.hs index aa7c03f..33c879b 100644 --- a/Crypto/Number/Compat.hs +++ b/Crypto/Number/Compat.hs @@ -36,14 +36,17 @@ import GHC.Integer.Logarithms (integerLog2#) import Data.Word import GHC.Ptr (Ptr(..)) +-- | GMP Supported / Unsupported data GmpSupported a = GmpSupported a | GmpUnsupported deriving (Show,Eq) +-- | Simple combinator in case the operation is not supported through GMP onGmpUnsupported :: GmpSupported a -> a -> a onGmpUnsupported (GmpSupported a) _ = a onGmpUnsupported GmpUnsupported f = f +-- | Compute the GCDE of a two integer through GMP gmpGcde :: Integer -> Integer -> GmpSupported (Integer, Integer, Integer) #if MIN_VERSION_integer_gmp(0,5,1) gmpGcde a b = @@ -54,6 +57,7 @@ gmpGcde a b = gmpGcde _ _ = GmpUnsupported #endif +-- | Compute the binary logarithm of an integer through GMP gmpLog2 :: Integer -> GmpSupported Int #if MIN_VERSION_integer_gmp(0,5,1) gmpLog2 0 = GmpSupported 0 @@ -62,6 +66,8 @@ gmpLog2 x = GmpSupported (I# (integerLog2# x)) gmpLog2 _ = GmpUnsupported #endif +-- | Compute the power modulus using extra security to remain constant +-- time wise through GMP gmpPowModSecInteger :: Integer -> Integer -> Integer -> GmpSupported Integer #if MIN_VERSION_integer_gmp(1,0,0) gmpPowModSecInteger b e m = GmpUnsupported @@ -71,6 +77,7 @@ gmpPowModSecInteger b e m = GmpSupported (powModSecInteger b e m) gmpPowModSecInteger _ _ _ = GmpUnsupported #endif +-- | Compute the power modulus through GMP gmpPowModInteger :: Integer -> Integer -> Integer -> GmpSupported Integer #if MIN_VERSION_integer_gmp(0,5,1) gmpPowModInteger b e m = GmpSupported (powModInteger b e m) @@ -78,6 +85,7 @@ gmpPowModInteger b e m = GmpSupported (powModInteger b e m) gmpPowModInteger _ _ _ = GmpUnsupported #endif +-- | Inverse modulus of a number through GMP gmpInverse :: Integer -> Integer -> GmpSupported (Maybe Integer) #if MIN_VERSION_integer_gmp(0,5,1) gmpInverse g m @@ -88,6 +96,7 @@ gmpInverse g m gmpInverse _ _ = GmpUnsupported #endif +-- | Get the next prime from a specific value through GMP gmpNextPrime :: Integer -> GmpSupported Integer #if MIN_VERSION_integer_gmp(0,5,1) gmpNextPrime n = GmpSupported (nextPrimeInteger n) @@ -95,6 +104,7 @@ gmpNextPrime n = GmpSupported (nextPrimeInteger n) gmpNextPrime _ = GmpUnsupported #endif +-- | Test if a number is prime using Miller Rabin gmpTestPrimeMillerRabin :: Int -> Integer -> GmpSupported Bool #if MIN_VERSION_integer_gmp(0,5,1) gmpTestPrimeMillerRabin (I# tries) !n = GmpSupported $ @@ -105,6 +115,7 @@ gmpTestPrimeMillerRabin (I# tries) !n = GmpSupported $ gmpTestPrimeMillerRabin _ _ = GmpUnsupported #endif +-- | Return the size in bytes of a integer gmpSizeInBytes :: Integer -> GmpSupported Int #if MIN_VERSION_integer_gmp(0,5,1) gmpSizeInBytes n = GmpSupported (I# (word2Int# (sizeInBaseInteger n 256#))) @@ -112,6 +123,7 @@ gmpSizeInBytes n = GmpSupported (I# (word2Int# (sizeInBaseInteger n 256#))) gmpSizeInBytes _ = GmpUnsupported #endif +-- | Export an integer to a memory gmpExportInteger :: Integer -> Ptr Word8 -> GmpSupported (IO ()) #if MIN_VERSION_integer_gmp(1,0,0) gmpExportInteger n (Ptr addr) = GmpSupported $ do @@ -125,6 +137,7 @@ gmpExportInteger n (Ptr addr) = GmpSupported $ IO $ \s -> gmpExportInteger _ _ = GmpUnsupported #endif +-- | Import an integer from a memory gmpImportInteger :: Int -> Ptr Word8 -> GmpSupported (IO Integer) #if MIN_VERSION_integer_gmp(1,0,0) gmpImportInteger (I# n) (Ptr addr) = GmpSupported $ diff --git a/Crypto/Number/F2m.hs b/Crypto/Number/F2m.hs index 25a2338..8c68d11 100644 --- a/Crypto/Number/F2m.hs +++ b/Crypto/Number/F2m.hs @@ -22,6 +22,7 @@ import Data.Bits ((.&.),(.|.),xor,shift,testBit) import Crypto.Number.Basic import Crypto.Internal.Imports +-- | Binary Polynomial represented by an integer type BinaryPolynomial = Integer -- | Addition over F₂m. This is just a synonym of 'xor'. diff --git a/Crypto/PubKey/ECC/DH.hs b/Crypto/PubKey/ECC/DH.hs index c2b7fd4..fbe3cbe 100644 --- a/Crypto/PubKey/ECC/DH.hs +++ b/Crypto/PubKey/ECC/DH.hs @@ -1,12 +1,22 @@ -module Crypto.PubKey.ECC.DH ( - Curve - , PublicPoint - , PrivateNumber - , SharedKey(..) - , generatePrivate - , calculatePublic - , getShared - ) where +-- | +-- Module : Crypto.PubKey.ECC.DH +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : experimental +-- Portability : unknown +-- +-- Elliptic curve Diffie Hellman +-- +module Crypto.PubKey.ECC.DH + ( + Curve + , PublicPoint + , PrivateNumber + , SharedKey(..) + , generatePrivate + , calculatePublic + , getShared + ) where import Crypto.Number.Generate (generateMax) import Crypto.PubKey.ECC.Prim (pointMul) diff --git a/Crypto/Random.hs b/Crypto/Random.hs index 6d67d85..5092899 100644 --- a/Crypto/Random.hs +++ b/Crypto/Random.hs @@ -1,3 +1,4 @@ +-- | -- Module : Crypto.Random -- License : BSD-style -- Maintainer : Vincent Hanquez @@ -23,8 +24,16 @@ import Crypto.Random.Entropy import Data.ByteArray (ScrubbedBytes) import Crypto.Internal.Imports +-- | Create a new DRG from system entropy drgNew :: IO ChaChaDRG drgNew = initialize <$> (getEntropy 40 :: IO ScrubbedBytes) +-- | Create a new DRG from 5 Word64. +-- +-- This is a convenient interface to create deterministic interface +-- for quickcheck style testing. +-- +-- It can also be used in other contexts provided the input +-- has been properly randomly generated. drgNewTest :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG drgNewTest = initializeWords diff --git a/Crypto/Random/Entropy/Backend.hs b/Crypto/Random/Entropy/Backend.hs index 08b5691..8ff03e7 100644 --- a/Crypto/Random/Entropy/Backend.hs +++ b/Crypto/Random/Entropy/Backend.hs @@ -1,3 +1,10 @@ +-- | +-- Module : Crypto.Random.Entropy.Backend +-- License : BSD-style +-- Maintainer : Vincent Hanquez +-- Stability : stable +-- Portability : good +-- {-# LANGUAGE CPP #-} {-# LANGUAGE ExistentialQuantification #-} module Crypto.Random.Entropy.Backend @@ -18,6 +25,7 @@ import Crypto.Random.Entropy.Windows import Crypto.Random.Entropy.Unix #endif +-- | All supported backends supportedBackends :: [IO (Maybe EntropyBackend)] supportedBackends = [ @@ -31,12 +39,18 @@ supportedBackends = #endif ] +-- | Any Entropy Backend data EntropyBackend = forall b . EntropySource b => EntropyBackend b +-- | Open a backend handle openBackend :: EntropySource b => b -> IO (Maybe EntropyBackend) openBackend b = fmap EntropyBackend `fmap` callOpen b where callOpen :: EntropySource b => b -> IO (Maybe b) callOpen _ = entropyOpen -gatherBackend :: EntropyBackend -> Ptr Word8 -> Int -> IO Int +-- | Gather randomness from an open handle +gatherBackend :: EntropyBackend -- ^ An open Entropy Backend + -> Ptr Word8 -- ^ Pointer to a buffer to write to + -> Int -- ^ number of bytes to write + -> IO Int -- ^ return the number of bytes actually written gatherBackend (EntropyBackend backend) ptr n = entropyGather backend ptr n diff --git a/Crypto/Random/Entropy/Unsafe.hs b/Crypto/Random/Entropy/Unsafe.hs index 3690b2c..5770dc0 100644 --- a/Crypto/Random/Entropy/Unsafe.hs +++ b/Crypto/Random/Entropy/Unsafe.hs @@ -14,7 +14,13 @@ import Data.Word (Word8) import Foreign.Ptr (Ptr, plusPtr) import Crypto.Random.Entropy.Backend --- Refill the entropy in a buffer +-- | Refill the entropy in a buffer +-- +-- call each entropy backend in turn until the buffer has +-- been replenish. +-- +-- If the buffer cannot be refill after 3 loopings, this will raise +-- an User Error exception replenish :: Int -> [EntropyBackend] -> Ptr Word8 -> IO () replenish _ [] _ = fail "cryptonite: random: cannot get any source of entropy on this system" replenish poolSize backends ptr = loop 0 backends ptr poolSize diff --git a/Crypto/Random/Types.hs b/Crypto/Random/Types.hs index d93161e..8bcee6f 100644 --- a/Crypto/Random/Types.hs +++ b/Crypto/Random/Types.hs @@ -8,6 +8,7 @@ module Crypto.Random.Types ( MonadRandom(..) + , MonadPseudoRandom , DRG(..) , withDRG ) where @@ -16,15 +17,20 @@ import Crypto.Random.Entropy import Crypto.Internal.ByteArray import Crypto.Internal.Imports +-- | A monad constraint that allows to generate random bytes class (Functor m, Monad m) => MonadRandom m where getRandomBytes :: ByteArray byteArray => Int -> m byteArray +-- | A Deterministic Random Generator (DRG) class class DRG gen where + -- | Generate N bytes of randomness from a DRG randomBytesGenerate :: ByteArray byteArray => Int -> gen -> (byteArray, gen) instance MonadRandom IO where getRandomBytes = getEntropy +-- | A simple Monad class very similar to a State Monad +-- with the state being a DRG. newtype MonadPseudoRandom gen a = MonadPseudoRandom { runPseudoRandom :: gen -> (a, gen) } @@ -49,5 +55,7 @@ instance DRG gen => Monad (MonadPseudoRandom gen) where instance DRG gen => MonadRandom (MonadPseudoRandom gen) where getRandomBytes n = MonadPseudoRandom (randomBytesGenerate n) +-- | Run a pure computation with a Deterministic Random Generator +-- in the 'MonadPseudoRandom' withDRG :: DRG gen => gen -> MonadPseudoRandom gen a -> (a, gen) withDRG gen m = runPseudoRandom m gen diff --git a/cryptonite.cabal b/cryptonite.cabal index 7454564..9901670 100644 --- a/cryptonite.cabal +++ b/cryptonite.cabal @@ -126,7 +126,6 @@ Library Crypto.Internal.ByteArray Crypto.Internal.Compat Crypto.Internal.CompatPrim - Crypto.Internal.Hex Crypto.Internal.Imports Crypto.Internal.Words Crypto.Internal.WordArray