Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ghc-cryptonite for openSUSE:Factory checked in at 2021-02-16 22:37:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-cryptonite (Old) and /work/SRC/openSUSE:Factory/.ghc-cryptonite.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-cryptonite" Tue Feb 16 22:37:18 2021 rev:18 rq:870452 version:0.28 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-cryptonite/ghc-cryptonite.changes 2020-12-22 11:38:17.145429301 +0100 +++ /work/SRC/openSUSE:Factory/.ghc-cryptonite.new.28504/ghc-cryptonite.changes 2021-02-16 22:45:29.774346477 +0100 @@ -1,0 +2,9 @@ +Wed Jan 27 19:35:26 UTC 2021 - [email protected] + +- Update cryptonite to version 0.28. + ## 0.28 + + * Add hash constant time capability + * Prevent possible overflow during hashing by hashing in 4GB chunks + +------------------------------------------------------------------- Old: ---- cryptonite-0.27.tar.gz New: ---- cryptonite-0.28.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-cryptonite.spec ++++++ --- /var/tmp/diff_new_pack.0iTizF/_old 2021-02-16 22:45:30.730347735 +0100 +++ /var/tmp/diff_new_pack.0iTizF/_new 2021-02-16 22:45:30.734347740 +0100 @@ -1,7 +1,7 @@ # # spec file for package ghc-cryptonite # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %global pkg_name cryptonite %bcond_with tests Name: ghc-%{pkg_name} -Version: 0.27 +Version: 0.28 Release: 0 Summary: Cryptography Primitives sink License: BSD-3-Clause ++++++ cryptonite-0.27.tar.gz -> cryptonite-0.28.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/CHANGELOG.md new/cryptonite-0.28/CHANGELOG.md --- old/cryptonite-0.27/CHANGELOG.md 2020-06-21 06:03:21.000000000 +0200 +++ new/cryptonite-0.28/CHANGELOG.md 2021-01-27 03:47:53.000000000 +0100 @@ -1,3 +1,8 @@ +## 0.28 + +* Add hash constant time capability +* Prevent possible overflow during hashing by hashing in 4GB chunks + ## 0.27 * Optimise AES GCM and CCM diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Cipher/RC4.hs new/cryptonite-0.28/Crypto/Cipher/RC4.hs --- old/cryptonite-0.27/Crypto/Cipher/RC4.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Cipher/RC4.hs 2021-01-16 10:05:08.000000000 +0100 @@ -30,6 +30,11 @@ import Crypto.Internal.Imports -- | The encryption state for RC4 +-- +-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal +-- layout is architecture dependent, may contain uninitialized data fragments, +-- and change in future versions. The bytearray should not be used as input to +-- cryptographic algorithms. newtype State = State ScrubbedBytes deriving (ByteArrayAccess,NFData) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Cipher/Types/AEAD.hs new/cryptonite-0.28/Crypto/Cipher/Types/AEAD.hs --- old/cryptonite-0.27/Crypto/Cipher/Types/AEAD.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Cipher/Types/AEAD.hs 2021-01-16 10:05:08.000000000 +0100 @@ -27,24 +27,24 @@ -- | Authenticated Encryption with Associated Data algorithms data AEAD cipher = forall st . AEAD { aeadModeImpl :: AEADModeImpl st - , aeadState :: st + , 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 +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 +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 +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 +aeadFinalize (AEAD impl st) = aeadImplFinalize impl st -- | Simple AEAD encryption aeadSimpleEncrypt :: (ByteArrayAccess aad, ByteArray ba) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/Algorithms.hs new/cryptonite-0.28/Crypto/Hash/Algorithms.hs --- old/cryptonite-0.27/Crypto/Hash/Algorithms.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/Algorithms.hs 2021-01-16 10:05:08.000000000 +0100 @@ -9,6 +9,7 @@ -- module Crypto.Hash.Algorithms ( HashAlgorithm + , HashAlgorithmPrefix -- * Hash algorithms , Blake2s_160(..) , Blake2s_224(..) @@ -54,7 +55,7 @@ , Whirlpool(..) ) where -import Crypto.Hash.Types (HashAlgorithm) +import Crypto.Hash.Types (HashAlgorithm, HashAlgorithmPrefix) import Crypto.Hash.Blake2s import Crypto.Hash.Blake2sp import Crypto.Hash.Blake2b diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/IO.hs new/cryptonite-0.28/Crypto/Hash/IO.hs --- old/cryptonite-0.27/Crypto/Hash/IO.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/IO.hs 2021-01-16 10:05:08.000000000 +0100 @@ -24,6 +24,11 @@ import Foreign.Ptr -- | A Mutable hash context +-- +-- This type is an instance of 'B.ByteArrayAccess' for debugging purpose. +-- Internal layout is architecture dependent, may contain uninitialized data +-- fragments, and change in future versions. The bytearray should not be used +-- as input to cryptographic algorithms. newtype MutableContext a = MutableContext B.Bytes deriving (B.ByteArrayAccess) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/MD5.hs new/cryptonite-0.28/Crypto/Hash/MD5.hs --- old/cryptonite-0.27/Crypto/Hash/MD5.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/MD5.hs 2021-01-16 10:05:08.000000000 +0100 @@ -34,6 +34,9 @@ hashInternalUpdate = c_md5_update hashInternalFinalize = c_md5_finalize +instance HashAlgorithmPrefix MD5 where + hashInternalFinalizePrefix = c_md5_finalize_prefix + foreign import ccall unsafe "cryptonite_md5_init" c_md5_init :: Ptr (Context a)-> IO () @@ -42,3 +45,6 @@ foreign import ccall unsafe "cryptonite_md5_finalize" c_md5_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () + +foreign import ccall "cryptonite_md5_finalize_prefix" + c_md5_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/SHA1.hs new/cryptonite-0.28/Crypto/Hash/SHA1.hs --- old/cryptonite-0.27/Crypto/Hash/SHA1.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/SHA1.hs 2021-01-16 10:05:08.000000000 +0100 @@ -34,6 +34,9 @@ hashInternalUpdate = c_sha1_update hashInternalFinalize = c_sha1_finalize +instance HashAlgorithmPrefix SHA1 where + hashInternalFinalizePrefix = c_sha1_finalize_prefix + foreign import ccall unsafe "cryptonite_sha1_init" c_sha1_init :: Ptr (Context a)-> IO () @@ -42,3 +45,6 @@ foreign import ccall unsafe "cryptonite_sha1_finalize" c_sha1_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () + +foreign import ccall "cryptonite_sha1_finalize_prefix" + c_sha1_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/SHA224.hs new/cryptonite-0.28/Crypto/Hash/SHA224.hs --- old/cryptonite-0.27/Crypto/Hash/SHA224.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/SHA224.hs 2021-01-16 10:05:08.000000000 +0100 @@ -34,6 +34,9 @@ hashInternalUpdate = c_sha224_update hashInternalFinalize = c_sha224_finalize +instance HashAlgorithmPrefix SHA224 where + hashInternalFinalizePrefix = c_sha224_finalize_prefix + foreign import ccall unsafe "cryptonite_sha224_init" c_sha224_init :: Ptr (Context a)-> IO () @@ -42,3 +45,6 @@ foreign import ccall unsafe "cryptonite_sha224_finalize" c_sha224_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () + +foreign import ccall "cryptonite_sha224_finalize_prefix" + c_sha224_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/SHA256.hs new/cryptonite-0.28/Crypto/Hash/SHA256.hs --- old/cryptonite-0.27/Crypto/Hash/SHA256.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/SHA256.hs 2021-01-16 10:05:08.000000000 +0100 @@ -34,6 +34,9 @@ hashInternalUpdate = c_sha256_update hashInternalFinalize = c_sha256_finalize +instance HashAlgorithmPrefix SHA256 where + hashInternalFinalizePrefix = c_sha256_finalize_prefix + foreign import ccall unsafe "cryptonite_sha256_init" c_sha256_init :: Ptr (Context a)-> IO () @@ -42,3 +45,6 @@ foreign import ccall unsafe "cryptonite_sha256_finalize" c_sha256_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () + +foreign import ccall "cryptonite_sha256_finalize_prefix" + c_sha256_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/SHA384.hs new/cryptonite-0.28/Crypto/Hash/SHA384.hs --- old/cryptonite-0.27/Crypto/Hash/SHA384.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/SHA384.hs 2021-01-16 10:05:08.000000000 +0100 @@ -34,6 +34,9 @@ hashInternalUpdate = c_sha384_update hashInternalFinalize = c_sha384_finalize +instance HashAlgorithmPrefix SHA384 where + hashInternalFinalizePrefix = c_sha384_finalize_prefix + foreign import ccall unsafe "cryptonite_sha384_init" c_sha384_init :: Ptr (Context a)-> IO () @@ -42,3 +45,6 @@ foreign import ccall unsafe "cryptonite_sha384_finalize" c_sha384_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () + +foreign import ccall "cryptonite_sha384_finalize_prefix" + c_sha384_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/SHA512.hs new/cryptonite-0.28/Crypto/Hash/SHA512.hs --- old/cryptonite-0.27/Crypto/Hash/SHA512.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/SHA512.hs 2021-01-16 10:05:08.000000000 +0100 @@ -34,6 +34,9 @@ hashInternalUpdate = c_sha512_update hashInternalFinalize = c_sha512_finalize +instance HashAlgorithmPrefix SHA512 where + hashInternalFinalizePrefix = c_sha512_finalize_prefix + foreign import ccall unsafe "cryptonite_sha512_init" c_sha512_init :: Ptr (Context a)-> IO () @@ -42,3 +45,6 @@ foreign import ccall unsafe "cryptonite_sha512_finalize" c_sha512_finalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () + +foreign import ccall "cryptonite_sha512_finalize_prefix" + c_sha512_finalize_prefix :: Ptr (Context a) -> Ptr Word8 -> Word32 -> Word32 -> Ptr (Digest a) -> IO () diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash/Types.hs new/cryptonite-0.28/Crypto/Hash/Types.hs --- old/cryptonite-0.27/Crypto/Hash/Types.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash/Types.hs 2021-01-16 10:05:08.000000000 +0100 @@ -14,6 +14,7 @@ {-# LANGUAGE TypeFamilies #-} module Crypto.Hash.Types ( HashAlgorithm(..) + , HashAlgorithmPrefix(..) , Context(..) , Digest(..) ) where @@ -59,12 +60,28 @@ -- | Finalize the context and set the digest raw memory to the right value hashInternalFinalize :: Ptr (Context a) -> Ptr (Digest a) -> IO () +-- | Hashing algorithms with a constant-time implementation. +class HashAlgorithm a => HashAlgorithmPrefix a where + -- | Update the context with the first N bytes of a buffer and finalize this + -- context. The code path executed is independent from N and depends only + -- on the complete buffer length. + hashInternalFinalizePrefix :: Ptr (Context a) + -> Ptr Word8 -> Word32 + -> Word32 + -> Ptr (Digest a) + -> IO () + {- hashContextGetAlgorithm :: HashAlgorithm a => Context a -> a hashContextGetAlgorithm = undefined -} -- | Represent a context for a given hash algorithm. +-- +-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal +-- layout is architecture dependent, may contain uninitialized data fragments, +-- and change in future versions. The bytearray should not be used as input to +-- cryptographic algorithms. newtype Context a = Context Bytes deriving (ByteArrayAccess,NFData) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Hash.hs new/cryptonite-0.28/Crypto/Hash.hs --- old/cryptonite-0.27/Crypto/Hash.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Hash.hs 2021-01-16 10:05:08.000000000 +0100 @@ -28,14 +28,17 @@ -- * Hash methods parametrized by algorithm , hashInitWith , hashWith + , hashPrefixWith -- * Hash methods , hashInit , hashUpdates , hashUpdate , hashFinalize + , hashFinalizePrefix , hashBlockSize , hashDigestSize , hash + , hashPrefix , hashlazy -- * Hash algorithms , module Crypto.Hash.Algorithms @@ -47,16 +50,20 @@ import Crypto.Internal.Compat (unsafeDoIO) import Crypto.Hash.Types import Crypto.Hash.Algorithms -import Foreign.Ptr (Ptr) +import Foreign.Ptr (Ptr, plusPtr) import Crypto.Internal.ByteArray (ByteArrayAccess) import qualified Crypto.Internal.ByteArray as B import qualified Data.ByteString.Lazy as L -import Data.Word (Word8) +import Data.Word (Word8, Word32) -- | Hash a strict bytestring into a digest. hash :: (ByteArrayAccess ba, HashAlgorithm a) => ba -> Digest a hash bs = hashFinalize $ hashUpdate hashInit bs +-- | Hash the first N bytes of a bytestring, with code path independent from N. +hashPrefix :: (ByteArrayAccess ba, HashAlgorithmPrefix a) => ba -> Int -> Digest a +hashPrefix = hashFinalizePrefix hashInit + -- | Hash a lazy bytestring into a digest. hashlazy :: HashAlgorithm a => L.ByteString -> Digest a hashlazy lbs = hashFinalize $ hashUpdates hashInit (L.toChunks lbs) @@ -81,9 +88,17 @@ hashUpdates c l | null ls = c | otherwise = Context $ B.copyAndFreeze c $ \(ctx :: Ptr (Context a)) -> - mapM_ (\b -> B.withByteArray b $ \d -> hashInternalUpdate ctx d (fromIntegral $ B.length b)) ls + mapM_ (\b -> B.withByteArray b (processBlocks ctx (B.length b))) ls where ls = filter (not . B.null) l + -- process the data in 4GB chunks to fit in uint32_t + processBlocks ctx bytesLeft dataPtr + | bytesLeft == 0 = return () + | otherwise = do + hashInternalUpdate ctx dataPtr (fromIntegral actuallyProcessed) + processBlocks ctx (bytesLeft - actuallyProcessed) (dataPtr `plusPtr` actuallyProcessed) + where + actuallyProcessed = min bytesLeft (fromIntegral (maxBound :: Word32)) -- | Finalize a context and return a digest. hashFinalize :: forall a . HashAlgorithm a @@ -94,6 +109,24 @@ ((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> hashInternalFinalize ctx dig return () +-- | Update the context with the first N bytes of a bytestring and return the +-- digest. The code path is independent from N but much slower than a normal +-- 'hashUpdate'. The function can be called for the last bytes of a message, in +-- order to exclude a variable padding, without leaking the padding length. The +-- begining of the message, never impacted by the padding, should preferably go +-- through 'hashUpdate' for better performance. +hashFinalizePrefix :: forall a ba . (HashAlgorithmPrefix a, ByteArrayAccess ba) + => Context a + -> ba + -> Int + -> Digest a +hashFinalizePrefix !c b len = + Digest $ B.allocAndFreeze (hashDigestSize (undefined :: a)) $ \(dig :: Ptr (Digest a)) -> do + ((!_) :: B.Bytes) <- B.copy c $ \(ctx :: Ptr (Context a)) -> + B.withByteArray b $ \d -> + hashInternalFinalizePrefix ctx d (fromIntegral $ B.length b) (fromIntegral len) dig + return () + -- | Initialize a new context for a specified hash algorithm hashInitWith :: HashAlgorithm alg => alg -> Context alg hashInitWith _ = hashInit @@ -102,6 +135,10 @@ hashWith :: (ByteArrayAccess ba, HashAlgorithm alg) => alg -> ba -> Digest alg hashWith _ = hash +-- | Run the 'hashPrefix' function but takes an explicit hash algorithm parameter +hashPrefixWith :: (ByteArrayAccess ba, HashAlgorithmPrefix alg) => alg -> ba -> Int -> Digest alg +hashPrefixWith _ = hashPrefix + -- | Try to transform a bytearray into a Digest of specific algorithm. -- -- If the digest is not the right size for the algorithm specified, then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/MAC/Poly1305.hs new/cryptonite-0.28/Crypto/MAC/Poly1305.hs --- old/cryptonite-0.27/Crypto/MAC/Poly1305.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/Crypto/MAC/Poly1305.hs 2021-01-16 10:05:08.000000000 +0100 @@ -33,6 +33,11 @@ import Crypto.Error -- | Poly1305 State +-- +-- This type is an instance of 'ByteArrayAccess' for debugging purpose. Internal +-- layout is architecture dependent, may contain uninitialized data fragments, +-- and change in future versions. The bytearray should not be used as input to +-- cryptographic algorithms. newtype State = State ScrubbedBytes deriving (ByteArrayAccess) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/Crypto/Random.hs new/cryptonite-0.28/Crypto/Random.hs --- old/cryptonite-0.27/Crypto/Random.hs 2020-02-14 01:10:29.000000000 +0100 +++ new/cryptonite-0.28/Crypto/Random.hs 2021-01-16 10:05:08.000000000 +0100 @@ -84,6 +84,9 @@ -- Note that the @Arbitrary@ instance provided by QuickCheck for 'Word64' does -- not have a uniform distribution. It is often better to use instead -- @arbitraryBoundedRandom@. +-- +-- System endianness impacts how the tuple is interpreted and therefore changes +-- the resulting DRG. drgNewTest :: (Word64, Word64, Word64, Word64, Word64) -> ChaChaDRG drgNewTest = initializeWords diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/README.md new/cryptonite-0.28/README.md --- old/cryptonite-0.27/README.md 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/README.md 2021-01-16 10:05:08.000000000 +0100 @@ -52,6 +52,10 @@ with the lack of autodetection feature builtin in .cabal file, it is left on the user to disable the aesni. See the [Disabling AESNI] section +On CentOS 7 the default C compiler includes intrinsic header files incompatible +with per-function target options. Solutions are to use GCC >= 4.9 or disable +flag *use_target_attributes* (see flag configuration examples below). + Disabling AESNI --------------- @@ -72,6 +76,13 @@ For help with cabal flags, see: [stackoverflow : is there a way to define flags for cabal](http://stackoverflow.com/questions/23523869/is-there-any-way-to-define-flags-for-cabal-dependencies) +Enabling PCLMULDQ +----------------- + +When the C toolchain supports it, enabling flag *support_pclmuldq* can bring +additional security and performance for AES GCM. A CPU with the necessary +instruction set will use an alternate implementation selected at runtime. + Links ----- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_align.h new/cryptonite-0.28/cbits/cryptonite_align.h --- old/cryptonite-0.27/cbits/cryptonite_align.h 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_align.h 2021-01-16 10:05:08.000000000 +0100 @@ -44,11 +44,21 @@ *((uint32_t *) dst) = cpu_to_le32(v); } +static inline void xor_le32_aligned(uint8_t *dst, const uint32_t v) +{ + *((uint32_t *) dst) ^= cpu_to_le32(v); +} + static inline void store_be32_aligned(uint8_t *dst, const uint32_t v) { *((uint32_t *) dst) = cpu_to_be32(v); } +static inline void xor_be32_aligned(uint8_t *dst, const uint32_t v) +{ + *((uint32_t *) dst) ^= cpu_to_be32(v); +} + static inline void store_le64_aligned(uint8_t *dst, const uint64_t v) { *((uint64_t *) dst) = cpu_to_le64(v); @@ -59,6 +69,11 @@ *((uint64_t *) dst) = cpu_to_be64(v); } +static inline void xor_be64_aligned(uint8_t *dst, const uint64_t v) +{ + *((uint64_t *) dst) ^= cpu_to_be64(v); +} + #ifdef UNALIGNED_ACCESS_OK #define load_le32(a) load_le32_aligned(a) #else @@ -70,20 +85,30 @@ #ifdef UNALIGNED_ACCESS_OK #define store_le32(a, b) store_le32_aligned(a, b) +#define xor_le32(a, b) xor_le32_aligned(a, b) #else static inline void store_le32(uint8_t *dst, const uint32_t v) { dst[0] = v; dst[1] = v >> 8; dst[2] = v >> 16; dst[3] = v >> 24; } +static inline void xor_le32(uint8_t *dst, const uint32_t v) +{ + dst[0] ^= v; dst[1] ^= v >> 8; dst[2] ^= v >> 16; dst[3] ^= v >> 24; +} #endif #ifdef UNALIGNED_ACCESS_OK #define store_be32(a, b) store_be32_aligned(a, b) +#define xor_be32(a, b) xor_be32_aligned(a, b) #else static inline void store_be32(uint8_t *dst, const uint32_t v) { dst[3] = v; dst[2] = v >> 8; dst[1] = v >> 16; dst[0] = v >> 24; } +static inline void xor_be32(uint8_t *dst, const uint32_t v) +{ + dst[3] ^= v; dst[2] ^= v >> 8; dst[1] ^= v >> 16; dst[0] ^= v >> 24; +} #endif #ifdef UNALIGNED_ACCESS_OK @@ -98,12 +123,18 @@ #ifdef UNALIGNED_ACCESS_OK #define store_be64(a, b) store_be64_aligned(a, b) +#define xor_be64(a, b) xor_be64_aligned(a, b) #else static inline void store_be64(uint8_t *dst, const uint64_t v) { dst[7] = v ; dst[6] = v >> 8 ; dst[5] = v >> 16; dst[4] = v >> 24; dst[3] = v >> 32; dst[2] = v >> 40; dst[1] = v >> 48; dst[0] = v >> 56; } +static inline void xor_be64(uint8_t *dst, const uint64_t v) +{ + dst[7] ^= v ; dst[6] ^= v >> 8 ; dst[5] ^= v >> 16; dst[4] ^= v >> 24; + dst[3] ^= v >> 32; dst[2] ^= v >> 40; dst[1] ^= v >> 48; dst[0] ^= v >> 56; +} #endif #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_hash_prefix.c new/cryptonite-0.28/cbits/cryptonite_hash_prefix.c --- old/cryptonite-0.27/cbits/cryptonite_hash_prefix.c 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_hash_prefix.c 2021-01-16 10:05:08.000000000 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2020 Olivier Ch??ron <[email protected]> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <cryptonite_hash_prefix.h> + +void CRYPTONITE_HASHED(finalize_prefix)(struct HASHED_LOWER(ctx) *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out) +{ + uint64_t bits[HASHED(BITS_ELEMS)]; + uint8_t *p = (uint8_t *) &bits; + uint32_t index, padidx, padlen, pos, out_mask; + static const uint32_t cut_off = HASHED(BLOCK_SIZE) - sizeof(bits); + + /* Make sure n <= len */ + n += (len - n) & constant_time_lt(len, n); + + /* Initial index, based on current context state */ + index = CRYPTONITE_HASHED(get_index)(ctx); + + /* Final size after n bytes */ + CRYPTONITE_HASHED(incr_sz)(ctx, bits, n); + + /* Padding index and length */ + padidx = CRYPTONITE_HASHED(get_index)(ctx); + padlen = HASHED(BLOCK_SIZE) + cut_off - padidx; + padlen -= HASHED(BLOCK_SIZE) & constant_time_lt(padidx, cut_off); + + /* Initialize buffers because we will XOR into them */ + memset(ctx->buf + index, 0, HASHED(BLOCK_SIZE) - index); + memset(out, 0, HASHED(DIGEST_SIZE)); + pos = 0; + + /* Iterate based on the full buffer length, regardless of n, and include + * the maximum overhead with padding and size bytes + */ + while (pos < len + HASHED(BLOCK_SIZE) + sizeof(bits)) { + uint8_t b; + + /* Take as many bytes from the input buffer as possible */ + if (pos < len) + b = *(data++) & (uint8_t) constant_time_lt(pos, n); + else + b = 0; + + /* First padding byte */ + b |= 0x80 & (uint8_t) constant_time_eq(pos, n); + + /* Size bytes are always at the end of a block */ + if (index >= cut_off) + b |= p[index - cut_off] & (uint8_t) constant_time_ge(pos, n + padlen); + + /* Store this byte into the buffer */ + ctx->buf[index++] ^= b; + pos++; + + /* Process a full block, at a boundary which is independent from n */ + if (index >= HASHED(BLOCK_SIZE)) { + index = 0; + HASHED_LOWER(do_chunk)(ctx, (void *) ctx->buf); + memset(ctx->buf, 0, HASHED(BLOCK_SIZE)); + + /* Try to store the result: this is a no-op except when we reach the + * actual size based on n, more iterations may continue after that + * when len is really larger + */ + out_mask = constant_time_eq(pos, n + padlen + sizeof(bits)); + CRYPTONITE_HASHED(select_digest)(ctx, out, out_mask); + } + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_hash_prefix.h new/cryptonite-0.28/cbits/cryptonite_hash_prefix.h --- old/cryptonite-0.27/cbits/cryptonite_hash_prefix.h 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_hash_prefix.h 2021-01-16 10:05:08.000000000 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 Olivier Ch??ron <[email protected]> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CRYPTONITE_HASH_PREFIX_H +#define CRYPTONITE_HASH_PREFIX_H + +#include <stdint.h> + +static inline uint32_t constant_time_msb(uint32_t a) +{ + return 0 - (a >> 31); +} + +static inline uint32_t constant_time_lt(uint32_t a, uint32_t b) +{ + return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +static inline uint32_t constant_time_ge(uint32_t a, uint32_t b) +{ + return ~constant_time_lt(a, b); +} + +static inline uint32_t constant_time_is_zero(uint32_t a) +{ + return constant_time_msb(~a & (a - 1)); +} + +static inline uint32_t constant_time_eq(uint32_t a, uint32_t b) +{ + return constant_time_is_zero(a ^ b); +} + +static inline uint64_t constant_time_msb_64(uint64_t a) +{ + return 0 - (a >> 63); +} + +static inline uint64_t constant_time_lt_64(uint64_t a, uint64_t b) +{ + return constant_time_msb_64(a ^ ((a ^ b) | ((a - b) ^ b))); +} + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_md5.c new/cryptonite-0.28/cbits/cryptonite_md5.c --- old/cryptonite-0.27/cbits/cryptonite_md5.c 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_md5.c 2021-01-16 10:05:08.000000000 +0100 @@ -185,3 +185,30 @@ store_le32(out+ 8, ctx->h[2]); store_le32(out+12, ctx->h[3]); } + +#define HASHED(m) MD5_##m +#define HASHED_LOWER(m) md5_##m +#define CRYPTONITE_HASHED(m) cryptonite_md5_##m +#define MD5_BLOCK_SIZE 64 +#define MD5_BITS_ELEMS 1 + +static inline uint32_t cryptonite_md5_get_index(const struct md5_ctx *ctx) +{ + return (uint32_t) (ctx->sz & 0x3f); +} + +static inline void cryptonite_md5_incr_sz(struct md5_ctx *ctx, uint64_t *bits, uint32_t n) +{ + ctx->sz += n; + *bits = cpu_to_le64(ctx->sz << 3); +} + +static inline void cryptonite_md5_select_digest(const struct md5_ctx *ctx, uint8_t *out, uint32_t out_mask) +{ + xor_le32(out , ctx->h[0] & out_mask); + xor_le32(out+ 4, ctx->h[1] & out_mask); + xor_le32(out+ 8, ctx->h[2] & out_mask); + xor_le32(out+12, ctx->h[3] & out_mask); +} + +#include <cryptonite_hash_prefix.c> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_md5.h new/cryptonite-0.28/cbits/cryptonite_md5.h --- old/cryptonite-0.27/cbits/cryptonite_md5.h 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_md5.h 2021-01-16 10:05:08.000000000 +0100 @@ -39,5 +39,6 @@ void cryptonite_md5_init(struct md5_ctx *ctx); void cryptonite_md5_update(struct md5_ctx *ctx, const uint8_t *data, uint32_t len); void cryptonite_md5_finalize(struct md5_ctx *ctx, uint8_t *out); +void cryptonite_md5_finalize_prefix(struct md5_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_sha1.c new/cryptonite-0.28/cbits/cryptonite_sha1.c --- old/cryptonite-0.27/cbits/cryptonite_sha1.c 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_sha1.c 2021-01-16 10:05:08.000000000 +0100 @@ -216,3 +216,31 @@ store_be32(out+12, ctx->h[3]); store_be32(out+16, ctx->h[4]); } + +#define HASHED(m) SHA1_##m +#define HASHED_LOWER(m) sha1_##m +#define CRYPTONITE_HASHED(m) cryptonite_sha1_##m +#define SHA1_BLOCK_SIZE 64 +#define SHA1_BITS_ELEMS 1 + +static inline uint32_t cryptonite_sha1_get_index(const struct sha1_ctx *ctx) +{ + return (uint32_t) (ctx->sz & 0x3f); +} + +static inline void cryptonite_sha1_incr_sz(struct sha1_ctx *ctx, uint64_t *bits, uint32_t n) +{ + ctx->sz += n; + *bits = cpu_to_be64(ctx->sz << 3); +} + +static inline void cryptonite_sha1_select_digest(const struct sha1_ctx *ctx, uint8_t *out, uint32_t out_mask) +{ + xor_be32(out , ctx->h[0] & out_mask); + xor_be32(out+ 4, ctx->h[1] & out_mask); + xor_be32(out+ 8, ctx->h[2] & out_mask); + xor_be32(out+12, ctx->h[3] & out_mask); + xor_be32(out+16, ctx->h[4] & out_mask); +} + +#include <cryptonite_hash_prefix.c> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_sha1.h new/cryptonite-0.28/cbits/cryptonite_sha1.h --- old/cryptonite-0.27/cbits/cryptonite_sha1.h 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_sha1.h 2021-01-16 10:05:08.000000000 +0100 @@ -41,5 +41,6 @@ void cryptonite_sha1_init(struct sha1_ctx *ctx); void cryptonite_sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len); void cryptonite_sha1_finalize(struct sha1_ctx *ctx, uint8_t *out); +void cryptonite_sha1_finalize_prefix(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_sha256.c new/cryptonite-0.28/cbits/cryptonite_sha256.c --- old/cryptonite-0.27/cbits/cryptonite_sha256.c 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_sha256.c 2021-01-16 10:05:08.000000000 +0100 @@ -161,6 +161,14 @@ memcpy(out, intermediate, SHA224_DIGEST_SIZE); } +void cryptonite_sha224_finalize_prefix(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out) +{ + uint8_t intermediate[SHA256_DIGEST_SIZE]; + + cryptonite_sha256_finalize_prefix(ctx, data, len, n, intermediate); + memcpy(out, intermediate, SHA224_DIGEST_SIZE); +} + void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out) { static uint8_t padding[64] = { 0x80, }; @@ -182,3 +190,29 @@ for (i = 0; i < 8; i++) store_be32(out+4*i, ctx->h[i]); } + +#define HASHED(m) SHA256_##m +#define HASHED_LOWER(m) sha256_##m +#define CRYPTONITE_HASHED(m) cryptonite_sha256_##m +#define SHA256_BLOCK_SIZE 64 +#define SHA256_BITS_ELEMS 1 + +static inline uint32_t cryptonite_sha256_get_index(const struct sha256_ctx *ctx) +{ + return (uint32_t) (ctx->sz & 0x3f); +} + +static inline void cryptonite_sha256_incr_sz(struct sha256_ctx *ctx, uint64_t *bits, uint32_t n) +{ + ctx->sz += n; + *bits = cpu_to_be64(ctx->sz << 3); +} + +static inline void cryptonite_sha256_select_digest(const struct sha256_ctx *ctx, uint8_t *out, uint32_t out_mask) +{ + uint32_t i; + for (i = 0; i < 8; i++) + xor_be32(out+4*i, ctx->h[i] & out_mask); +} + +#include <cryptonite_hash_prefix.c> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_sha256.h new/cryptonite-0.28/cbits/cryptonite_sha256.h --- old/cryptonite-0.27/cbits/cryptonite_sha256.h 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_sha256.h 2021-01-16 10:05:08.000000000 +0100 @@ -47,9 +47,11 @@ void cryptonite_sha224_init(struct sha224_ctx *ctx); void cryptonite_sha224_update(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len); void cryptonite_sha224_finalize(struct sha224_ctx *ctx, uint8_t *out); +void cryptonite_sha224_finalize_prefix(struct sha224_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); void cryptonite_sha256_init(struct sha256_ctx *ctx); void cryptonite_sha256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len); void cryptonite_sha256_finalize(struct sha256_ctx *ctx, uint8_t *out); +void cryptonite_sha256_finalize_prefix(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_sha512.c new/cryptonite-0.28/cbits/cryptonite_sha512.c --- old/cryptonite-0.27/cbits/cryptonite_sha512.c 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_sha512.c 2021-01-16 10:05:08.000000000 +0100 @@ -180,6 +180,14 @@ memcpy(out, intermediate, SHA384_DIGEST_SIZE); } +void cryptonite_sha384_finalize_prefix(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out) +{ + uint8_t intermediate[SHA512_DIGEST_SIZE]; + + cryptonite_sha512_finalize_prefix(ctx, data, len, n, intermediate); + memcpy(out, intermediate, SHA384_DIGEST_SIZE); +} + void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out) { static uint8_t padding[128] = { 0x80, }; @@ -203,6 +211,38 @@ store_be64(out+8*i, ctx->h[i]); } +#define HASHED(m) SHA512_##m +#define HASHED_LOWER(m) sha512_##m +#define CRYPTONITE_HASHED(m) cryptonite_sha512_##m +#define SHA512_BLOCK_SIZE 128 +#define SHA512_BITS_ELEMS 2 + +#include <cryptonite_hash_prefix.h> + +static inline uint32_t cryptonite_sha512_get_index(const struct sha512_ctx *ctx) +{ + return (uint32_t) (ctx->sz[0] & 0x7f); +} + +static inline void cryptonite_sha512_incr_sz(struct sha512_ctx *ctx, uint64_t *bits, uint32_t n) +{ + ctx->sz[0] += n; + ctx->sz[1] += 1 & constant_time_lt_64(ctx->sz[0], n); + bits[0] = cpu_to_be64((ctx->sz[1] << 3 | ctx->sz[0] >> 61)); + bits[1] = cpu_to_be64((ctx->sz[0] << 3)); +} + +static inline void cryptonite_sha512_select_digest(const struct sha512_ctx *ctx, uint8_t *out, uint32_t out_mask) +{ + uint32_t i; + uint64_t out_mask_64 = out_mask; + out_mask_64 |= out_mask_64 << 32; + for (i = 0; i < 8; i++) + xor_be64(out+8*i, ctx->h[i] & out_mask_64); +} + +#include <cryptonite_hash_prefix.c> + #include <stdio.h> void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cbits/cryptonite_sha512.h new/cryptonite-0.28/cbits/cryptonite_sha512.h --- old/cryptonite-0.27/cbits/cryptonite_sha512.h 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/cbits/cryptonite_sha512.h 2021-01-16 10:05:08.000000000 +0100 @@ -46,10 +46,12 @@ void cryptonite_sha384_init(struct sha384_ctx *ctx); void cryptonite_sha384_update(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len); void cryptonite_sha384_finalize(struct sha384_ctx *ctx, uint8_t *out); +void cryptonite_sha384_finalize_prefix(struct sha384_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); void cryptonite_sha512_init(struct sha512_ctx *ctx); void cryptonite_sha512_update(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len); void cryptonite_sha512_finalize(struct sha512_ctx *ctx, uint8_t *out); +void cryptonite_sha512_finalize_prefix(struct sha512_ctx *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out); /* only multiples of 8 are supported as valid t values */ void cryptonite_sha512t_init(struct sha512_ctx *ctx, uint32_t hashlen); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/cryptonite.cabal new/cryptonite-0.28/cryptonite.cabal --- old/cryptonite-0.27/cryptonite.cabal 2020-06-21 06:03:37.000000000 +0200 +++ new/cryptonite-0.28/cryptonite.cabal 2021-01-16 10:08:21.000000000 +0100 @@ -1,5 +1,5 @@ Name: cryptonite -version: 0.27 +version: 0.28 Synopsis: Cryptography Primitives sink Description: A repository of cryptographic primitives. @@ -57,6 +57,7 @@ cbits/argon2/*.h cbits/argon2/*.c cbits/aes/x86ni_impl.c + cbits/cryptonite_hash_prefix.c tests/*.hs source-repository head diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.27/tests/Hash.hs new/cryptonite-0.28/tests/Hash.hs --- old/cryptonite-0.27/tests/Hash.hs 2019-12-17 01:55:14.000000000 +0100 +++ new/cryptonite-0.28/tests/Hash.hs 2021-01-16 10:05:08.000000000 +0100 @@ -221,6 +221,24 @@ runhashinc (HashAlg hashAlg) v = B.convertToBase B.Base16 $ hashinc $ v where hashinc = hashFinalize . foldl hashUpdate (hashInitWith hashAlg) +data HashPrefixAlg = forall alg . HashAlgorithmPrefix alg => HashPrefixAlg alg + +expectedPrefix :: [ (String, HashPrefixAlg) ] +expectedPrefix = + [ ("MD5", HashPrefixAlg MD5) + , ("SHA1", HashPrefixAlg SHA1) + , ("SHA224", HashPrefixAlg SHA224) + , ("SHA256", HashPrefixAlg SHA256) + , ("SHA384", HashPrefixAlg SHA384) + , ("SHA512", HashPrefixAlg SHA512) + ] + +runhashpfx :: HashPrefixAlg -> ByteString -> ByteString +runhashpfx (HashPrefixAlg hashAlg) v = B.convertToBase B.Base16 $ hashWith hashAlg v + +runhashpfxpfx :: HashPrefixAlg -> ByteString -> Int -> ByteString +runhashpfxpfx (HashPrefixAlg hashAlg) v len = B.convertToBase B.Base16 $ hashPrefixWith hashAlg v len + makeTestAlg (name, hashAlg, results) = testGroup name $ concatMap maketest (zip3 is vectors results) where @@ -236,6 +254,19 @@ runhash hashAlg inp `propertyEq` runhashinc hashAlg (chunkS ckLen inp) ] +makeTestPrefix (hashName, hashAlg) = + [ testProperty hashName $ \(ArbitraryBS0_2901 inp) (Int0_2901 len) -> + runhashpfx hashAlg (B.take len inp) `propertyEq` runhashpfxpfx hashAlg inp len + ] + +makeTestHybrid (hashName, HashPrefixAlg alg) = + [ testProperty hashName $ \(ArbitraryBS0_2901 start) (ArbitraryBS0_2901 end) -> do + len <- choose (0, B.length end) + let ref = hashWith alg (start `B.append` B.take len end) + hyb = hashFinalizePrefix (hashUpdate (hashInitWith alg) start) end len + return (ref `propertyEq` hyb) + ] + -- SHAKE128 truncation example with expected byte at final position -- <https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/ShakeTruncation.pdf> shake128TruncationBytes = [0x01, 0x03, 0x07, 0x0f, 0x0f, 0x2f, 0x6f, 0x6f] @@ -253,6 +284,8 @@ tests = testGroup "hash" [ testGroup "KATs" (map makeTestAlg expected) , testGroup "Chunking" (concatMap makeTestChunk expected) + , testGroup "Prefix" (concatMap makeTestPrefix expectedPrefix) + , testGroup "Hybrid" (concatMap makeTestHybrid expectedPrefix) , testGroup "Truncating" [ testGroup "SHAKE128" (zipWith makeTestSHAKE128Truncation [1..] shake128TruncationBytes)
