crypton 0.33 → 0.34
raw patch · 23 files changed
+1004/−446 lines, 23 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Crypto.Cipher.ChaCha: initializeX :: (ByteArrayAccess key, ByteArrayAccess nonce) => Int -> key -> nonce -> State
+ Crypto.Cipher.ChaChaPoly1305: data XNonce
+ Crypto.Cipher.ChaChaPoly1305: initializeX :: ByteArrayAccess key => key -> XNonce -> CryptoFailable State
+ Crypto.Cipher.ChaChaPoly1305: instance Data.ByteArray.Types.ByteArrayAccess Crypto.Cipher.ChaChaPoly1305.XNonce
+ Crypto.Cipher.ChaChaPoly1305: nonce24 :: ByteArrayAccess ba => ba -> CryptoFailable XNonce
+ Crypto.MAC.KeyedBlake2: KeyedBlake2 :: Digest a -> KeyedBlake2 a
+ Crypto.MAC.KeyedBlake2: [keyedBlake2GetDigest] :: KeyedBlake2 a -> Digest a
+ Crypto.MAC.KeyedBlake2: class HashAlgorithm a => HashBlake2 a
+ Crypto.MAC.KeyedBlake2: data Context a
+ Crypto.MAC.KeyedBlake2: finalize :: HashBlake2 a => Context a -> KeyedBlake2 a
+ Crypto.MAC.KeyedBlake2: initialize :: forall a key. (HashBlake2 a, ByteArrayAccess key) => key -> Context a
+ Crypto.MAC.KeyedBlake2: instance Control.DeepSeq.NFData (Crypto.MAC.KeyedBlake2.KeyedBlake2 a)
+ Crypto.MAC.KeyedBlake2: instance Data.ByteArray.Types.ByteArrayAccess (Crypto.MAC.KeyedBlake2.KeyedBlake2 a)
+ Crypto.MAC.KeyedBlake2: instance GHC.Classes.Eq (Crypto.MAC.KeyedBlake2.KeyedBlake2 a)
+ Crypto.MAC.KeyedBlake2: keyedBlake2 :: (HashBlake2 a, ByteArrayAccess key, ByteArrayAccess ba) => key -> ba -> KeyedBlake2 a
+ Crypto.MAC.KeyedBlake2: keyedBlake2Lazy :: (HashBlake2 a, ByteArrayAccess key) => key -> ByteString -> KeyedBlake2 a
+ Crypto.MAC.KeyedBlake2: newtype KeyedBlake2 a
+ Crypto.MAC.KeyedBlake2: update :: (HashBlake2 a, ByteArrayAccess ba) => Context a -> ba -> Context a
+ Crypto.MAC.KeyedBlake2: updates :: (HashBlake2 a, ByteArrayAccess ba) => Context a -> [ba] -> Context a
Files
- CHANGELOG.md +9/−0
- Crypto/Cipher/ChaCha.hs +26/−0
- Crypto/Cipher/ChaChaPoly1305.hs +38/−2
- Crypto/Cipher/Types/Block.hs +1/−1
- Crypto/Hash/Blake2.hs +40/−1
- Crypto/MAC/KeyedBlake2.hs +88/−0
- Crypto/Random.hs +8/−1
- README.md +0/−4
- cbits/crypton_blake2b.c +5/−0
- cbits/crypton_blake2b.h +1/−0
- cbits/crypton_blake2bp.c +5/−0
- cbits/crypton_blake2bp.h +1/−0
- cbits/crypton_blake2s.c +5/−0
- cbits/crypton_blake2s.h +1/−0
- cbits/crypton_blake2sp.c +5/−0
- cbits/crypton_blake2sp.h +1/−0
- cbits/crypton_chacha.c +91/−4
- cbits/crypton_chacha.h +1/−0
- crypton.cabal +474/−432
- tests/ChaCha.hs +13/−0
- tests/ChaChaPoly1305.hs +23/−1
- tests/KAT_Blake2.hs +166/−0
- tests/Tests.hs +2/−0
CHANGELOG.md view
@@ -1,3 +1,12 @@+## 0.34++* Hashing getRandomBytes before using as Seed for ChaChaDRG+ [#24](https://github.com/kazu-yamamoto/crypton/pull/24)+* Add support for XChaCha and XChaChaPoly1305+ [#18](https://github.com/kazu-yamamoto/crypton/pull/18)+* Strict byteArray of IV c+ [#16](https://github.com/kazu-yamamoto/crypton/pull/16)+ ## 0.33 * Add "crypton_" prefix to the final C symbols.
Crypto/Cipher/ChaCha.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Crypto.Cipher.ChaCha ( initialize+ , initializeX , combine , generate , State@@ -53,6 +54,28 @@ where kLen = B.length key nonceLen = B.length nonce +-- | Initialize a new XChaCha context with the number of rounds,+-- the key and the nonce associated.+--+-- An XChaCha state can be used like a regular ChaCha state after initialisation.+initializeX :: (ByteArrayAccess key, ByteArrayAccess nonce)+ => Int -- ^ number of rounds (8,12,20)+ -> key -- ^ the key (256 bits)+ -> nonce -- ^ the nonce (192 bits)+ -> State -- ^ the initial ChaCha state+initializeX nbRounds key nonce+ | kLen /= 32 = error "XChaCha: key length should be 256 bits"+ | nonceLen /= 24 = error "XChaCha: nonce length should be 192 bits"+ | nbRounds `notElem` [8,12,20] = error "XChaCha: rounds should be 8, 12 or 20"+ | otherwise = unsafeDoIO $ do+ stPtr <- B.alloc 132 $ \stPtr ->+ B.withByteArray nonce $ \noncePtr ->+ B.withByteArray key $ \keyPtr ->+ ccrypton_xchacha_init stPtr nbRounds keyPtr noncePtr+ return $ State stPtr+ where kLen = B.length key+ nonceLen = B.length nonce+ -- | Initialize simple ChaCha State -- -- The seed need to be at least 40 bytes long@@ -114,6 +137,9 @@ foreign import ccall "crypton_chacha_init" ccrypton_chacha_init :: Ptr State -> Int -> Int -> Ptr Word8 -> Int -> Ptr Word8 -> IO ()++foreign import ccall "crypton_xchacha_init"+ ccrypton_xchacha_init :: Ptr State -> Int -> Ptr Word8 -> Ptr Word8 -> IO () foreign import ccall "crypton_chacha_combine" ccrypton_chacha_combine :: Ptr Word8 -> Ptr State -> Ptr Word8 -> CUInt -> IO ()
Crypto/Cipher/ChaChaPoly1305.hs view
@@ -38,10 +38,13 @@ module Crypto.Cipher.ChaChaPoly1305 ( State , Nonce+ , XNonce , nonce12 , nonce8+ , nonce24 , incrementNonce , initialize+ , initializeX , appendAAD , finalizeAAD , encrypt@@ -81,6 +84,14 @@ withByteArray (Nonce8 n) = B.withByteArray n withByteArray (Nonce12 n) = B.withByteArray n +-- | Extended nonce for XChaChaPoly1305.+newtype XNonce = Nonce24 Bytes++instance ByteArrayAccess XNonce where+ length (Nonce24 n) = B.length n+ withByteArray (Nonce24 n) = B.withByteArray n++ -- Based on the following pseudo code: -- -- chacha20_aead_encrypt(aad, key, iv, constant, plaintext):@@ -117,6 +128,13 @@ | B.length iv /= 8 = CryptoFailed CryptoError_IvSizeInvalid | otherwise = CryptoPassed . Nonce8 . B.concat $ [constant, iv] +-- | 24 bytes IV, extended nonce constructor+nonce24 :: ByteArrayAccess ba+ => ba -> CryptoFailable XNonce+nonce24 iv+ | B.length iv /= 24 = CryptoFailed CryptoError_IvSizeInvalid+ | otherwise = CryptoPassed . Nonce24 . B.convert $ iv+ -- | Increment a nonce incrementNonce :: Nonce -> Nonce incrementNonce (Nonce8 n) = Nonce8 $ incrementNonce' n 4@@ -143,15 +161,33 @@ initialize key (Nonce8 nonce) = initialize' key nonce initialize key (Nonce12 nonce) = initialize' key nonce + initialize' :: ByteArrayAccess key => key -> Bytes -> CryptoFailable State initialize' key nonce | B.length key /= 32 = CryptoFailed CryptoError_KeySizeInvalid- | otherwise = CryptoPassed $ State encState polyState 0 0+ | otherwise = CryptoPassed $ initFromRootState rootState+ where rootState = ChaCha.initialize 20 key nonce+++initFromRootState :: ChaCha.State -> State+initFromRootState rootState = State encState polyState 0 0 where- rootState = ChaCha.initialize 20 key nonce (polyKey, encState) = ChaCha.generate rootState 64 polyState = throwCryptoError $ Poly1305.initialize (B.take 32 polyKey :: ScrubbedBytes)+++-- | Initialize a new XChaChaPoly1305 State+--+-- The key length needs to be 256 bits, and the nonce+-- procured using `nonce24`.+initializeX :: ByteArrayAccess key+ => key -> XNonce -> CryptoFailable State+initializeX key (Nonce24 nonce)+ | B.length key /= 32 = CryptoFailed CryptoError_KeySizeInvalid+ | otherwise = CryptoPassed $ initFromRootState rootState+ where rootState = ChaCha.initializeX 20 key nonce+ -- | Append Authenticated Data to the State and return -- the new modified State.
Crypto/Cipher/Types/Block.hs view
@@ -50,7 +50,7 @@ import Foreign.Storable -- | an IV parametrized by the cipher-data IV c = forall byteArray . ByteArray byteArray => IV byteArray+data IV c = forall byteArray . ByteArray byteArray => IV !byteArray instance BlockCipher c => ByteArrayAccess (IV c) where withByteArray (IV z) f = withByteArray z f
Crypto/Hash/Blake2.hs view
@@ -33,7 +33,8 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeFamilies #-} module Crypto.Hash.Blake2- ( Blake2s(..)+ ( HashBlake2(..)+ , Blake2s(..) , Blake2sp(..) , Blake2b(..) , Blake2bp(..)@@ -46,6 +47,13 @@ import GHC.TypeLits (Nat, KnownNat) import Crypto.Internal.Nat +-- | Typeclass for the Blake2 family of digest functions.+class HashAlgorithm a => HashBlake2 a where++ -- | Init Blake2 algorithm with the specified key of the specified length.+ -- The key length is specified in bytes.+ blake2InternalKeyedInit :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO ()+ -- | Fast and secure alternative to SHA1 and HMAC-SHA1 -- -- It is espacially known to target 32bits architectures.@@ -72,8 +80,16 @@ hashInternalUpdate = c_blake2s_update hashInternalFinalize p = c_blake2s_finalize p (integralNatVal (Proxy :: Proxy bitlen)) +instance (IsDivisibleBy8 bitlen, KnownNat bitlen, IsAtLeast bitlen 8, IsAtMost bitlen 256)+ => HashBlake2 (Blake2s bitlen)+ where+ blake2InternalKeyedInit p = c_blake2s_init_key p outLen+ where outLen = integralNatVal (Proxy :: Proxy bitlen)+ foreign import ccall unsafe "crypton_blake2s_init" c_blake2s_init :: Ptr (Context a) -> Word32 -> IO ()+foreign import ccall unsafe "crypton_blake2s_init_key"+ c_blake2s_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO () foreign import ccall "crypton_blake2s_update" c_blake2s_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO () foreign import ccall unsafe "crypton_blake2s_finalize"@@ -107,8 +123,16 @@ hashInternalUpdate = c_blake2b_update hashInternalFinalize p = c_blake2b_finalize p (integralNatVal (Proxy :: Proxy bitlen)) +instance (IsDivisibleBy8 bitlen, KnownNat bitlen, IsAtLeast bitlen 8, IsAtMost bitlen 512)+ => HashBlake2 (Blake2b bitlen)+ where+ blake2InternalKeyedInit p = c_blake2b_init_key p outLen+ where outLen = integralNatVal (Proxy :: Proxy bitlen)+ foreign import ccall unsafe "crypton_blake2b_init" c_blake2b_init :: Ptr (Context a) -> Word32 -> IO ()+foreign import ccall unsafe "crypton_blake2b_init_key"+ c_blake2b_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO () foreign import ccall "crypton_blake2b_update" c_blake2b_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO () foreign import ccall unsafe "crypton_blake2b_finalize"@@ -130,8 +154,16 @@ hashInternalUpdate = c_blake2sp_update hashInternalFinalize p = c_blake2sp_finalize p (integralNatVal (Proxy :: Proxy bitlen)) +instance (IsDivisibleBy8 bitlen, KnownNat bitlen, IsAtLeast bitlen 8, IsAtMost bitlen 256)+ => HashBlake2 (Blake2sp bitlen)+ where+ blake2InternalKeyedInit p = c_blake2sp_init_key p outLen+ where outLen = integralNatVal (Proxy :: Proxy bitlen)+ foreign import ccall unsafe "crypton_blake2sp_init" c_blake2sp_init :: Ptr (Context a) -> Word32 -> IO ()+foreign import ccall unsafe "crypton_blake2sp_init_key"+ c_blake2sp_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO () foreign import ccall "crypton_blake2sp_update" c_blake2sp_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO () foreign import ccall unsafe "crypton_blake2sp_finalize"@@ -153,9 +185,16 @@ hashInternalUpdate = c_blake2bp_update hashInternalFinalize p = c_blake2bp_finalize p (integralNatVal (Proxy :: Proxy bitlen)) +instance (IsDivisibleBy8 bitlen, KnownNat bitlen, IsAtLeast bitlen 8, IsAtMost bitlen 512)+ => HashBlake2 (Blake2bp bitlen)+ where+ blake2InternalKeyedInit p = c_blake2bp_init_key p outLen+ where outLen = integralNatVal (Proxy :: Proxy bitlen) foreign import ccall unsafe "crypton_blake2bp_init" c_blake2bp_init :: Ptr (Context a) -> Word32 -> IO ()+foreign import ccall unsafe "crypton_blake2bp_init_key"+ c_blake2bp_init_key :: Ptr (Context a) -> Word32 -> Ptr Word8 -> Word32 -> IO () foreign import ccall "crypton_blake2bp_update" c_blake2bp_update :: Ptr (Context a) -> Ptr Word8 -> Word32 -> IO () foreign import ccall unsafe "crypton_blake2bp_finalize"
+ Crypto/MAC/KeyedBlake2.hs view
@@ -0,0 +1,88 @@+-- |+-- Module : Crypto.MAC.KeyedBlake2+-- License : BSD-style+-- Maintainer : Matthias Valvekens <dev@mvalvekens.be>+-- Stability : experimental+-- Portability : unknown+--+-- Expose a MAC interface to the keyed Blake2 algorithms+-- defined in RFC 7693.+--+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Crypto.MAC.KeyedBlake2+ ( HashBlake2+ , KeyedBlake2(..)+ , keyedBlake2+ , keyedBlake2Lazy+ -- * Incremental+ , Context+ , initialize+ , update+ , updates+ , finalize+ ) where++import qualified Crypto.Hash as H+import qualified Crypto.Hash.Types as H+import Crypto.Hash.Blake2+import Crypto.Internal.DeepSeq (NFData)+import qualified Data.ByteArray as B+import Data.ByteArray (ByteArrayAccess)+import qualified Data.ByteString.Lazy as L++import Foreign.Ptr (Ptr)+++-- Keyed Blake2b++-- | Represent a Blake2b MAC that is a phantom type with the hash used to produce the+-- MAC.+--+-- The Eq instance is constant time. No Show instance is provided, to avoid+-- printing by mistake.+newtype KeyedBlake2 a = KeyedBlake2 { keyedBlake2GetDigest :: H.Digest a }+ deriving (ByteArrayAccess,NFData)++instance Eq (KeyedBlake2 a) where+ KeyedBlake2 x == KeyedBlake2 y = B.constEq x y++-- | Represent an ongoing Blake2 state, that can be appended with 'update' and+-- finalized to a 'KeyedBlake2' with 'finalize'.+newtype Context a = Context (H.Context a)++-- | Initialize a new incremental keyed Blake2 context with the supplied key.+initialize :: forall a key . (HashBlake2 a, ByteArrayAccess key)+ => key -> Context a+initialize k = Context $ H.Context $ B.allocAndFreeze ctxSz performInit+ where ctxSz = H.hashInternalContextSize (undefined :: a)+ digestSz = H.hashDigestSize (undefined :: a)+ -- cap the number of key bytes at digestSz,+ -- since that's the maximal key size+ keyByteLen = min (B.length k) digestSz+ performInit :: Ptr (H.Context a) -> IO ()+ performInit ptr = B.withByteArray k+ $ \keyPtr -> blake2InternalKeyedInit ptr keyPtr (fromIntegral keyByteLen)++-- | Incrementally update a keyed Blake2 context.+update :: (HashBlake2 a, ByteArrayAccess ba) => Context a -> ba -> Context a+update (Context ctx) = Context . H.hashUpdate ctx++-- | Incrementally update a keyed Blake2 context with multiple inputs.+updates :: (HashBlake2 a, ByteArrayAccess ba) => Context a -> [ba] -> Context a+updates (Context ctx) = Context . H.hashUpdates ctx++-- | Finalize a keyed Blake2 context and return the computed MAC.+finalize :: HashBlake2 a => Context a -> KeyedBlake2 a+finalize (Context ctx) = KeyedBlake2 $ H.hashFinalize ctx++-- | Compute a Blake2 MAC using the supplied key.+keyedBlake2 :: (HashBlake2 a, ByteArrayAccess key, ByteArrayAccess ba)+ => key -> ba -> KeyedBlake2 a+keyedBlake2 key msg = finalize $ update (initialize key) msg++-- | Compute a Blake2 MAC using the supplied key, for a lazy input.+keyedBlake2Lazy :: (HashBlake2 a, ByteArrayAccess key)+ => key -> L.ByteString -> KeyedBlake2 a+keyedBlake2Lazy key msg = finalize $ updates (initialize key) (L.toChunks msg)
Crypto/Random.hs view
@@ -37,6 +37,7 @@ import Data.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes) import qualified Data.ByteArray as B import Crypto.Internal.Imports+import Crypto.Hash (Digest, SHA512, hash) import qualified Crypto.Number.Serialize as Serialize @@ -49,7 +50,13 @@ -- | Create a new Seed from system entropy seedNew :: MonadRandom randomly => randomly Seed-seedNew = Seed `fmap` getRandomBytes seedLength+-- The degree of its randomness depends on the source, e.g. for iOS we+-- have to compile with DoNotUseEntropy flag, as iOS doesn't allow+-- using getentropy, and on some other systems it can be also+-- potentially comprisable sources. Hashing of entropy before using+-- it as a seed is a common mitigation for attacks via RNG/entropy+-- source.+seedNew = (Seed . B.take seedLength . B.convert . (hash :: ScrubbedBytes -> Digest SHA512)) `fmap` getRandomBytes 64 -- | Convert a Seed to an integer seedToInteger :: Seed -> Integer
README.md view
@@ -29,10 +29,6 @@ Next version of `0.x` is `0.(x+1)`. There's no exceptions, or API related meaning behind the numbers. -Each versions of stackage (going back 3 stable LTS) has a crypton version-that we maintain with security fixes when necessary and are versioned with the-following `0.x.y` scheme.- Coding Style ------------
cbits/crypton_blake2b.c view
@@ -5,6 +5,11 @@ _crypton_blake2b_init(ctx, hashlen / 8); } +void crypton_blake2b_init_key(blake2b_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen)+{+ _crypton_blake2b_init_key(ctx, hashlen / 8, (const void *) key, keylen);+}+ void crypton_blake2b_update(blake2b_ctx *ctx, const uint8_t *data, uint32_t len) { _crypton_blake2b_update(ctx, data, len);
cbits/crypton_blake2b.h view
@@ -6,6 +6,7 @@ typedef blake2b_state blake2b_ctx; void crypton_blake2b_init(blake2b_ctx *ctx, uint32_t hashlen);+void crypton_blake2b_init_key(blake2b_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen); void crypton_blake2b_update(blake2b_ctx *ctx, const uint8_t *data, uint32_t len); void crypton_blake2b_finalize(blake2b_ctx *ctx, uint32_t hashlen, uint8_t *out);
cbits/crypton_blake2bp.c view
@@ -5,6 +5,11 @@ _crypton_blake2bp_init(ctx, hashlen / 8); } +void crypton_blake2bp_init_key(blake2bp_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen)+{+ _crypton_blake2bp_init_key(ctx, hashlen / 8, (const void *) key, keylen);+}+ void crypton_blake2bp_update(blake2bp_ctx *ctx, const uint8_t *data, uint32_t len) { _crypton_blake2bp_update(ctx, data, len);
cbits/crypton_blake2bp.h view
@@ -6,6 +6,7 @@ typedef blake2bp_state blake2bp_ctx; void crypton_blake2bp_init(blake2bp_ctx *ctx, uint32_t hashlen);+void crypton_blake2bp_init_key(blake2bp_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen); void crypton_blake2bp_update(blake2bp_ctx *ctx, const uint8_t *data, uint32_t len); void crypton_blake2bp_finalize(blake2bp_ctx *ctx, uint32_t hashlen, uint8_t *out);
cbits/crypton_blake2s.c view
@@ -5,6 +5,11 @@ _crypton_blake2s_init(ctx, hashlen / 8); } +void crypton_blake2s_init_key(blake2s_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen)+{+ _crypton_blake2s_init_key(ctx, hashlen / 8, (const void *) key, keylen);+}+ void crypton_blake2s_update(blake2s_ctx *ctx, const uint8_t *data, uint32_t len) { _crypton_blake2s_update(ctx, data, len);
cbits/crypton_blake2s.h view
@@ -6,6 +6,7 @@ typedef blake2s_state blake2s_ctx; void crypton_blake2s_init(blake2s_ctx *ctx, uint32_t hashlen);+void crypton_blake2s_init_key(blake2s_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen); void crypton_blake2s_update(blake2s_ctx *ctx, const uint8_t *data, uint32_t len); void crypton_blake2s_finalize(blake2s_ctx *ctx, uint32_t hashlen, uint8_t *out);
cbits/crypton_blake2sp.c view
@@ -5,6 +5,11 @@ _crypton_blake2sp_init(ctx, hashlen / 8); } +void crypton_blake2sp_init_key(blake2sp_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen)+{+ _crypton_blake2sp_init_key(ctx, hashlen / 8, (const void *) key, keylen);+}+ void crypton_blake2sp_update(blake2sp_ctx *ctx, const uint8_t *data, uint32_t len) { _crypton_blake2sp_update(ctx, data, len);
cbits/crypton_blake2sp.h view
@@ -6,6 +6,7 @@ typedef blake2sp_state blake2sp_ctx; void crypton_blake2sp_init(blake2sp_ctx *ctx, uint32_t hashlen);+void crypton_blake2sp_init_key(blake2sp_ctx *ctx, uint32_t hashlen, const uint8_t *key, size_t keylen); void crypton_blake2sp_update(blake2sp_ctx *ctx, const uint8_t *data, uint32_t len); void crypton_blake2sp_finalize(blake2sp_ctx *ctx, uint32_t hashlen, uint8_t *out);
cbits/crypton_chacha.c view
@@ -92,11 +92,44 @@ out->d[15] = cpu_to_le32(x15); } -/* only 2 valids values are 256 (32) and 128 (16) */-void crypton_chacha_init_core(crypton_chacha_state *st,- uint32_t keylen, const uint8_t *key,- uint32_t ivlen, const uint8_t *iv)+static void hchacha_core(int rounds, uint32_t *out, const crypton_chacha_state *in) {+ uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;+ int i;++ x0 = in->d[0]; x1 = in->d[1]; x2 = in->d[2]; x3 = in->d[3];+ x4 = in->d[4]; x5 = in->d[5]; x6 = in->d[6]; x7 = in->d[7];+ x8 = in->d[8]; x9 = in->d[9]; x10 = in->d[10]; x11 = in->d[11];+ x12 = in->d[12]; x13 = in->d[13]; x14 = in->d[14]; x15 = in->d[15];++ for (i = rounds; i > 0; i -= 2) {+ QR(x0, x4, x8, x12);+ QR(x1, x5, x9, x13);+ QR(x2, x6, x10, x14);+ QR(x3, x7, x11, x15);++ QR(x0, x5, x10, x15);+ QR(x1, x6, x11, x12);+ QR(x2, x7, x8, x13);+ QR(x3, x4, x9, x14);+ }++ /* HChaCha doesn't perform the final addition */++ out[0] = cpu_to_le32(x0);+ out[1] = cpu_to_le32(x1);+ out[2] = cpu_to_le32(x2);+ out[3] = cpu_to_le32(x3);+ out[4] = cpu_to_le32(x12);+ out[5] = cpu_to_le32(x13);+ out[6] = cpu_to_le32(x14);+ out[7] = cpu_to_le32(x15);+}++/* Common initialization logic for ChaCha20 and HChaCha20 */+static void chacha_init_key_state(crypton_chacha_state *st,+ uint32_t keylen, const uint8_t *key)+{ const uint8_t *constants = (keylen == 32) ? sigma : tau; ASSERT_ALIGNMENT(constants, 4);@@ -117,6 +150,14 @@ st->d[9] = load_le32(key + 4); st->d[10] = load_le32(key + 8); st->d[11] = load_le32(key + 12);+}++/* only 2 valids values are 256 (32) and 128 (16) */+void crypton_chacha_init_core(crypton_chacha_state *st,+ uint32_t keylen, const uint8_t *key,+ uint32_t ivlen, const uint8_t *iv)+{+ chacha_init_key_state(st, keylen, key); st->d[12] = 0; switch (ivlen) { case 8:@@ -133,6 +174,19 @@ } } +void crypton_hchacha_init_core(crypton_chacha_state *st,+ const uint8_t *key,+ const uint8_t *iv)+{+ /* keylen is always 32 here */+ chacha_init_key_state(st, 32, key);+ /* fill the last 4 uint32s with the 128-bit nonce */+ st->d[12] = load_le32(iv + 0);+ st->d[13] = load_le32(iv + 4);+ st->d[14] = load_le32(iv + 8);+ st->d[15] = load_le32(iv + 12);+}+ void crypton_chacha_init(crypton_chacha_context *ctx, uint8_t nb_rounds, uint32_t keylen, const uint8_t *key, uint32_t ivlen, const uint8_t *iv)@@ -141,6 +195,39 @@ ctx->nb_rounds = nb_rounds; crypton_chacha_init_core(&ctx->st, keylen, key, ivlen, iv); }++void crypton_hchacha(uint8_t nb_rounds, const uint8_t *keyin, const uint8_t *iv,+ uint8_t *keyout)+{+ crypton_chacha_state st;++ crypton_hchacha_init_core(&st, keyin, iv);+ /* output to uint32_t* and do a memcpy to avoid+ violating the strict aliasing rule */+ uint32_t keyout32[8];+ hchacha_core(nb_rounds, keyout32, &st);+ memset(&st, 0, sizeof(st));+ memcpy(keyout, keyout32, 32);++ memset(keyout32, 0, 32);+}++/* XChaCha: 256-bit key, 192-bit nonce version of ChaCha.*/+void crypton_xchacha_init(crypton_chacha_context *ctx, uint8_t nb_rounds,+ const uint8_t *key, const uint8_t *iv)+{+ memset(ctx, 0, sizeof(*ctx));+ ctx->nb_rounds = nb_rounds;++ /* perform HChaCha with the key and the first 16 bytes of the nonce+ to get the subkey */+ uint8_t subkey[32];+ crypton_hchacha(nb_rounds, key, iv, subkey);+ /* perform regular ChaCha with the generated subkey and the last 8 bytes+ of the input IV */+ crypton_chacha_init_core(&ctx->st, 32, subkey, 8, iv + 16);+}+ void crypton_chacha_combine(uint8_t *dst, crypton_chacha_context *ctx, const uint8_t *src, uint32_t bytes) {
cbits/crypton_chacha.h view
@@ -48,6 +48,7 @@ void crypton_chacha_init_core(crypton_chacha_state *st, uint32_t keylen, const uint8_t *key, uint32_t ivlen, const uint8_t *iv); void crypton_chacha_init(crypton_chacha_context *ctx, uint8_t nb_rounds, uint32_t keylen, const uint8_t *key, uint32_t ivlen, const uint8_t *iv);+void crypton_xchacha_init(crypton_chacha_context *ctx, uint8_t nb_rounds, const uint8_t *key, const uint8_t *iv); void crypton_chacha_combine(uint8_t *dst, crypton_chacha_context *st, const uint8_t *src, uint32_t bytes); void crypton_chacha_generate(uint8_t *dst, crypton_chacha_context *st, uint32_t bytes);
crypton.cabal view
@@ -1,7 +1,17 @@-Name: crypton-version: 0.33-Synopsis: Cryptography Primitives sink-Description:+cabal-version: 1.18+name: crypton+version: 0.34+license: BSD3+license-file: LICENSE+copyright: Vincent Hanquez <vincent@snarc.org>+maintainer: Kazu Yamamoto <kazu@iij.ad.jp>+author: Vincent Hanquez <vincent@snarc.org>+stability: experimental+tested-with: ghc ==9.2.2 ghc ==9.0.2 ghc ==8.10.7 ghc ==8.8.4+homepage: https://github.com/kazu-yamamoto/crypton+bug-reports: https://github.com/kazu-yamamoto/crypton/issues+synopsis: Cryptography Primitives sink+description: A repository of cryptographic primitives. . * Symmetric ciphers: AES, DES, 3DES, CAST5, Blowfish, Twofish, Camellia, RC4, Salsa, XSalsa, ChaCha.@@ -25,463 +35,495 @@ Evaluate the security related to your requirements before using. . Read "Crypto.Tutorial" for a quick start guide.-License: BSD3-License-file: LICENSE-Copyright: Vincent Hanquez <vincent@snarc.org>-Author: Vincent Hanquez <vincent@snarc.org>-Maintainer: Kazu Yamamoto <kazu@iij.ad.jp>-Category: Cryptography-Stability: experimental-Build-Type: Simple-Homepage: https://github.com/kazu-yamamoto/crypton-Bug-reports: https://github.com/kazu-yamamoto/crypton/issues-Cabal-Version: 1.18-tested-with: GHC==9.2.2, GHC==9.0.2, GHC==8.10.7, GHC==8.8.4-extra-doc-files: README.md CHANGELOG.md-extra-source-files: cbits/*.h- cbits/aes/*.h- cbits/ed25519/*.h- cbits/decaf/include/*.h- cbits/decaf/include/decaf/*.h- cbits/decaf/include/arch_32/*.h- cbits/decaf/include/arch_ref64/*.h- cbits/decaf/p448/arch_32/*.h- cbits/decaf/p448/arch_ref64/*.h- cbits/decaf/p448/*.h- cbits/decaf/ed448goldilocks/decaf_tables.c- cbits/decaf/ed448goldilocks/decaf.c- cbits/include32/p256/*.h- cbits/include64/p256/*.h- cbits/blake2/ref/*.h- cbits/blake2/sse/*.h- cbits/argon2/*.h- cbits/argon2/*.c- cbits/aes/x86ni_impl.c- cbits/crypton_hash_prefix.c- tests/*.hs +category: Cryptography+build-type: Simple+extra-source-files:+ cbits/*.h+ cbits/aes/*.h+ cbits/ed25519/*.h+ cbits/decaf/include/*.h+ cbits/decaf/include/decaf/*.h+ cbits/decaf/include/arch_32/*.h+ cbits/decaf/include/arch_ref64/*.h+ cbits/decaf/p448/arch_32/*.h+ cbits/decaf/p448/arch_ref64/*.h+ cbits/decaf/p448/*.h+ cbits/decaf/ed448goldilocks/decaf_tables.c+ cbits/decaf/ed448goldilocks/decaf.c+ cbits/include32/p256/*.h+ cbits/include64/p256/*.h+ cbits/blake2/ref/*.h+ cbits/blake2/sse/*.h+ cbits/argon2/*.h+ cbits/argon2/*.c+ cbits/aes/x86ni_impl.c+ cbits/crypton_hash_prefix.c+ tests/*.hs++extra-doc-files:+ README.md+ CHANGELOG.md+ source-repository head- type: git- location: https://github.com/kazu-yamamoto/crypton+ type: git+ location: https://github.com/kazu-yamamoto/crypton -Flag support_aesni- Description: allow compilation with AESNI on system and architecture that supports it- Default: True- Manual: True+flag support_aesni+ description:+ allow compilation with AESNI on system and architecture that supports it -Flag support_rdrand- Description: allow compilation with RDRAND on system and architecture that supports it- Default: True- Manual: True+ manual: True -Flag support_pclmuldq- Description: Allow compilation with pclmuldq on architecture that supports it- Default: True- Manual: True+flag support_rdrand+ description:+ allow compilation with RDRAND on system and architecture that supports it -Flag support_sse- Description: Use SSE optimized version of (BLAKE2, ARGON2)- Default: False- Manual: True+ manual: True -Flag integer-gmp- Description: Whether or not to use GMP for some functions- Default: True- Manual: True+flag support_pclmuldq+ description:+ Allow compilation with pclmuldq on architecture that supports it -Flag support_deepseq- Description: add deepseq instances for cryptographic types- Default: True- Manual: True+ manual: True -Flag old_toolchain_inliner- Description: use -fgnu89-inline to workaround an old compiler / linker / glibc issue.- Default: False- Manual: True+flag support_sse+ description: Use SSE optimized version of (BLAKE2, ARGON2)+ default: False+ manual: True -Flag check_alignment- Description: extra check on alignment in C layers, which cause lowlevel assert errors. for debugging only.- Default: False- Manual: True+flag integer-gmp+ description: Whether or not to use GMP for some functions+ manual: True -Flag use_target_attributes- Description: use GCC / clang function attributes instead of global target options.- Default: True- Manual: True+flag support_deepseq+ description: add deepseq instances for cryptographic types+ manual: True -Library- Exposed-modules: Crypto.Cipher.AES- Crypto.Cipher.AESGCMSIV- Crypto.Cipher.Blowfish- Crypto.Cipher.CAST5- Crypto.Cipher.Camellia- Crypto.Cipher.ChaCha- Crypto.Cipher.ChaChaPoly1305- Crypto.Cipher.DES- Crypto.Cipher.RC4- Crypto.Cipher.Salsa- Crypto.Cipher.TripleDES- Crypto.Cipher.Twofish- Crypto.Cipher.Types- Crypto.Cipher.Utils- Crypto.Cipher.XSalsa- Crypto.ConstructHash.MiyaguchiPreneel- Crypto.Data.AFIS- Crypto.Data.Padding- Crypto.ECC- Crypto.ECC.Edwards25519- Crypto.Error- Crypto.MAC.CMAC- Crypto.MAC.Poly1305- Crypto.MAC.HMAC- Crypto.MAC.KMAC- Crypto.Number.Basic- Crypto.Number.F2m- Crypto.Number.Generate- Crypto.Number.ModArithmetic- Crypto.Number.Nat- Crypto.Number.Prime- Crypto.Number.Serialize- Crypto.Number.Serialize.LE- Crypto.Number.Serialize.Internal- Crypto.Number.Serialize.Internal.LE- Crypto.KDF.Argon2- Crypto.KDF.PBKDF2- Crypto.KDF.Scrypt- Crypto.KDF.BCrypt- Crypto.KDF.BCryptPBKDF- Crypto.KDF.HKDF- Crypto.Hash- Crypto.Hash.IO- Crypto.Hash.Algorithms- Crypto.OTP- Crypto.PubKey.Curve25519- Crypto.PubKey.Curve448- Crypto.PubKey.MaskGenFunction- Crypto.PubKey.DH- Crypto.PubKey.DSA- Crypto.PubKey.ECC.Generate- Crypto.PubKey.ECC.Prim- Crypto.PubKey.ECC.DH- Crypto.PubKey.ECC.ECDSA- Crypto.PubKey.ECC.P256- Crypto.PubKey.ECC.Types- Crypto.PubKey.ECDSA- Crypto.PubKey.ECIES- Crypto.PubKey.Ed25519- Crypto.PubKey.Ed448- Crypto.PubKey.EdDSA- Crypto.PubKey.RSA- Crypto.PubKey.RSA.PKCS15- Crypto.PubKey.RSA.Prim- Crypto.PubKey.RSA.PSS- Crypto.PubKey.RSA.OAEP- Crypto.PubKey.RSA.Types- Crypto.PubKey.Rabin.OAEP- Crypto.PubKey.Rabin.Basic- Crypto.PubKey.Rabin.Modified- Crypto.PubKey.Rabin.RW- Crypto.PubKey.Rabin.Types- Crypto.Random- Crypto.Random.Types- Crypto.Random.Entropy- Crypto.Random.EntropyPool- Crypto.Random.Entropy.Unsafe- Crypto.System.CPU- Crypto.Tutorial- Other-modules: Crypto.Cipher.AES.Primitive- Crypto.Cipher.Blowfish.Box- Crypto.Cipher.Blowfish.Primitive- Crypto.Cipher.CAST5.Primitive- Crypto.Cipher.Camellia.Primitive- Crypto.Cipher.DES.Primitive- Crypto.Cipher.Twofish.Primitive- Crypto.Cipher.Types.AEAD- Crypto.Cipher.Types.Base- Crypto.Cipher.Types.Block- Crypto.Cipher.Types.GF- Crypto.Cipher.Types.Stream- Crypto.Cipher.Types.Utils- Crypto.Error.Types- Crypto.Number.Compat- Crypto.Hash.Types- Crypto.Hash.Blake2- Crypto.Hash.Blake2s- Crypto.Hash.Blake2sp- Crypto.Hash.Blake2b- Crypto.Hash.Blake2bp- Crypto.Hash.SHA1- Crypto.Hash.SHA224- Crypto.Hash.SHA256- Crypto.Hash.SHA384- Crypto.Hash.SHA512- Crypto.Hash.SHA512t- Crypto.Hash.SHA3- Crypto.Hash.SHAKE- Crypto.Hash.Keccak- Crypto.Hash.MD2- Crypto.Hash.MD4- Crypto.Hash.MD5- Crypto.Hash.RIPEMD160- Crypto.Hash.Skein256- Crypto.Hash.Skein512- Crypto.Hash.Tiger- Crypto.Hash.Whirlpool- Crypto.Random.Entropy.Source- Crypto.Random.Entropy.Backend- Crypto.Random.ChaChaDRG- Crypto.Random.SystemDRG- Crypto.Random.Probabilistic- Crypto.PubKey.Internal- Crypto.PubKey.ElGamal- Crypto.ECC.Simple.Types- Crypto.ECC.Simple.Prim- Crypto.Internal.Builder- Crypto.Internal.ByteArray- Crypto.Internal.Compat- Crypto.Internal.CompatPrim- Crypto.Internal.DeepSeq- Crypto.Internal.Imports- Crypto.Internal.Nat- Crypto.Internal.Words- Crypto.Internal.WordArray- if impl(ghc < 8.8)- Buildable: False- else- Build-depends: base+flag old_toolchain_inliner+ description:+ use -fgnu89-inline to workaround an old compiler / linker / glibc issue. - Build-depends: bytestring- , memory >= 0.14.18- , basement >= 0.0.6- , ghc-prim- ghc-options: -Wall -fwarn-tabs -optc-O3- if os(linux)- extra-libraries: pthread- default-language: Haskell2010- cc-options: -std=gnu99- if flag(old_toolchain_inliner)- cc-options: -fgnu89-inline- C-sources: cbits/crypton_chacha.c- , cbits/crypton_salsa.c- , cbits/crypton_xsalsa.c- , cbits/crypton_rc4.c- , cbits/crypton_cpu.c- , cbits/p256/p256.c- , cbits/p256/p256_ec.c- , cbits/crypton_blake2s.c- , cbits/crypton_blake2sp.c- , cbits/crypton_blake2b.c- , cbits/crypton_blake2bp.c- , cbits/crypton_poly1305.c- , cbits/crypton_sha1.c- , cbits/crypton_sha256.c- , cbits/crypton_sha512.c- , cbits/crypton_sha3.c- , cbits/crypton_md2.c- , cbits/crypton_md4.c- , cbits/crypton_md5.c- , cbits/crypton_ripemd.c- , cbits/crypton_skein256.c- , cbits/crypton_skein512.c- , cbits/crypton_tiger.c- , cbits/crypton_whirlpool.c- , cbits/crypton_scrypt.c- , cbits/crypton_pbkdf2.c- , cbits/ed25519/ed25519.c- include-dirs: cbits- , cbits/ed25519- , cbits/decaf/include- , cbits/decaf/p448+ default: False+ manual: True - if arch(x86_64) || arch(aarch64)- include-dirs: cbits/include64- else- include-dirs: cbits/include32+flag check_alignment+ description:+ extra check on alignment in C layers, which cause lowlevel assert errors. for debugging only. - if arch(x86_64) || arch(aarch64)- C-sources: cbits/decaf/p448/arch_ref64/f_impl.c- , cbits/decaf/p448/f_generic.c- , cbits/decaf/p448/f_arithmetic.c- , cbits/decaf/utils.c- , cbits/decaf/ed448goldilocks/scalar.c- , cbits/decaf/ed448goldilocks/decaf_all.c- , cbits/decaf/ed448goldilocks/eddsa.c+ default: False+ manual: True - include-dirs: cbits/decaf/include/arch_ref64- , cbits/decaf/p448/arch_ref64- else- C-sources: cbits/decaf/p448/arch_32/f_impl.c- , cbits/decaf/p448/f_generic.c- , cbits/decaf/p448/f_arithmetic.c- , cbits/decaf/utils.c- , cbits/decaf/ed448goldilocks/scalar.c- , cbits/decaf/ed448goldilocks/decaf_all.c- , cbits/decaf/ed448goldilocks/eddsa.c+flag use_target_attributes+ description:+ use GCC / clang function attributes instead of global target options. - include-dirs: cbits/decaf/include/arch_32- , cbits/decaf/p448/arch_32+ manual: True - if arch(x86_64) || arch(aarch64)- C-sources: cbits/curve25519/curve25519-donna-c64.c- else- C-sources: cbits/curve25519/curve25519-donna.c+library+ exposed-modules:+ Crypto.Cipher.AES+ Crypto.Cipher.AESGCMSIV+ Crypto.Cipher.Blowfish+ Crypto.Cipher.CAST5+ Crypto.Cipher.Camellia+ Crypto.Cipher.ChaCha+ Crypto.Cipher.ChaChaPoly1305+ Crypto.Cipher.DES+ Crypto.Cipher.RC4+ Crypto.Cipher.Salsa+ Crypto.Cipher.TripleDES+ Crypto.Cipher.Twofish+ Crypto.Cipher.Types+ Crypto.Cipher.Utils+ Crypto.Cipher.XSalsa+ Crypto.ConstructHash.MiyaguchiPreneel+ Crypto.Data.AFIS+ Crypto.Data.Padding+ Crypto.ECC+ Crypto.ECC.Edwards25519+ Crypto.Error+ Crypto.MAC.CMAC+ Crypto.MAC.Poly1305+ Crypto.MAC.HMAC+ Crypto.MAC.KeyedBlake2+ Crypto.MAC.KMAC+ Crypto.Number.Basic+ Crypto.Number.F2m+ Crypto.Number.Generate+ Crypto.Number.ModArithmetic+ Crypto.Number.Nat+ Crypto.Number.Prime+ Crypto.Number.Serialize+ Crypto.Number.Serialize.LE+ Crypto.Number.Serialize.Internal+ Crypto.Number.Serialize.Internal.LE+ Crypto.KDF.Argon2+ Crypto.KDF.PBKDF2+ Crypto.KDF.Scrypt+ Crypto.KDF.BCrypt+ Crypto.KDF.BCryptPBKDF+ Crypto.KDF.HKDF+ Crypto.Hash+ Crypto.Hash.IO+ Crypto.Hash.Algorithms+ Crypto.OTP+ Crypto.PubKey.Curve25519+ Crypto.PubKey.Curve448+ Crypto.PubKey.MaskGenFunction+ Crypto.PubKey.DH+ Crypto.PubKey.DSA+ Crypto.PubKey.ECC.Generate+ Crypto.PubKey.ECC.Prim+ Crypto.PubKey.ECC.DH+ Crypto.PubKey.ECC.ECDSA+ Crypto.PubKey.ECC.P256+ Crypto.PubKey.ECC.Types+ Crypto.PubKey.ECDSA+ Crypto.PubKey.ECIES+ Crypto.PubKey.Ed25519+ Crypto.PubKey.Ed448+ Crypto.PubKey.EdDSA+ Crypto.PubKey.RSA+ Crypto.PubKey.RSA.PKCS15+ Crypto.PubKey.RSA.Prim+ Crypto.PubKey.RSA.PSS+ Crypto.PubKey.RSA.OAEP+ Crypto.PubKey.RSA.Types+ Crypto.PubKey.Rabin.OAEP+ Crypto.PubKey.Rabin.Basic+ Crypto.PubKey.Rabin.Modified+ Crypto.PubKey.Rabin.RW+ Crypto.PubKey.Rabin.Types+ Crypto.Random+ Crypto.Random.Types+ Crypto.Random.Entropy+ Crypto.Random.EntropyPool+ Crypto.Random.Entropy.Unsafe+ Crypto.System.CPU+ Crypto.Tutorial - -- FIXME armel or mispel is also little endian.- -- might be a good idea to also add a runtime autodetect mode.- -- ARCH_ENDIAN_UNKNOWN- if (arch(i386) || arch(x86_64))- CPP-options: -DARCH_IS_LITTLE_ENDIAN+ cc-options: -std=gnu99+ c-sources:+ cbits/crypton_chacha.c+ cbits/crypton_salsa.c+ cbits/crypton_xsalsa.c+ cbits/crypton_rc4.c+ cbits/crypton_cpu.c+ cbits/p256/p256.c+ cbits/p256/p256_ec.c+ cbits/crypton_blake2s.c+ cbits/crypton_blake2sp.c+ cbits/crypton_blake2b.c+ cbits/crypton_blake2bp.c+ cbits/crypton_poly1305.c+ cbits/crypton_sha1.c+ cbits/crypton_sha256.c+ cbits/crypton_sha512.c+ cbits/crypton_sha3.c+ cbits/crypton_md2.c+ cbits/crypton_md4.c+ cbits/crypton_md5.c+ cbits/crypton_ripemd.c+ cbits/crypton_skein256.c+ cbits/crypton_skein512.c+ cbits/crypton_tiger.c+ cbits/crypton_whirlpool.c+ cbits/crypton_scrypt.c+ cbits/crypton_pbkdf2.c+ cbits/ed25519/ed25519.c+ cbits/argon2/argon2.c - if arch(i386)- CPP-options: -DARCH_X86+ other-modules:+ Crypto.Cipher.AES.Primitive+ Crypto.Cipher.Blowfish.Box+ Crypto.Cipher.Blowfish.Primitive+ Crypto.Cipher.CAST5.Primitive+ Crypto.Cipher.Camellia.Primitive+ Crypto.Cipher.DES.Primitive+ Crypto.Cipher.Twofish.Primitive+ Crypto.Cipher.Types.AEAD+ Crypto.Cipher.Types.Base+ Crypto.Cipher.Types.Block+ Crypto.Cipher.Types.GF+ Crypto.Cipher.Types.Stream+ Crypto.Cipher.Types.Utils+ Crypto.Error.Types+ Crypto.Number.Compat+ Crypto.Hash.Types+ Crypto.Hash.Blake2+ Crypto.Hash.Blake2s+ Crypto.Hash.Blake2sp+ Crypto.Hash.Blake2b+ Crypto.Hash.Blake2bp+ Crypto.Hash.SHA1+ Crypto.Hash.SHA224+ Crypto.Hash.SHA256+ Crypto.Hash.SHA384+ Crypto.Hash.SHA512+ Crypto.Hash.SHA512t+ Crypto.Hash.SHA3+ Crypto.Hash.SHAKE+ Crypto.Hash.Keccak+ Crypto.Hash.MD2+ Crypto.Hash.MD4+ Crypto.Hash.MD5+ Crypto.Hash.RIPEMD160+ Crypto.Hash.Skein256+ Crypto.Hash.Skein512+ Crypto.Hash.Tiger+ Crypto.Hash.Whirlpool+ Crypto.Random.Entropy.Source+ Crypto.Random.Entropy.Backend+ Crypto.Random.ChaChaDRG+ Crypto.Random.SystemDRG+ Crypto.Random.Probabilistic+ Crypto.PubKey.Internal+ Crypto.PubKey.ElGamal+ Crypto.ECC.Simple.Types+ Crypto.ECC.Simple.Prim+ Crypto.Internal.Builder+ Crypto.Internal.ByteArray+ Crypto.Internal.Compat+ Crypto.Internal.CompatPrim+ Crypto.Internal.DeepSeq+ Crypto.Internal.Imports+ Crypto.Internal.Nat+ Crypto.Internal.Words+ Crypto.Internal.WordArray - if arch(x86_64)- CPP-options: -DARCH_X86_64+ default-language: Haskell2010+ include-dirs:+ cbits cbits/ed25519 cbits/decaf/include cbits/decaf/p448+ cbits/argon2 - if flag(support_rdrand) && (arch(i386) || arch(x86_64)) && !os(windows)- CPP-options: -DSUPPORT_RDRAND- Other-modules: Crypto.Random.Entropy.RDRand- c-sources: cbits/crypton_rdrand.c+ ghc-options: -Wall -fwarn-tabs -optc-O3+ build-depends:+ bytestring,+ memory >=0.14.18,+ basement >=0.0.6,+ ghc-prim - if flag(support_aesni) && (os(linux) || os(freebsd) || os(osx)) && (arch(i386) || arch(x86_64))- CC-options: -DWITH_AESNI- if !flag(use_target_attributes)- CC-options: -mssse3 -maes- if flag(support_pclmuldq)- CC-options: -DWITH_PCLMUL- if !flag(use_target_attributes)- CC-options: -msse4.1 -mpclmul- C-sources: cbits/aes/x86ni.c- , cbits/aes/generic.c- , cbits/aes/gf.c- , cbits/crypton_aes.c- else- C-sources: cbits/aes/generic.c- , cbits/aes/gf.c- , cbits/crypton_aes.c+ if impl(ghc <8.8)+ buildable: False - if arch(x86_64) || flag(support_sse)- C-sources: cbits/blake2/sse/blake2s.c- , cbits/blake2/sse/blake2sp.c- , cbits/blake2/sse/blake2b.c- , cbits/blake2/sse/blake2bp.c- include-dirs: cbits/blake2/sse- else- C-sources: cbits/blake2/ref/blake2s-ref.c- , cbits/blake2/ref/blake2sp-ref.c- , cbits/blake2/ref/blake2b-ref.c- , cbits/blake2/ref/blake2bp-ref.c- include-dirs: cbits/blake2/ref+ else+ build-depends: base - if arch(x86_64) || flag(support_sse)- CPP-options: -DSUPPORT_SSE+ if os(linux)+ extra-libraries: pthread++ if flag(old_toolchain_inliner)+ cc-options: -fgnu89-inline++ if (arch(x86_64) || arch(aarch64))+ include-dirs: cbits/include64++ else+ include-dirs: cbits/include32++ if (arch(x86_64) || arch(aarch64))+ c-sources:+ cbits/decaf/p448/arch_ref64/f_impl.c+ cbits/decaf/p448/f_generic.c+ cbits/decaf/p448/f_arithmetic.c+ cbits/decaf/utils.c+ cbits/decaf/ed448goldilocks/scalar.c+ cbits/decaf/ed448goldilocks/decaf_all.c+ cbits/decaf/ed448goldilocks/eddsa.c++ include-dirs: cbits/decaf/include/arch_ref64 cbits/decaf/p448/arch_ref64++ else+ c-sources:+ cbits/decaf/p448/arch_32/f_impl.c+ cbits/decaf/p448/f_generic.c+ cbits/decaf/p448/f_arithmetic.c+ cbits/decaf/utils.c+ cbits/decaf/ed448goldilocks/scalar.c+ cbits/decaf/ed448goldilocks/decaf_all.c+ cbits/decaf/ed448goldilocks/eddsa.c++ include-dirs: cbits/decaf/include/arch_32 cbits/decaf/p448/arch_32++ if (arch(x86_64) || arch(aarch64))+ c-sources: cbits/curve25519/curve25519-donna-c64.c++ else+ c-sources: cbits/curve25519/curve25519-donna.c++ if (arch(i386) || arch(x86_64))+ cpp-options: -DARCH_IS_LITTLE_ENDIAN+ if arch(i386)- CC-options: -msse2+ cpp-options: -DARCH_X86 - C-sources: cbits/argon2/argon2.c- include-dirs: cbits/argon2+ if arch(x86_64)+ cpp-options: -DARCH_X86_64 - if os(windows)- cpp-options: -DWINDOWS- Build-Depends: Win32- Other-modules: Crypto.Random.Entropy.Windows- extra-libraries: advapi32- else- Other-modules: Crypto.Random.Entropy.Unix+ if ((flag(support_rdrand) && (arch(i386) || arch(x86_64))) && !os(windows))+ cpp-options: -DSUPPORT_RDRAND+ c-sources: cbits/crypton_rdrand.c+ other-modules: Crypto.Random.Entropy.RDRand - if impl(ghc) && flag(integer-gmp)- Build-depends: integer-gmp+ if ((flag(support_aesni) && ((os(linux) || os(freebsd)) || os(osx))) && (arch(i386) || arch(x86_64)))+ cc-options: -DWITH_AESNI+ c-sources:+ cbits/aes/x86ni.c+ cbits/aes/generic.c+ cbits/aes/gf.c+ cbits/crypton_aes.c - if flag(support_deepseq)- CPP-options: -DWITH_DEEPSEQ_SUPPORT- Build-depends: deepseq- if flag(check_alignment)- cc-options: -DWITH_ASSERT_ALIGNMENT- if flag(use_target_attributes)- cc-options: -DWITH_TARGET_ATTRIBUTES+ if !flag(use_target_attributes)+ cc-options: -mssse3 -maes -Test-Suite test-crypton- type: exitcode-stdio-1.0- hs-source-dirs: tests- Main-is: Tests.hs- Other-modules: BlockCipher- ChaCha- BCrypt- BCryptPBKDF- ECC- ECC.Edwards25519- ECDSA- Hash- Imports- KAT_AES.KATCBC- KAT_AES.KATECB- KAT_AES.KATGCM- KAT_AES.KATCCM- KAT_AES.KATOCB3- KAT_AES.KATXTS- KAT_AES- KAT_AESGCMSIV- KAT_AFIS- KAT_Argon2- KAT_Blowfish- KAT_CAST5- KAT_Camellia- KAT_Curve25519- KAT_Curve448- KAT_DES- KAT_Ed25519- KAT_Ed448- KAT_EdDSA- KAT_CMAC- KAT_HKDF- KAT_HMAC- KAT_KMAC- KAT_MiyaguchiPreneel- KAT_PBKDF2- KAT_OTP- KAT_PubKey.DSA- KAT_PubKey.ECC- KAT_PubKey.ECDSA- KAT_PubKey.OAEP- KAT_PubKey.PSS- KAT_PubKey.P256- KAT_PubKey.RSA- KAT_PubKey.Rabin- KAT_PubKey- KAT_RC4- KAT_Scrypt- KAT_TripleDES- KAT_Twofish- ChaChaPoly1305- Number- Number.F2m- Padding- Poly1305- Salsa- Utils- XSalsa- Build-Depends: base >= 0 && < 10- , bytestring- , memory- , tasty- , tasty-quickcheck- , tasty-hunit- , tasty-kat- , crypton- ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures -rtsopts- default-language: Haskell2010+ if flag(support_pclmuldq)+ cc-options: -DWITH_PCLMUL -Benchmark bench-crypton- type: exitcode-stdio-1.0- hs-source-dirs: benchs- Main-is: Bench.hs- Other-modules: Number.F2m- Build-Depends: base- , bytestring- , deepseq- , memory- , gauge- , random- , crypton- ghc-options: -Wall -fno-warn-missing-signatures- default-language: Haskell2010+ if !flag(use_target_attributes)+ cc-options: -msse4.1 -mpclmul++ else+ c-sources:+ cbits/aes/generic.c+ cbits/aes/gf.c+ cbits/crypton_aes.c++ if (arch(x86_64) || flag(support_sse))+ c-sources:+ cbits/blake2/sse/blake2s.c+ cbits/blake2/sse/blake2sp.c+ cbits/blake2/sse/blake2b.c+ cbits/blake2/sse/blake2bp.c++ include-dirs: cbits/blake2/sse++ else+ c-sources:+ cbits/blake2/ref/blake2s-ref.c+ cbits/blake2/ref/blake2sp-ref.c+ cbits/blake2/ref/blake2b-ref.c+ cbits/blake2/ref/blake2bp-ref.c++ include-dirs: cbits/blake2/ref++ if (arch(x86_64) || flag(support_sse))+ cpp-options: -DSUPPORT_SSE++ if arch(i386)+ cc-options: -msse2++ if os(windows)+ cpp-options: -DWINDOWS+ other-modules: Crypto.Random.Entropy.Windows+ extra-libraries: advapi32+ build-depends: Win32++ else+ other-modules: Crypto.Random.Entropy.Unix++ if (impl(ghc >=0) && flag(integer-gmp))+ build-depends: integer-gmp++ if flag(support_deepseq)+ cpp-options: -DWITH_DEEPSEQ_SUPPORT+ build-depends: deepseq++ if flag(check_alignment)+ cc-options: -DWITH_ASSERT_ALIGNMENT++ if flag(use_target_attributes)+ cc-options: -DWITH_TARGET_ATTRIBUTES++test-suite test-crypton+ type: exitcode-stdio-1.0+ main-is: Tests.hs+ hs-source-dirs: tests+ other-modules:+ BlockCipher+ ChaCha+ BCrypt+ BCryptPBKDF+ ECC+ ECC.Edwards25519+ ECDSA+ Hash+ Imports+ KAT_AES.KATCBC+ KAT_AES.KATECB+ KAT_AES.KATGCM+ KAT_AES.KATCCM+ KAT_AES.KATOCB3+ KAT_AES.KATXTS+ KAT_AES+ KAT_AESGCMSIV+ KAT_AFIS+ KAT_Argon2+ KAT_Blowfish+ KAT_CAST5+ KAT_Camellia+ KAT_Curve25519+ KAT_Curve448+ KAT_DES+ KAT_Ed25519+ KAT_Ed448+ KAT_EdDSA+ KAT_Blake2+ KAT_CMAC+ KAT_HKDF+ KAT_HMAC+ KAT_KMAC+ KAT_MiyaguchiPreneel+ KAT_PBKDF2+ KAT_OTP+ KAT_PubKey.DSA+ KAT_PubKey.ECC+ KAT_PubKey.ECDSA+ KAT_PubKey.OAEP+ KAT_PubKey.PSS+ KAT_PubKey.P256+ KAT_PubKey.RSA+ KAT_PubKey.Rabin+ KAT_PubKey+ KAT_RC4+ KAT_Scrypt+ KAT_TripleDES+ KAT_Twofish+ ChaChaPoly1305+ Number+ Number.F2m+ Padding+ Poly1305+ Salsa+ Utils+ XSalsa++ default-language: Haskell2010+ ghc-options:+ -Wall -fno-warn-orphans -fno-warn-missing-signatures -rtsopts++ build-depends:+ base >=0 && <10,+ bytestring,+ memory,+ tasty,+ tasty-quickcheck,+ tasty-hunit,+ tasty-kat,+ crypton++benchmark bench-crypton+ type: exitcode-stdio-1.0+ main-is: Bench.hs+ hs-source-dirs: benchs+ other-modules: Number.F2m+ default-language: Haskell2010+ ghc-options: -Wall -fno-warn-missing-signatures+ build-depends:+ base,+ bytestring,+ deepseq,+ memory,+ gauge,+ random,+ crypton
tests/ChaCha.hs view
@@ -23,6 +23,18 @@ b20_256_k0_i0 = "\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5\x31\xed\x1f\x28\x51\x0a\xfb\x45\xac\xe1\x0a\x1f\x4b\x79\x4d\x6f" +-- XChaCha20 test vector from RFC draft: https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha++xChaCha20_ExampleKAT = expected @=? fst (ChaCha.combine initState plaintext)+ where iv = B.pack $ [0x40 .. 0x56] ++ [0x58]+ key = B.pack [0x80 .. 0x9f]+ initState = ChaCha.initializeX 20 key iv+ plaintext :: B.ByteString+ plaintext = "The dhole (pronounced \"dole\") is also known as the Asiatic wild dog, red dog, and whistling dog. It is about the size of a German shepherd but looks more like a long-legged fox. This highly elusive and skilled jumper is classified with wolves, coyotes, jackals, and foxes in the taxonomic family Canidae."+ expected :: B.ByteString+ expected = "\x45\x59\xab\xba\x4e\x48\xc1\x61\x02\xe8\xbb\x2c\x05\xe6\x94\x7f\x50\xa7\x86\xde\x16\x2f\x9b\x0b\x7e\x59\x2a\x9b\x53\xd0\xd4\xe9\x8d\x8d\x64\x10\xd5\x40\xa1\xa6\x37\x5b\x26\xd8\x0d\xac\xe4\xfa\xb5\x23\x84\xc7\x31\xac\xbf\x16\xa5\x92\x3c\x0c\x48\xd3\x57\x5d\x4d\x0d\x2c\x67\x3b\x66\x6f\xaa\x73\x10\x61\x27\x77\x01\x09\x3a\x6b\xf7\xa1\x58\xa8\x86\x42\x92\xa4\x1c\x48\xe3\xa9\xb4\xc0\xda\xec\xe0\xf8\xd9\x8d\x0d\x7e\x05\xb3\x7a\x30\x7b\xbb\x66\x33\x31\x64\xec\x9e\x1b\x24\xea\x0d\x6c\x3f\xfd\xdc\xec\x4f\x68\xe7\x44\x30\x56\x19\x3a\x03\xc8\x10\xe1\x13\x44\xca\x06\xd8\xed\x8a\x2b\xfb\x1e\x8d\x48\xcf\xa6\xbc\x0e\xb4\xe2\x46\x4b\x74\x81\x42\x40\x7c\x9f\x43\x1a\xee\x76\x99\x60\xe1\x5b\xa8\xb9\x68\x90\x46\x6e\xf2\x45\x75\x99\x85\x23\x85\xc6\x61\xf7\x52\xce\x20\xf9\xda\x0c\x09\xab\x6b\x19\xdf\x74\xe7\x6a\x95\x96\x74\x46\xf8\xd0\xfd\x41\x5e\x7b\xee\x2a\x12\xa1\x14\xc2\x0e\xb5\x29\x2a\xe7\xa3\x49\xae\x57\x78\x20\xd5\x52\x0a\x1f\x3f\xb6\x2a\x17\xce\x6a\x7e\x68\xfa\x7c\x79\x11\x1d\x88\x60\x92\x0b\xc0\x48\xef\x43\xfe\x84\x48\x6c\xcb\x87\xc2\x5f\x0a\xe0\x45\xf0\xcc\xe1\xe7\x98\x9a\x9a\xa2\x20\xa2\x8b\xdd\x48\x27\xe7\x51\xa2\x4a\x6d\x5c\x62\xd7\x90\xa6\x63\x93\xb9\x31\x11\xc1\xa5\x5d\xd7\x42\x1a\x10\x18\x49\x74\xc7\xc5"++ data Vector = Vector Int -- rounds ByteString -- key ByteString -- nonce@@ -38,6 +50,7 @@ , testCase "8-256-K0-I0" (chachaRunSimple b8_256_k0_i0 8 32 8) , testCase "12-256-K0-I0" (chachaRunSimple b12_256_k0_i0 12 32 8) , testCase "20-256-K0-I0" (chachaRunSimple b20_256_k0_i0 20 32 8)+ , testCase "XChaCha20 example KAT" xChaCha20_ExampleKAT , testProperty "generate-combine" chachaGenerateCombine , testProperty "chunking-generate" chachaGenerateChunks , testProperty "chunking-combine" chachaCombineChunks
tests/ChaChaPoly1305.hs view
@@ -9,14 +9,17 @@ import qualified Data.ByteString as B import qualified Data.ByteArray as B (convert) -plaintext, aad, key, iv, ciphertext, tag, nonce1, nonce2, nonce3, nonce4, nonce5, nonce6, nonce7, nonce8, nonce9, nonce10 :: B.ByteString+plaintext, aad, key, iv, ivX, ciphertext, ciphertextX, tag, tagX, nonce1, nonce2, nonce3, nonce4, nonce5, nonce6, nonce7, nonce8, nonce9, nonce10 :: B.ByteString plaintext = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." aad = "\x50\x51\x52\x53\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7" key = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" iv = "\x40\x41\x42\x43\x44\x45\x46\x47"+ivX = B.pack [0x40 .. 0x57] constant = "\x07\x00\x00\x00" ciphertext = "\xd3\x1a\x8d\x34\x64\x8e\x60\xdb\x7b\x86\xaf\xbc\x53\xef\x7e\xc2\xa4\xad\xed\x51\x29\x6e\x08\xfe\xa9\xe2\xb5\xa7\x36\xee\x62\xd6\x3d\xbe\xa4\x5e\x8c\xa9\x67\x12\x82\xfa\xfb\x69\xda\x92\x72\x8b\x1a\x71\xde\x0a\x9e\x06\x0b\x29\x05\xd6\xa5\xb6\x7e\xcd\x3b\x36\x92\xdd\xbd\x7f\x2d\x77\x8b\x8c\x98\x03\xae\xe3\x28\x09\x1b\x58\xfa\xb3\x24\xe4\xfa\xd6\x75\x94\x55\x85\x80\x8b\x48\x31\xd7\xbc\x3f\xf4\xde\xf0\x8e\x4b\x7a\x9d\xe5\x76\xd2\x65\x86\xce\xc6\x4b\x61\x16"+ciphertextX = "\xbd\x6d\x17\x9d\x3e\x83\xd4\x3b\x95\x76\x57\x94\x93\xc0\xe9\x39\x57\x2a\x17\x00\x25\x2b\xfa\xcc\xbe\xd2\x90\x2c\x21\x39\x6c\xbb\x73\x1c\x7f\x1b\x0b\x4a\xa6\x44\x0b\xf3\xa8\x2f\x4e\xda\x7e\x39\xae\x64\xc6\x70\x8c\x54\xc2\x16\xcb\x96\xb7\x2e\x12\x13\xb4\x52\x2f\x8c\x9b\xa4\x0d\xb5\xd9\x45\xb1\x1b\x69\xb9\x82\xc1\xbb\x9e\x3f\x3f\xac\x2b\xc3\x69\x48\x8f\x76\xb2\x38\x35\x65\xd3\xff\xf9\x21\xf9\x66\x4c\x97\x63\x7d\xa9\x76\x88\x12\xf6\x15\xc6\x8b\x13\xb5\x2e" tag = "\x1a\xe1\x0b\x59\x4f\x09\xe2\x6a\x7e\x90\x2e\xcb\xd0\x60\x06\x91"+tagX = "\xc0\x87\x59\x24\xc1\xc7\x98\x79\x47\xde\xaf\xd8\x78\x0a\xcf\x49" nonce1 = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" nonce2 = "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" nonce3 = "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"@@ -31,6 +34,8 @@ tests = testGroup "ChaChaPoly1305" [ testCase "V1" runEncrypt , testCase "V1-decrypt" runDecrypt+ , testCase "V1-extended" runEncryptX+ , testCase "V1-extended-decrypt" runDecryptX , testCase "nonce increment" runNonceInc ] where runEncrypt =@@ -41,6 +46,14 @@ in propertyHoldCase [ eqTest "ciphertext" ciphertext out , eqTest "tag" tag (B.convert outtag) ]+ runEncryptX =+ let ini = throwCryptoError $ AEAD.initializeX key (throwCryptoError $ AEAD.nonce24 ivX)+ afterAAD = AEAD.finalizeAAD (AEAD.appendAAD aad ini)+ (out, afterEncrypt) = AEAD.encrypt plaintext afterAAD+ outtag = AEAD.finalize afterEncrypt+ in propertyHoldCase [ eqTest "ciphertext" ciphertextX out+ , eqTest "tag" tagX (B.convert outtag)+ ] runDecrypt = let ini = throwCryptoError $ AEAD.initialize key (throwCryptoError $ AEAD.nonce8 constant iv)@@ -49,6 +62,15 @@ outtag = AEAD.finalize afterDecrypt in propertyHoldCase [ eqTest "plaintext" plaintext out , eqTest "tag" tag (B.convert outtag)+ ]++ runDecryptX =+ let ini = throwCryptoError $ AEAD.initializeX key (throwCryptoError $ AEAD.nonce24 ivX)+ afterAAD = AEAD.finalizeAAD (AEAD.appendAAD aad ini)+ (out, afterDecrypt) = AEAD.decrypt ciphertextX afterAAD+ outtag = AEAD.finalize afterDecrypt+ in propertyHoldCase [ eqTest "plaintext" plaintext out+ , eqTest "tag" tagX (B.convert outtag) ] runNonceInc =
+ tests/KAT_Blake2.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+module KAT_Blake2 (tests) where++import Crypto.Hash (digestFromByteString)+import Crypto.Hash.Algorithms+import qualified Crypto.MAC.KeyedBlake2 as KB++import qualified Data.ByteString as B++import Imports+++data MACVector hash = MACVector+ { macMessage :: ByteString+ , macKey :: ByteString+ , macResult :: KB.KeyedBlake2 hash+ }++instance Show (KB.KeyedBlake2 hash) where+ show (KB.KeyedBlake2 d) = show d++digest :: KB.HashBlake2 hash => ByteString -> KB.KeyedBlake2 hash+digest = maybe (error "cannot get digest") KB.KeyedBlake2 . digestFromByteString+++-- From: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/+vectorsBlake2bKAT :: [MACVector (Blake2b 512)]+vectorsBlake2bKAT =+ [ MACVector+ { macMessage = ""+ , macKey = fixedKey+ , macResult = digest "\x10\xeb\xb6\x77\x00\xb1\x86\x8e\xfb\x44\x17\x98\x7a\xcf\x46\x90\xae\x9d\x97\x2f\xb7\xa5\x90\xc2\xf0\x28\x71\x79\x9a\xaa\x47\x86\xb5\xe9\x96\xe8\xf0\xf4\xeb\x98\x1f\xc2\x14\xb0\x05\xf4\x2d\x2f\xf4\x23\x34\x99\x39\x16\x53\xdf\x7a\xef\xcb\xc1\x3f\xc5\x15\x68"+ }+ , MACVector+ { macMessage = "\x00"+ , macKey = fixedKey+ , macResult = digest "\x96\x1f\x6d\xd1\xe4\xdd\x30\xf6\x39\x01\x69\x0c\x51\x2e\x78\xe4\xb4\x5e\x47\x42\xed\x19\x7c\x3c\x5e\x45\xc5\x49\xfd\x25\xf2\xe4\x18\x7b\x0b\xc9\xfe\x30\x49\x2b\x16\xb0\xd0\xbc\x4e\xf9\xb0\xf3\x4c\x70\x03\xfa\xc0\x9a\x5e\xf1\x53\x2e\x69\x43\x02\x34\xce\xbd"+ }+ , MACVector+ { macMessage = B.pack [ 0x00 .. 0xfe ]+ , macKey = fixedKey+ , macResult = digest "\x14\x27\x09\xd6\x2e\x28\xfc\xcc\xd0\xaf\x97\xfa\xd0\xf8\x46\x5b\x97\x1e\x82\x20\x1d\xc5\x10\x70\xfa\xa0\x37\x2a\xa4\x3e\x92\x48\x4b\xe1\xc1\xe7\x3b\xa1\x09\x06\xd5\xd1\x85\x3d\xb6\xa4\x10\x6e\x0a\x7b\xf9\x80\x0d\x37\x3d\x6d\xee\x2d\x46\xd6\x2e\xf2\xa4\x61"+ }+ ]+ where fixedKey = B.pack [ 0x00 .. 0x3f ]++vectorsBlake2bpKAT :: [MACVector (Blake2bp 512)]+vectorsBlake2bpKAT =+ [ MACVector+ { macMessage = ""+ , macKey = fixedKey+ , macResult = digest "\x9d\x94\x61\x07\x3e\x4e\xb6\x40\xa2\x55\x35\x7b\x83\x9f\x39\x4b\x83\x8c\x6f\xf5\x7c\x9b\x68\x6a\x3f\x76\x10\x7c\x10\x66\x72\x8f\x3c\x99\x56\xbd\x78\x5c\xbc\x3b\xf7\x9d\xc2\xab\x57\x8c\x5a\x0c\x06\x3b\x9d\x9c\x40\x58\x48\xde\x1d\xbe\x82\x1c\xd0\x5c\x94\x0a"+ }+ , MACVector+ { macMessage = "\x00"+ , macKey = fixedKey+ , macResult = digest "\xff\x8e\x90\xa3\x7b\x94\x62\x39\x32\xc5\x9f\x75\x59\xf2\x60\x35\x02\x9c\x37\x67\x32\xcb\x14\xd4\x16\x02\x00\x1c\xbb\x73\xad\xb7\x92\x93\xa2\xdb\xda\x5f\x60\x70\x30\x25\x14\x4d\x15\x8e\x27\x35\x52\x95\x96\x25\x1c\x73\xc0\x34\x5c\xa6\xfc\xcb\x1f\xb1\xe9\x7e"+ }+ , MACVector+ { macMessage = B.pack [ 0x00 .. 0xfe ]+ , macKey = fixedKey+ , macResult = digest "\x96\xfb\xcb\xb6\x0b\xd3\x13\xb8\x84\x50\x33\xe5\xbc\x05\x8a\x38\x02\x74\x38\x57\x2d\x7e\x79\x57\xf3\x68\x4f\x62\x68\xaa\xdd\x3a\xd0\x8d\x21\x76\x7e\xd6\x87\x86\x85\x33\x1b\xa9\x85\x71\x48\x7e\x12\x47\x0a\xad\x66\x93\x26\x71\x6e\x46\x66\x7f\x69\xf8\xd7\xe8"+ }+ ]+ where fixedKey = B.pack [ 0x00 .. 0x3f ]++vectorsBlake2sKAT :: [MACVector (Blake2s 256)]+vectorsBlake2sKAT =+ [ MACVector+ { macMessage = ""+ , macKey = fixedKey+ , macResult = digest "\x48\xa8\x99\x7d\xa4\x07\x87\x6b\x3d\x79\xc0\xd9\x23\x25\xad\x3b\x89\xcb\xb7\x54\xd8\x6a\xb7\x1a\xee\x04\x7a\xd3\x45\xfd\x2c\x49"+ }+ , MACVector+ { macMessage = "\x00"+ , macKey = fixedKey+ , macResult = digest "\x40\xd1\x5f\xee\x7c\x32\x88\x30\x16\x6a\xc3\xf9\x18\x65\x0f\x80\x7e\x7e\x01\xe1\x77\x25\x8c\xdc\x0a\x39\xb1\x1f\x59\x80\x66\xf1"+ }+ , MACVector+ { macMessage = B.pack [ 0x00 .. 0xfe ]+ , macKey = fixedKey+ , macResult = digest "\x3f\xb7\x35\x06\x1a\xbc\x51\x9d\xfe\x97\x9e\x54\xc1\xee\x5b\xfa\xd0\xa9\xd8\x58\xb3\x31\x5b\xad\x34\xbd\xe9\x99\xef\xd7\x24\xdd"+ }+ ]+ where fixedKey = B.pack [ 0x00 .. 0x1f ]++vectorsBlake2spKAT :: [MACVector (Blake2sp 256)]+vectorsBlake2spKAT =+ [ MACVector+ { macMessage = ""+ , macKey = fixedKey+ , macResult = digest "\x71\x5c\xb1\x38\x95\xae\xb6\x78\xf6\x12\x41\x60\xbf\xf2\x14\x65\xb3\x0f\x4f\x68\x74\x19\x3f\xc8\x51\xb4\x62\x10\x43\xf0\x9c\xc6"+ }+ , MACVector+ { macMessage = "\x00"+ , macKey = fixedKey+ , macResult = digest "\x40\x57\x8f\xfa\x52\xbf\x51\xae\x18\x66\xf4\x28\x4d\x3a\x15\x7f\xc1\xbc\xd3\x6a\xc1\x3c\xbd\xcb\x03\x77\xe4\xd0\xcd\x0b\x66\x03"+ }+ , MACVector+ { macMessage = B.pack [ 0x00 .. 0xfe ]+ , macKey = fixedKey+ , macResult = digest "\x0c\x8a\x36\x59\x7d\x74\x61\xc6\x3a\x94\x73\x28\x21\xc9\x41\x85\x6c\x66\x83\x76\x60\x6c\x86\xa5\x2d\xe0\xee\x41\x04\xc6\x15\xdb"+ }+ ]+ where fixedKey = B.pack [ 0x00 .. 0x1f ]++macTests :: [TestTree]+macTests =+ [ testGroup "Blake2b_512" (concatMap toMACTest $ zip is vectorsBlake2bKAT)+ , testGroup "Blake2bp_512" (concatMap toMACTest $ zip is vectorsBlake2bpKAT)+ , testGroup "Blake2s_512" (concatMap toMACTest $ zip is vectorsBlake2sKAT)+ , testGroup "Blake2sp_512" (concatMap toMACTest $ zip is vectorsBlake2spKAT)+ ]+ where toMACTest (i, MACVector{..}) =+ [ testCase (show i) (macResult @=? KB.keyedBlake2 macKey macMessage)+ , testCase ("incr-" ++ show i) (macResult @=?+ KB.finalize (KB.update (KB.initialize macKey) macMessage))+ ]+ is :: [Int]+ is = [1..]++data MacIncremental a = MacIncremental ByteString ByteString (KB.KeyedBlake2 a)+ deriving (Show,Eq)++instance KB.HashBlake2 a => Arbitrary (MacIncremental a) where+ arbitrary = do+ key <- arbitraryBSof 32 64+ msg <- arbitraryBSof 1 99+ return $ MacIncremental key msg (KB.keyedBlake2 key msg)++data MacIncrementalList a = MacIncrementalList ByteString [ByteString] (KB.KeyedBlake2 a)+ deriving (Show,Eq)++instance KB.HashBlake2 a => Arbitrary (MacIncrementalList a) where+ arbitrary = do+ key <- arbitraryBSof 32 64+ msgs <- choose (1,20) >>= \n -> replicateM n (arbitraryBSof 1 99)+ return $ MacIncrementalList key msgs (KB.keyedBlake2 key (B.concat msgs))++macIncrementalTests :: [TestTree]+macIncrementalTests =+ [ testIncrProperties "Blake2b_512" (Blake2b :: Blake2b 512)+ , testIncrProperties "Blake2bp_512" (Blake2bp :: Blake2bp 512)+ , testIncrProperties "Blake2s_256" (Blake2s :: Blake2s 256)+ , testIncrProperties "Blake2sp_256" (Blake2sp :: Blake2sp 256)+ ]+ where+ testIncrProperties :: KB.HashBlake2 a => TestName -> a -> TestTree+ testIncrProperties name a = testGroup name+ [ testProperty "list-one" (prop_inc0 a)+ , testProperty "list-multi" (prop_inc1 a)+ ]++ prop_inc0 :: KB.HashBlake2 a => a -> MacIncremental a -> Bool+ prop_inc0 _ (MacIncremental secret msg result) =+ result `assertEq` KB.finalize (KB.update (KB.initialize secret) msg)++ prop_inc1 :: KB.HashBlake2 a => a -> MacIncrementalList a -> Bool+ prop_inc1 _ (MacIncrementalList secret msgs result) =+ result `assertEq` KB.finalize (foldl' KB.update (KB.initialize secret) msgs)++tests = testGroup "Blake2"+ [ testGroup "KATs" macTests+ , testGroup "properties" macIncrementalTests ]
tests/Tests.hs view
@@ -19,6 +19,7 @@ import qualified ChaCha import qualified ChaChaPoly1305 import qualified KAT_MiyaguchiPreneel+import qualified KAT_Blake2 import qualified KAT_CMAC import qualified KAT_HMAC import qualified KAT_KMAC@@ -60,6 +61,7 @@ ] , testGroup "MAC" [ Poly1305.tests+ , KAT_Blake2.tests , KAT_CMAC.tests , KAT_HMAC.tests , KAT_KMAC.tests