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)

Reply via email to