Hello community, here is the log from the commit of package ghc-cryptonite for openSUSE:Factory checked in at 2016-10-19 13:03:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-cryptonite (Old) and /work/SRC/openSUSE:Factory/.ghc-cryptonite.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-cryptonite" Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-cryptonite/ghc-cryptonite.changes 2016-07-21 08:05:48.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-cryptonite.new/ghc-cryptonite.changes 2016-10-19 13:03:30.000000000 +0200 @@ -1,0 +2,5 @@ +Thu Sep 15 06:34:53 UTC 2016 - psim...@suse.com + +- Update to version 0.19 revision 0 with cabal2obs. + +------------------------------------------------------------------- Old: ---- cryptonite-0.15.tar.gz New: ---- cryptonite-0.19.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-cryptonite.spec ++++++ --- /var/tmp/diff_new_pack.xqhVDd/_old 2016-10-19 13:03:31.000000000 +0200 +++ /var/tmp/diff_new_pack.xqhVDd/_new 2016-10-19 13:03:31.000000000 +0200 @@ -19,15 +19,14 @@ %global pkg_name cryptonite %bcond_with tests Name: ghc-%{pkg_name} -Version: 0.15 +Version: 0.19 Release: 0 Summary: Cryptography Primitives sink License: BSD-3-Clause -Group: System/Libraries +Group: Development/Languages/Other Url: https://hackage.haskell.org/package/%{pkg_name} Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz BuildRequires: ghc-Cabal-devel -# Begin cabal-rpm deps: BuildRequires: ghc-bytestring-devel BuildRequires: ghc-deepseq-devel BuildRequires: ghc-memory-devel @@ -40,7 +39,6 @@ BuildRequires: ghc-tasty-kat-devel BuildRequires: ghc-tasty-quickcheck-devel %endif -# End cabal-rpm deps %description A repository of cryptographic primitives. @@ -52,7 +50,7 @@ * MAC: HMAC, Poly1305 -* Assymmetric crypto: DSA, RSA, DH, ECDH, ECDSA, ECC, Curve25519, Ed25519 +* Asymmetric crypto: DSA, RSA, DH, ECDH, ECDSA, ECC, Curve25519, Ed25519, Ed448 * Key Derivation Function: PBKDF2, Scrypt, HKDF @@ -67,6 +65,8 @@ Evaluate the security related to your requirements before using. +Read "Crypto.Tutorial" for a quick start guide. + %package devel Summary: Haskell %{pkg_name} library development files Group: Development/Libraries/Other @@ -81,21 +81,15 @@ %prep %setup -q -n %{pkg_name}-%{version} - %build -%define cabal_configure_options -f"-support_aesni -support_rdrand -support_blake2_sse" +%define cabal_configure_options -f-support_aesni -f-support_rdrand -f-support_blake2_sse %ghc_lib_build - %install %ghc_lib_install - %check -%if %{with tests} -%{cabal} test -%endif - +%cabal_test %post devel %ghc_pkg_recache ++++++ cryptonite-0.15.tar.gz -> cryptonite-0.19.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/CHANGELOG.md new/cryptonite-0.19/CHANGELOG.md --- old/cryptonite-0.15/CHANGELOG.md 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/CHANGELOG.md 2016-08-12 08:14:25.000000000 +0200 @@ -1,3 +1,25 @@ +## 0.19 + +* Add tutorial (Yann Esposito) +* Derive Show instance for better interaction with Show pretty printer (Eric Mertens) + +## 0.18 + +* Re-used standard rdrand instructions instead of bytedump of rdrand instruction +* Improvement to F2m, including lots of tests (Andrew Lelechenko) + +## 0.17 + +* Add Miyaguchi-Preneel construction (Kei Hibino) +* Fix buffer length in scrypt (Luke Taylor) +* build fixes for i686 and arm related to rdrand + +## 0.16 + +* Fix basepoint for Ed448 + +* Enable 64-bit Curve25519 implementation + ## 0.15 * Fix serialization of DH and ECDH diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/Cipher/Blowfish/Primitive.hs new/cryptonite-0.19/Crypto/Cipher/Blowfish/Primitive.hs --- old/cryptonite-0.15/Crypto/Cipher/Blowfish/Primitive.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/Cipher/Blowfish/Primitive.hs 2016-08-12 08:14:25.000000000 +0200 @@ -79,7 +79,9 @@ -- Cost must be between 4 and 31 inclusive -- See <https://www.usenix.org/conference/1999-usenix-annual-technical-conference/future-adaptable-password-scheme> eksBlowfish :: (ByteArrayAccess salt, ByteArrayAccess password) => Int -> salt -> password -> Context -eksBlowfish cost salt key = makeKeySchedule key (Just (salt, cost)) +eksBlowfish cost salt key + | B.length salt /= 16 = error "bcrypt salt must be 16 bytes" + | otherwise = makeKeySchedule key (Just (salt, cost)) coreCrypto :: Context -> Word64 -> Word64 coreCrypto (BF p s0 s1 s2 s3) input = doRound input 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/ConstructHash/MiyaguchiPreneel.hs new/cryptonite-0.19/Crypto/ConstructHash/MiyaguchiPreneel.hs --- old/cryptonite-0.15/Crypto/ConstructHash/MiyaguchiPreneel.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.19/Crypto/ConstructHash/MiyaguchiPreneel.hs 2016-08-12 08:14:25.000000000 +0200 @@ -0,0 +1,68 @@ +-- | +-- Module : Crypto.ConstructHash.MiyaguchiPreneel +-- License : BSD-style +-- Maintainer : Kei Hibino <ex8k.hib...@gmail.com> +-- Stability : experimental +-- Portability : unknown +-- +-- provide the hash function construction method from block cipher +-- <https://en.wikipedia.org/wiki/One-way_compression_function> +-- +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +module Crypto.ConstructHash.MiyaguchiPreneel + ( compute, compute' + , MiyaguchiPreneel + ) where + +import Data.List (foldl') + +import Crypto.Data.Padding (pad, Format (ZERO)) +import Crypto.Cipher.Types +import Crypto.Error (throwCryptoError) +import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, Bytes) +import qualified Crypto.Internal.ByteArray as B + + +newtype MiyaguchiPreneel a = MP Bytes + deriving (ByteArrayAccess) + +instance Eq (MiyaguchiPreneel a) where + MP b1 == MP b2 = B.constEq b1 b2 + + +-- | Compute Miyaguchi-Preneel one way compress using the supplied block cipher. +compute' :: (ByteArrayAccess bin, BlockCipher cipher) + => (Bytes -> cipher) -- ^ key build function to compute Miyaguchi-Preneel. care about block-size and key-size + -> bin -- ^ input message + -> MiyaguchiPreneel cipher -- ^ output tag +compute' g = MP . foldl' (step $ g) (B.replicate bsz 0) . chunks . pad (ZERO bsz) . B.convert + where + bsz = blockSize ( g B.empty {- dummy to get block size -} ) + chunks msg + | B.null msg = [] + | otherwise = (hd :: Bytes) : chunks tl + where + (hd, tl) = B.splitAt bsz msg + +-- | Compute Miyaguchi-Preneel one way compress using the infered block cipher. +-- Only safe when KEY-SIZE equals to BLOCK-SIZE. +-- +-- Simple usage /mp' msg :: MiyaguchiPreneel AES128/ +compute :: (ByteArrayAccess bin, BlockCipher cipher) + => bin -- ^ input message + -> MiyaguchiPreneel cipher -- ^ output tag +compute = compute' $ throwCryptoError . cipherInit + +-- | computation step of Miyaguchi-Preneel +step :: (ByteArray ba, BlockCipher k) + => (ba -> k) + -> ba + -> ba + -> ba +step g iv msg = + ecbEncrypt k msg `bxor` iv `bxor` msg + where + k = g iv + +bxor :: ByteArray ba => ba -> ba -> ba +bxor = B.xor diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/Data/Padding.hs new/cryptonite-0.19/Crypto/Data/Padding.hs --- old/cryptonite-0.15/Crypto/Data/Padding.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/Data/Padding.hs 2016-08-12 08:14:25.000000000 +0200 @@ -21,6 +21,7 @@ data Format = PKCS5 -- ^ PKCS5: PKCS7 with hardcoded size of 8 | PKCS7 Int -- ^ PKCS7 with padding size between 1 and 255 + | ZERO Int -- ^ zero padding with block size deriving (Show, Eq) -- | Apply some pad to a bytearray @@ -30,6 +31,15 @@ where paddingString = B.replicate paddingByte (fromIntegral paddingByte) paddingByte = sz - (B.length bin `mod` sz) +pad (ZERO sz) bin = bin `B.append` paddingString + where + paddingString = B.replicate paddingSz 0 + paddingSz + | len == 0 = sz + | m == 0 = 0 + | otherwise = sz - m + m = len `mod` sz + len = B.length bin -- | Try to remove some padding from a bytearray. unpad :: ByteArray byteArray => Format -> byteArray -> Maybe byteArray @@ -46,3 +56,10 @@ paddingSz = fromIntegral paddingByte (content, padding) = B.splitAt (len - paddingSz) bin paddingWitness = B.replicate paddingSz paddingByte :: Bytes +unpad (ZERO sz) bin + | len == 0 = Nothing + | (len `mod` sz) /= 0 = Nothing + | B.index bin (len - 1) /= 0 = Just bin + | otherwise = Nothing + where + len = B.length bin diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/Error/Types.hs new/cryptonite-0.19/Crypto/Error/Types.hs --- old/cryptonite-0.15/Crypto/Error/Types.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/Error/Types.hs 2016-08-12 08:14:25.000000000 +0200 @@ -52,10 +52,8 @@ data CryptoFailable a = CryptoPassed a | CryptoFailed CryptoError + deriving (Show) -instance Show a => Show (CryptoFailable a) where - show (CryptoPassed a) = "CryptoPassed " ++ show a - show (CryptoFailed err) = "CryptoFailed " ++ show err instance Eq a => Eq (CryptoFailable a) where (==) (CryptoPassed a) (CryptoPassed b) = a == b (==) (CryptoFailed e1) (CryptoFailed e2) = e1 == e2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/KDF/Scrypt.hs new/cryptonite-0.19/Crypto/KDF/Scrypt.hs --- old/cryptonite-0.15/Crypto/KDF/Scrypt.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/KDF/Scrypt.hs 2016-08-12 08:14:25.000000000 +0200 @@ -53,7 +53,7 @@ let b = PBKDF2.generate prf (PBKDF2.Parameters 1 intLen) password salt :: B.Bytes newSalt <- B.copy b $ \bPtr -> allocaBytesAligned (128*(fromIntegral $ n params)*(r params)) 8 $ \v -> - allocaBytesAligned (256*r params) 8 $ \xy -> do + allocaBytesAligned (256*r params + 64) 8 $ \xy -> do forM_ [0..(p params-1)] $ \i -> ccryptonite_scrypt_smix (bPtr `plusPtr` (i * 128 * (r params))) (fromIntegral $ r params) (n params) v xy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/Number/F2m.hs new/cryptonite-0.19/Crypto/Number/F2m.hs --- old/cryptonite-0.15/Crypto/Number/F2m.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/Number/F2m.hs 2016-08-12 08:14:25.000000000 +0200 @@ -9,100 +9,133 @@ -- not optimal and it doesn't provide protection against timing -- attacks. The 'm' parameter is implicitly derived from the irreducible -- polynomial where applicable. + module Crypto.Number.F2m ( BinaryPolynomial , addF2m , mulF2m + , squareF2m' , squareF2m , modF2m , invF2m , divF2m ) where -import Data.Bits ((.&.),(.|.),xor,shift,testBit) -import Crypto.Number.Basic +import Data.Bits (xor, shift, testBit, setBit) +import Data.List import Crypto.Internal.Imports +import Crypto.Number.Basic -- | Binary Polynomial represented by an integer type BinaryPolynomial = Integer --- | Addition over F₂m. This is just a synonym of 'xor'. -addF2m :: Integer -> Integer -> Integer +-- | Addition over F₂m. This is just a synonym of 'xor'. +addF2m :: Integer + -> Integer + -> Integer addF2m = xor {-# INLINE addF2m #-} --- | Binary polynomial reduction modulo using long division algorithm. -modF2m :: BinaryPolynomial -- ^ Irreducible binary polynomial - -> Integer -> Integer -modF2m fx = go - where - lfx = log2 fx - go n | s == 0 = n `xor` fx - | s < 0 = n - | otherwise = go $ n `xor` shift fx s +-- | Reduction by modulo over F₂m. +-- +-- This function is undefined for negative arguments, because their bit +-- representation is platform-dependent. Zero modulus is also prohibited. +modF2m :: BinaryPolynomial -- ^ Modulus + -> Integer + -> Integer +modF2m fx i + | fx < 0 || i < 0 = error "modF2m: negative number represent no binary polynomial" + | fx == 0 = error "modF2m: cannot divide by zero polynomial" + | fx == 1 = 0 + | otherwise = go i where - s = log2 n - lfx + lfx = log2 fx + go n | s == 0 = n `addF2m` fx + | s < 0 = n + | otherwise = go $ n `addF2m` shift fx s + where s = log2 n - lfx {-# INLINE modF2m #-} -- | Multiplication over F₂m. -- --- n1 * n2 (in F(2^m)) -mulF2m :: BinaryPolynomial -- ^ Irreducible binary polynomial - -> Integer -> Integer -> Integer -mulF2m fx n1 n2 = modF2m fx - $ go (if n2 `mod` 2 == 1 then n1 else 0) (log2 n2) - where - go n s | s == 0 = n - | otherwise = if testBit n2 s - then go (n `xor` shift n1 s) (s - 1) - else go n (s - 1) +-- This function is undefined for negative arguments, because their bit +-- representation is platform-dependent. Zero modulus is also prohibited. +mulF2m :: BinaryPolynomial -- ^ Modulus + -> Integer + -> Integer + -> Integer +mulF2m fx n1 n2 + | fx < 0 + || n1 < 0 + || n2 < 0 = error "mulF2m: negative number represent no binary binary polynomial" + | fx == 0 = error "modF2m: cannot multiply modulo zero polynomial" + | otherwise = modF2m fx $ go (if n2 `mod` 2 == 1 then n1 else 0) (log2 n2) + where + go n s | s == 0 = n + | otherwise = if testBit n2 s + then go (n `addF2m` shift n1 s) (s - 1) + else go n (s - 1) {-# INLINABLE mulF2m #-} -- | Squaring over F₂m. --- TODO: This is still slower than @mulF2m@. - --- Multiplication table? C? -squareF2m :: BinaryPolynomial -- ^ Irreducible binary polynomial - -> Integer -> Integer -squareF2m fx = modF2m fx . square +-- +-- This function is undefined for negative arguments, because their bit +-- representation is platform-dependent. Zero modulus is also prohibited. +squareF2m :: BinaryPolynomial -- ^ Modulus + -> Integer + -> Integer +squareF2m fx = modF2m fx . squareF2m' {-# INLINE squareF2m #-} -square :: Integer -> Integer -square n1 = go n1 ln1 +-- | Squaring over F₂m without reduction by modulo. +-- +-- The implementation utilizes the fact that for binary polynomial S(x) we have +-- S(x)^2 = S(x^2). In other words, insert a zero bit between every bits of argument: 1101 -> 1010001. +-- +-- This function is undefined for negative arguments, because their bit +-- representation is platform-dependent. +squareF2m' :: Integer + -> Integer +squareF2m' n + | n < 0 = error "mulF2m: negative number represent no binary binary polynomial" + | otherwise = foldl' (\acc s -> if testBit n s then setBit acc (2 * s) else acc) 0 [0 .. log2 n] +{-# INLINE squareF2m' #-} + +-- | Extended GCD algorithm for polynomials. For @a@ and @b@ returns @(g, u, v)@ such that @a * u + b * v == g@. +-- +-- Reference: https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#B.C3.A9zout.27s_identity_and_extended_GCD_algorithm +gcdF2m :: Integer + -> Integer + -> (Integer, Integer, Integer) +gcdF2m a b = go (a, b, 1, 0, 0, 1) where - ln1 = log2 n1 - go n s | s == 0 = n - | otherwise = go (x .|. y) (s - 1) - where - x = shift (shift n (2 * (s - ln1) - 1)) (2 * (ln1 - s) + 2) - y = n .&. (shift 1 (2 * (ln1 - s) + 1) - 1) -{-# INLINE square #-} - --- | Inversion of @n over F₂m using extended Euclidean algorithm. --- --- If @n doesn't have an inverse, Nothing is returned. -invF2m :: BinaryPolynomial -- ^ Irreducible binary polynomial - -> Integer -> Maybe Integer -invF2m _ 0 = Nothing -invF2m fx n - | n >= fx = Nothing - | otherwise = go n fx 1 0 - where - go u v g1 g2 - | u == 1 = Just $ modF2m fx g1 - | j < 0 = go u (v `xor` shift u (-j)) g1 (g2 `xor` shift g1 (-j)) - | otherwise = go (u `xor` shift v j) v (g1 `xor` shift g2 j) g2 - where - j = log2 u - log2 v + go (g, 0, u, _, v, _) + = (g, u, v) + go (r0, r1, s0, s1, t0, t1) + = go (r1, r0 `addF2m` shift r1 j, s1, s0 `addF2m` shift s1 j, t1, t0 `addF2m` shift t1 j) + where j = max 0 (log2 r0 - log2 r1) + +-- | Modular inversion over F₂m. +-- If @n@ doesn't have an inverse, 'Nothing' is returned. +-- +-- This function is undefined for negative arguments, because their bit +-- representation is platform-dependent. Zero modulus is also prohibited. +invF2m :: BinaryPolynomial -- ^ Modulus + -> Integer + -> Maybe Integer +invF2m fx n = if g == 1 then Just (modF2m fx u) else Nothing + where + (g, u, _) = gcdF2m n fx {-# INLINABLE invF2m #-} -- | Division over F₂m. If the dividend doesn't have an inverse it returns -- 'Nothing'. -- --- Compute n1 / n2 -divF2m :: BinaryPolynomial -- ^ Irreducible binary polynomial - -> Integer -- ^ Dividend - -> Integer -- ^ Quotient - -> Maybe Integer +-- This function is undefined for negative arguments, because their bit +-- representation is platform-dependent. Zero modulus is also prohibited. +divF2m :: BinaryPolynomial -- ^ Modulus + -> Integer -- ^ Dividend + -> Integer -- ^ Divisor + -> Maybe Integer -- ^ Quotient divF2m fx n1 n2 = mulF2m fx n1 <$> invF2m fx n2 {-# INLINE divF2m #-} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/PubKey/ECC/Prim.hs new/cryptonite-0.19/Crypto/PubKey/ECC/Prim.hs --- old/cryptonite-0.15/Crypto/PubKey/ECC/Prim.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/PubKey/ECC/Prim.hs 2016-08-12 08:14:25.000000000 +0200 @@ -26,6 +26,13 @@ --TODO: Extract helper function for `fromMaybe PointO...` +-- | Elliptic Curve point negation: +-- @pointNegate c p@ returns point @q@ such that @pointAdd c p q == PointO@. +pointNegate :: Curve -> Point -> Point +pointNegate _ PointO = PointO +pointNegate CurveFP{} (Point x y) = Point x (-y) +pointNegate CurveF2m{} (Point x y) = Point x (x `addF2m` y) + -- | Elliptic Curve point addition. -- -- /WARNING:/ Vulnerable to timing attacks. @@ -33,22 +40,21 @@ pointAdd _ PointO PointO = PointO pointAdd _ PointO q = q pointAdd _ p PointO = p -pointAdd c@(CurveFP (CurvePrime pr _)) p@(Point xp yp) q@(Point xq yq) - | p == Point xq (-yq) = PointO - | p == q = pointDouble c p - | otherwise = fromMaybe PointO $ do - s <- divmod (yp - yq) (xp - xq) pr - let xr = (s ^ (2::Int) - xp - xq) `mod` pr - yr = (s * (xp - xr) - yp) `mod` pr - return $ Point xr yr -pointAdd c@(CurveF2m (CurveBinary fx cc)) p@(Point xp yp) q@(Point xq yq) - | p == Point xq (xq `addF2m` yq) = PointO - | p == q = pointDouble c p - | otherwise = fromMaybe PointO $ do - s <- divF2m fx (yp `addF2m` yq) (xp `addF2m` xq) - let xr = mulF2m fx s s `addF2m` s `addF2m` xp `addF2m` xq `addF2m` a - yr = mulF2m fx s (xp `addF2m` xr) `addF2m` xr `addF2m` yp - return $ Point xr yr +pointAdd c p q + | p == q = pointDouble c p + | p == pointNegate c q = PointO +pointAdd (CurveFP (CurvePrime pr _)) (Point xp yp) (Point xq yq) + = fromMaybe PointO $ do + s <- divmod (yp - yq) (xp - xq) pr + let xr = (s ^ (2::Int) - xp - xq) `mod` pr + yr = (s * (xp - xr) - yp) `mod` pr + return $ Point xr yr +pointAdd (CurveF2m (CurveBinary fx cc)) (Point xp yp) (Point xq yq) + = fromMaybe PointO $ do + s <- divF2m fx (yp `addF2m` yq) (xp `addF2m` xq) + let xr = mulF2m fx s s `addF2m` s `addF2m` xp `addF2m` xq `addF2m` a + yr = mulF2m fx s (xp `addF2m` xr) `addF2m` xr `addF2m` yp + return $ Point xr yr where a = ecc_a cc -- | Elliptic Curve point doubling. @@ -95,8 +101,8 @@ -- /WARNING:/ Vulnerable to timing attacks. pointMul :: Curve -> Integer -> Point -> Point pointMul _ _ PointO = PointO -pointMul c n p@(Point xp yp) - | n < 0 = pointMul c (-n) (Point xp (-yp)) +pointMul c n p + | n < 0 = pointMul c (-n) (pointNegate c p) | n == 0 = PointO | n == 1 = p | odd n = pointAdd c p (pointMul c (n - 1) p) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/PubKey/Ed448.hs new/cryptonite-0.19/Crypto/PubKey/Ed448.hs --- old/cryptonite-0.15/Crypto/PubKey/Ed448.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/PubKey/Ed448.hs 2016-08-12 08:14:25.000000000 +0200 @@ -89,7 +89,7 @@ withByteArray sec $ \psec -> ccryptonite_ed448 result psec basePoint where - basePoint = Ptr "\x05\x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00\x00x00\x00\x00\x00\x00\x00\x00"# + basePoint = Ptr "\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# {-# NOINLINE toPublic #-} x448_bytes :: Int diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/Random/EntropyPool.hs new/cryptonite-0.19/Crypto/Random/EntropyPool.hs --- old/cryptonite-0.15/Crypto/Random/EntropyPool.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/Crypto/Random/EntropyPool.hs 2016-08-12 08:14:25.000000000 +0200 @@ -21,8 +21,8 @@ import Foreign.Marshal.Utils (copyBytes) import Foreign.Ptr (plusPtr, Ptr) --- | Pool of Entropy. contains a self mutating pool of entropy, --- that is always guarantee to contains data. +-- | Pool of Entropy. Contains a self-mutating pool of entropy, +-- that is always guaranteed to contain data. data EntropyPool = EntropyPool [EntropyBackend] (MVar Int) ScrubbedBytes -- size of entropy pool by default @@ -31,7 +31,8 @@ -- | Create a new entropy pool of a specific size -- --- While you can create as many entropy pool as you want, the pool can be shared between multiples RNGs. +-- While you can create as many entropy pools as you want, +-- the pool can be shared between multiples RNGs. createEntropyPoolWith :: Int -> [EntropyBackend] -> IO EntropyPool createEntropyPoolWith poolSize backends = do m <- newMVar 0 @@ -40,7 +41,8 @@ -- | Create a new entropy pool with a default size. -- --- While you can create as many entropy pool as you want, the pool can be shared between multiples RNGs. +-- While you can create as many entropy pools as you want, +-- the pool can be shared between multiples RNGs. createEntropyPool :: IO EntropyPool createEntropyPool = do backends <- catMaybes `fmap` sequence supportedBackends diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/Crypto/Tutorial.hs new/cryptonite-0.19/Crypto/Tutorial.hs --- old/cryptonite-0.15/Crypto/Tutorial.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.19/Crypto/Tutorial.hs 2016-08-12 08:14:25.000000000 +0200 @@ -0,0 +1,34 @@ +{-# OPTIONS_GHC -fno-warn-unused-imports #-} +{-# LANGUAGE OverloadedStrings #-} + +{-| How to use @cryptonite@ + +> -- | Beware MUST BE 256bits as we use AES256 +> import Data.ByteString (ByteString) +> import Crypto.Cipher.AES (AES256) +> import Crypto.Cipher.Types (BlockCipher(..), Cipher(..),nullIV) +> import Crypto.Error (CryptoFailable(..)) +> +> secretKey :: ByteString +> secretKey = "012-456-89A-CDE-012-456-89A-CDE-" +> +> encrypt :: ByteString -> ByteString -> ByteString +> encrypt secret = ctrCombine ctx nullIV +> where +> ctx = cipherInitNoErr (cipherMakeKey (undefined :: AES256) secret) +> cipherInitNoErr :: BlockCipher c => Key c -> c +> cipherInitNoErr (Key k) = case cipherInit k of +> CryptoPassed a -> a +> CryptoFailed e -> error (show e) +> cipherMakeKey :: Cipher cipher => cipher -> ByteString -> Key cipher +> cipherMakeKey _ = Key -- Yeah Lazyness!!!!!! +> +> +> decrypt :: ByteString -> ByteString -> ByteString +> decrypt = encrypt + +|-} + +module Crypto.Tutorial () where + +import Crypto.Cipher.Types diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/README.md new/cryptonite-0.19/README.md --- old/cryptonite-0.15/README.md 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/README.md 2016-08-12 08:14:25.000000000 +0200 @@ -2,27 +2,25 @@ ========== [![Join the chat at https://gitter.im/vincenthz/cryptonite](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/vincenthz/cryptonite?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://travis-ci.org/vincenthz/cryptonite.png?branch=master)](https://travis-ci.org/vincenthz/cryptonite) +[![Build Status](https://travis-ci.org/haskell-crypto/cryptonite.png?branch=master)](https://travis-ci.org/haskell-crypto/cryptonite) [![BSD](http://b.repl.ca/v1/license-BSD-blue.png)](http://en.wikipedia.org/wiki/BSD_licenses) [![Haskell](http://b.repl.ca/v1/language-haskell-lightgrey.png)](http://haskell.org) Cryptonite is a haskell repository of cryptographic primitives. Each crypto -algorithm have specificities, that are hard to wrap in common APIs and types, -so instead of trying to provide a common ground for algorithms that wouldn't -allow to provide all different usage or a really complicated system, this just -provide a non-consistant low-level API. +algorithm has specificities that are hard to wrap in common APIs and types, +so instead of trying to provide a common ground for algorithms, this package +provides a non-consistent low-level API. -If you have no idea what're you doing, please do not use this directly, rely on -higher level protocols or higher level implementation. +If you have no idea what you're doing, please do not use this directly. +Instead, rely on higher level protocols or implementations. Documentation: [cryptonite on hackage](http://hackage.haskell.org/package/cryptonite) Versioning ---------- -Development versions are an incremental number prefixed by 0. -No specific meaning is associated with the versions, specially -no API stability. +Development versions are an incremental number prefixed by 0. There is no +API stability between development versions. Production versions : TBD @@ -35,7 +33,7 @@ Support ------- -cryptonite supports the following platform: +cryptonite supports the following platforms: * Windows >= 8 * OSX >= 10.8 @@ -55,21 +53,22 @@ * GHC 7.8.x * GHC 7.10.x -Further platforms and architectures probably works too, but until maintainer(s) don't have regular -access to them, we can't commit for further support +Further platforms and architectures probably work too, but since the +maintainer(s) don't have regular access to them, we can't commit to +further support. Known Building Issues --------------------- -on OSX <= 10.7, the system compiler doesn't understand the '-maes' option, and +On OSX <= 10.7, the system compiler doesn't understand the '-maes' option, and 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 Disabling AESNI --------------- -It may be useful to disable AESNI (for building, testing or runtime purpose), and one can do that with the -*support_aesni* flag. +It may be useful to disable AESNI for building, testing or runtime purposes. +This is achieved with the *support_aesni* flag. As part of configure of cryptonite: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/cbits/cryptonite_rdrand.c new/cryptonite-0.19/cbits/cryptonite_rdrand.c --- old/cryptonite-0.15/cbits/cryptonite_rdrand.c 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/cbits/cryptonite_rdrand.c 2016-08-12 08:14:25.000000000 +0200 @@ -37,23 +37,15 @@ int cryptonite_cpu_has_rdrand() { uint32_t ax,bx,cx,dx,func=1; +#if defined(__PIC__) && defined(__i386__) + __asm__ volatile ("mov %%ebx, %%edi;" "cpuid;" "xchgl %%ebx, %%edi;" + : "=a" (ax), "=D" (bx), "=c" (cx), "=d" (dx) : "a" (func)); +#else __asm__ volatile ("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func)); +#endif return (cx & 0x40000000); } -/* sadly many people are still using an old binutils, - * leading to report that instruction is not recognized. - */ -#if 0 -/* Returns 1 on success */ -static inline int crypto_random_rdrand64_step(uint64_t *buffer) -{ - unsigned char err; - asm volatile ("rdrand %0; setc %1" : "=r" (*buffer), "=qm" (err)); - return (int) err; -} -#endif - /* inline encoding of 'rdrand %rax' to cover old binutils * - no inputs * - 'cc' to the clobber list as we modify condition code. @@ -65,17 +57,51 @@ : \ : "cc") +/* inline encoding of 'rdrand %eax' to cover old binutils + * - no inputs + * - 'cc' to the clobber list as we modify condition code. + * - output of rdrand in eax and have a 8 bit error condition + */ +#define inline_rdrand_eax(val, err) \ + asm(".byte 0x0f,0xc7,0xf0; setc %1" \ + : "=a" (val), "=q" (err) \ + : \ + : "cc") + +#ifdef __x86_64__ +# define RDRAND_SZ 8 +# define RDRAND_T uint64_t +#define inline_rdrand(val, err) err = cryptonite_rdrand_step(&val) +#else +# define RDRAND_SZ 4 +# define RDRAND_T uint32_t +#define inline_rdrand(val, err) err = cryptonite_rdrand_step(&val) +#endif + +/* sadly many people are still using an old binutils, + * leading to report that instruction is not recognized. + */ +#if 1 +/* Returns 1 on success */ +static inline int cryptonite_rdrand_step(RDRAND_T *buffer) +{ + unsigned char err; + asm volatile ("rdrand %0; setc %1" : "=r" (*buffer), "=qm" (err)); + return (int) err; +} +#endif + /* Returns the number of bytes succesfully generated */ int cryptonite_get_rand_bytes(uint8_t *buffer, size_t len) { - uint64_t tmp; - int aligned = (intptr_t) buffer % 8; + RDRAND_T tmp; + int aligned = (intptr_t) buffer % RDRAND_SZ; int orig_len = len; - int to_alignment = 8 - aligned; + int to_alignment = RDRAND_SZ - aligned; uint8_t ok; if (aligned != 0) { - inline_rdrand_rax(tmp, ok); + inline_rdrand(tmp, ok); if (!ok) return 0; memcpy(buffer, (uint8_t *) &tmp, to_alignment); @@ -83,15 +109,15 @@ len -= to_alignment; } - for (; len >= 8; buffer += 8, len -= 8) { - inline_rdrand_rax(tmp, ok); + for (; len >= RDRAND_SZ; buffer += RDRAND_SZ, len -= RDRAND_SZ) { + inline_rdrand(tmp, ok); if (!ok) return (orig_len - len); - *((uint64_t *) buffer) = tmp; + *((RDRAND_T *) buffer) = tmp; } if (len > 0) { - inline_rdrand_rax(tmp, ok); + inline_rdrand(tmp, ok); if (!ok) return (orig_len - len); memcpy(buffer, (uint8_t *) &tmp, len); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/cbits/curve25519/curve25519-donna-c64.c new/cryptonite-0.19/cbits/curve25519/curve25519-donna-c64.c --- old/cryptonite-0.15/cbits/curve25519/curve25519-donna-c64.c 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.19/cbits/curve25519/curve25519-donna-c64.c 2016-08-12 08:14:25.000000000 +0200 @@ -0,0 +1,447 @@ +/* Copyright 2008, Google Inc. + * All rights reserved. + * + * Code released into the public domain. + * + * curve25519-donna: Curve25519 elliptic curve, public key function + * + * http://code.google.com/p/curve25519-donna/ + * + * Adam Langley <a...@imperialviolet.org> + * + * Derived from public domain C code by Daniel J. Bernstein <d...@cr.yp.to> + * + * More information about curve25519 can be found here + * http://cr.yp.to/ecdh.html + * + * djb's sample implementation of curve25519 is written in a special assembly + * language called qhasm and uses the floating point registers. + * + * This is, almost, a clean room reimplementation from the curve25519 paper. It + * uses many of the tricks described therein. Only the crecip function is taken + * from the sample implementation. + */ + +#include <string.h> +#include <stdint.h> + +typedef uint8_t u8; +typedef uint64_t limb; +typedef limb felem[5]; +// This is a special gcc mode for 128-bit integers. It's implemented on 64-bit +// platforms only as far as I know. +typedef unsigned uint128_t __attribute__((mode(TI))); + +#undef force_inline +#define force_inline __attribute__((always_inline)) + +/* Sum two numbers: output += in */ +static inline void force_inline +fsum(limb *output, const limb *in) { + output[0] += in[0]; + output[1] += in[1]; + output[2] += in[2]; + output[3] += in[3]; + output[4] += in[4]; +} + +/* Find the difference of two numbers: output = in - output + * (note the order of the arguments!) + * + * Assumes that out[i] < 2**52 + * On return, out[i] < 2**55 + */ +static inline void force_inline +fdifference_backwards(felem out, const felem in) { + /* 152 is 19 << 3 */ + static const limb two54m152 = (((limb)1) << 54) - 152; + static const limb two54m8 = (((limb)1) << 54) - 8; + + out[0] = in[0] + two54m152 - out[0]; + out[1] = in[1] + two54m8 - out[1]; + out[2] = in[2] + two54m8 - out[2]; + out[3] = in[3] + two54m8 - out[3]; + out[4] = in[4] + two54m8 - out[4]; +} + +/* Multiply a number by a scalar: output = in * scalar */ +static inline void force_inline +fscalar_product(felem output, const felem in, const limb scalar) { + uint128_t a; + + a = ((uint128_t) in[0]) * scalar; + output[0] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[1]) * scalar + ((limb) (a >> 51)); + output[1] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[2]) * scalar + ((limb) (a >> 51)); + output[2] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[3]) * scalar + ((limb) (a >> 51)); + output[3] = ((limb)a) & 0x7ffffffffffff; + + a = ((uint128_t) in[4]) * scalar + ((limb) (a >> 51)); + output[4] = ((limb)a) & 0x7ffffffffffff; + + output[0] += (a >> 51) * 19; +} + +/* Multiply two numbers: output = in2 * in + * + * output must be distinct to both inputs. The inputs are reduced coefficient + * form, the output is not. + * + * Assumes that in[i] < 2**55 and likewise for in2. + * On return, output[i] < 2**52 + */ +static inline void force_inline +fmul(felem output, const felem in2, const felem in) { + uint128_t t[5]; + limb r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c; + + r0 = in[0]; + r1 = in[1]; + r2 = in[2]; + r3 = in[3]; + r4 = in[4]; + + s0 = in2[0]; + s1 = in2[1]; + s2 = in2[2]; + s3 = in2[3]; + s4 = in2[4]; + + t[0] = ((uint128_t) r0) * s0; + t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0; + t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1; + t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1; + t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2; + + r4 *= 19; + r1 *= 19; + r2 *= 19; + r3 *= 19; + + t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2; + t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3; + t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4; + t[3] += ((uint128_t) r4) * s4; + + r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51); + t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51); + t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51); + t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51); + t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff; + r2 += c; + + output[0] = r0; + output[1] = r1; + output[2] = r2; + output[3] = r3; + output[4] = r4; +} + +static inline void force_inline +fsquare_times(felem output, const felem in, limb count) { + uint128_t t[5]; + limb r0,r1,r2,r3,r4,c; + limb d0,d1,d2,d4,d419; + + r0 = in[0]; + r1 = in[1]; + r2 = in[2]; + r3 = in[3]; + r4 = in[4]; + + do { + d0 = r0 * 2; + d1 = r1 * 2; + d2 = r2 * 2 * 19; + d419 = r4 * 19; + d4 = d419 * 2; + + t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 )); + t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19)); + t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 )); + t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 )); + t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 )); + + r0 = (limb)t[0] & 0x7ffffffffffff; c = (limb)(t[0] >> 51); + t[1] += c; r1 = (limb)t[1] & 0x7ffffffffffff; c = (limb)(t[1] >> 51); + t[2] += c; r2 = (limb)t[2] & 0x7ffffffffffff; c = (limb)(t[2] >> 51); + t[3] += c; r3 = (limb)t[3] & 0x7ffffffffffff; c = (limb)(t[3] >> 51); + t[4] += c; r4 = (limb)t[4] & 0x7ffffffffffff; c = (limb)(t[4] >> 51); + r0 += c * 19; c = r0 >> 51; r0 = r0 & 0x7ffffffffffff; + r1 += c; c = r1 >> 51; r1 = r1 & 0x7ffffffffffff; + r2 += c; + } while(--count); + + output[0] = r0; + output[1] = r1; + output[2] = r2; + output[3] = r3; + output[4] = r4; +} + +/* Load a little-endian 64-bit number */ +static limb +load_limb(const u8 *in) { + return + ((limb)in[0]) | + (((limb)in[1]) << 8) | + (((limb)in[2]) << 16) | + (((limb)in[3]) << 24) | + (((limb)in[4]) << 32) | + (((limb)in[5]) << 40) | + (((limb)in[6]) << 48) | + (((limb)in[7]) << 56); +} + +static void +store_limb(u8 *out, limb in) { + out[0] = in & 0xff; + out[1] = (in >> 8) & 0xff; + out[2] = (in >> 16) & 0xff; + out[3] = (in >> 24) & 0xff; + out[4] = (in >> 32) & 0xff; + out[5] = (in >> 40) & 0xff; + out[6] = (in >> 48) & 0xff; + out[7] = (in >> 56) & 0xff; +} + +/* Take a little-endian, 32-byte number and expand it into polynomial form */ +static void +fexpand(limb *output, const u8 *in) { + output[0] = load_limb(in) & 0x7ffffffffffff; + output[1] = (load_limb(in+6) >> 3) & 0x7ffffffffffff; + output[2] = (load_limb(in+12) >> 6) & 0x7ffffffffffff; + output[3] = (load_limb(in+19) >> 1) & 0x7ffffffffffff; + output[4] = (load_limb(in+24) >> 12) & 0x7ffffffffffff; +} + +/* Take a fully reduced polynomial form number and contract it into a + * little-endian, 32-byte array + */ +static void +fcontract(u8 *output, const felem input) { + uint128_t t[5]; + + t[0] = input[0]; + t[1] = input[1]; + t[2] = input[2]; + t[3] = input[3]; + t[4] = input[4]; + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff; + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff; + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + + t[0] += 19; + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[0] += 19 * (t[4] >> 51); t[4] &= 0x7ffffffffffff; + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + + t[0] += 0x8000000000000 - 19; + t[1] += 0x8000000000000 - 1; + t[2] += 0x8000000000000 - 1; + t[3] += 0x8000000000000 - 1; + t[4] += 0x8000000000000 - 1; + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + + t[1] += t[0] >> 51; t[0] &= 0x7ffffffffffff; + t[2] += t[1] >> 51; t[1] &= 0x7ffffffffffff; + t[3] += t[2] >> 51; t[2] &= 0x7ffffffffffff; + t[4] += t[3] >> 51; t[3] &= 0x7ffffffffffff; + t[4] &= 0x7ffffffffffff; + + store_limb(output, t[0] | (t[1] << 51)); + store_limb(output+8, (t[1] >> 13) | (t[2] << 38)); + store_limb(output+16, (t[2] >> 26) | (t[3] << 25)); + store_limb(output+24, (t[3] >> 39) | (t[4] << 12)); +} + +/* Input: Q, Q', Q-Q' + * Output: 2Q, Q+Q' + * + * x2 z3: long form + * x3 z3: long form + * x z: short form, destroyed + * xprime zprime: short form, destroyed + * qmqp: short form, preserved + */ +static void +fmonty(limb *x2, limb *z2, /* output 2Q */ + limb *x3, limb *z3, /* output Q + Q' */ + limb *x, limb *z, /* input Q */ + limb *xprime, limb *zprime, /* input Q' */ + const limb *qmqp /* input Q - Q' */) { + limb origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5], + zzprime[5], zzzprime[5]; + + memcpy(origx, x, 5 * sizeof(limb)); + fsum(x, z); + fdifference_backwards(z, origx); // does x - z + + memcpy(origxprime, xprime, sizeof(limb) * 5); + fsum(xprime, zprime); + fdifference_backwards(zprime, origxprime); + fmul(xxprime, xprime, z); + fmul(zzprime, x, zprime); + memcpy(origxprime, xxprime, sizeof(limb) * 5); + fsum(xxprime, zzprime); + fdifference_backwards(zzprime, origxprime); + fsquare_times(x3, xxprime, 1); + fsquare_times(zzzprime, zzprime, 1); + fmul(z3, zzzprime, qmqp); + + fsquare_times(xx, x, 1); + fsquare_times(zz, z, 1); + fmul(x2, xx, zz); + fdifference_backwards(zz, xx); // does zz = xx - zz + fscalar_product(zzz, zz, 121665); + fsum(zzz, xx); + fmul(z2, zz, zzz); +} + +// ----------------------------------------------------------------------------- +// Maybe swap the contents of two limb arrays (@a and @b), each @len elements +// long. Perform the swap iff @swap is non-zero. +// +// This function performs the swap without leaking any side-channel +// information. +// ----------------------------------------------------------------------------- +static void +swap_conditional(limb a[5], limb b[5], limb iswap) { + unsigned i; + const limb swap = -iswap; + + for (i = 0; i < 5; ++i) { + const limb x = swap & (a[i] ^ b[i]); + a[i] ^= x; + b[i] ^= x; + } +} + +/* Calculates nQ where Q is the x-coordinate of a point on the curve + * + * resultx/resultz: the x coordinate of the resulting curve point (short form) + * n: a little endian, 32-byte number + * q: a point of the curve (short form) + */ +static void +cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) { + limb a[5] = {0}, b[5] = {1}, c[5] = {1}, d[5] = {0}; + limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + limb e[5] = {0}, f[5] = {1}, g[5] = {0}, h[5] = {1}; + limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(limb) * 5); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + const limb bit = byte >> 7; + + swap_conditional(nqx, nqpqx, bit); + swap_conditional(nqz, nqpqz, bit); + fmonty(nqx2, nqz2, + nqpqx2, nqpqz2, + nqx, nqz, + nqpqx, nqpqz, + q); + swap_conditional(nqx2, nqpqx2, bit); + swap_conditional(nqz2, nqpqz2, bit); + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(limb) * 5); + memcpy(resultz, nqz, sizeof(limb) * 5); +} + + +// ----------------------------------------------------------------------------- +// Shamelessly copied from djb's code, tightened a little +// ----------------------------------------------------------------------------- +static void +crecip(felem out, const felem z) { + felem a,t0,b,c; + + /* 2 */ fsquare_times(a, z, 1); // a = 2 + /* 8 */ fsquare_times(t0, a, 2); + /* 9 */ fmul(b, t0, z); // b = 9 + /* 11 */ fmul(a, b, a); // a = 11 + /* 22 */ fsquare_times(t0, a, 1); + /* 2^5 - 2^0 = 31 */ fmul(b, t0, b); + /* 2^10 - 2^5 */ fsquare_times(t0, b, 5); + /* 2^10 - 2^0 */ fmul(b, t0, b); + /* 2^20 - 2^10 */ fsquare_times(t0, b, 10); + /* 2^20 - 2^0 */ fmul(c, t0, b); + /* 2^40 - 2^20 */ fsquare_times(t0, c, 20); + /* 2^40 - 2^0 */ fmul(t0, t0, c); + /* 2^50 - 2^10 */ fsquare_times(t0, t0, 10); + /* 2^50 - 2^0 */ fmul(b, t0, b); + /* 2^100 - 2^50 */ fsquare_times(t0, b, 50); + /* 2^100 - 2^0 */ fmul(c, t0, b); + /* 2^200 - 2^100 */ fsquare_times(t0, c, 100); + /* 2^200 - 2^0 */ fmul(t0, t0, c); + /* 2^250 - 2^50 */ fsquare_times(t0, t0, 50); + /* 2^250 - 2^0 */ fmul(t0, t0, b); + /* 2^255 - 2^5 */ fsquare_times(t0, t0, 5); + /* 2^255 - 21 */ fmul(out, t0, a); +} + +int +cryptonite_curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { + limb bp[5], x[5], z[5], zmone[5]; + uint8_t e[32]; + int i; + + for (i = 0;i < 32;++i) e[i] = secret[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + + fexpand(bp, basepoint); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + fcontract(mypublic, z); + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/cryptonite.cabal new/cryptonite-0.19/cryptonite.cabal --- old/cryptonite-0.15/cryptonite.cabal 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/cryptonite.cabal 2016-08-12 08:14:25.000000000 +0200 @@ -1,5 +1,5 @@ Name: cryptonite -Version: 0.15 +Version: 0.19 Synopsis: Cryptography Primitives sink Description: A repository of cryptographic primitives. @@ -10,7 +10,7 @@ . * MAC: HMAC, Poly1305 . - * Assymmetric crypto: DSA, RSA, DH, ECDH, ECDSA, ECC, Curve25519, Ed25519 + * Asymmetric crypto: DSA, RSA, DH, ECDH, ECDSA, ECC, Curve25519, Ed25519, Ed448 . * Key Derivation Function: PBKDF2, Scrypt, HKDF . @@ -23,6 +23,8 @@ cryptographic kitchen sink that provides cryptography for everyone. . 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 <vinc...@snarc.org> @@ -41,9 +43,7 @@ cbits/ed448/*.h cbits/p256/*.h cbits/blake2/ref/*.h - cbits/blake2/ref/*.c cbits/blake2/sse/*.h - cbits/blake2/sse/*.c cbits/aes/x86ni_impl.c tests/*.hs @@ -97,6 +97,7 @@ Crypto.Cipher.Salsa Crypto.Cipher.TripleDES Crypto.Cipher.Types + Crypto.ConstructHash.MiyaguchiPreneel Crypto.Data.AFIS Crypto.Data.Padding Crypto.Error @@ -140,6 +141,7 @@ Crypto.Random.Entropy Crypto.Random.EntropyPool Crypto.Random.Entropy.Unsafe + Crypto.Tutorial Other-modules: Crypto.Cipher.AES.Primitive Crypto.Cipher.Blowfish.Box Crypto.Cipher.Blowfish.Primitive @@ -201,7 +203,6 @@ , cbits/cryptonite_salsa.c , cbits/cryptonite_rc4.c , cbits/cryptonite_cpu.c - , cbits/curve25519/curve25519-donna.c , cbits/ed25519/ed25519.c , cbits/ed448/x448.c , cbits/p256/p256.c @@ -227,6 +228,11 @@ , cbits/cryptonite_scrypt.c include-dirs: cbits cbits/ed25519 + if arch(x86_64) + C-sources: cbits/curve25519/curve25519-donna-c64.c + else + C-sources: cbits/curve25519/curve25519-donna.c + -- FIXME armel or mispel is also little endian. -- might be a good idea to also add a runtime autodetect mode. -- ARCH_ENDIAN_UNKNOWN @@ -236,8 +242,10 @@ if arch(i386) CPP-options: -DARCH_X86 - if flag(support_rdrand) && arch(x86_64) - CPP-options: -DARCH_X86_64 + if arch(x86_64) + CPP-options: -DARCH_X86_64 + + if flag(support_rdrand) && (arch(i386) || arch(x86_64)) CPP-options: -DSUPPORT_RDRAND Other-modules: Crypto.Random.Entropy.RDRand c-sources: cbits/cryptonite_rdrand.c @@ -303,9 +311,12 @@ KAT_Camellia KAT_Curve25519 KAT_DES + KAT_Ed448 KAT_Ed25519 KAT_CMAC + KAT_HKDF KAT_HMAC + KAT_MiyaguchiPreneel KAT_PBKDF2 KAT_PubKey.DSA KAT_PubKey.ECC @@ -317,6 +328,10 @@ KAT_RC4 KAT_Scrypt KAT_TripleDES + ChaChaPoly1305 + Number + Number.F2m + Padding Poly1305 Salsa Utils diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/tests/BCrypt.hs new/cryptonite-0.19/tests/BCrypt.hs --- old/cryptonite-0.15/tests/BCrypt.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/tests/BCrypt.hs 2016-08-12 08:14:25.000000000 +0200 @@ -74,4 +74,5 @@ tests = testGroup "bcrypt" [ testGroup "KATs" makeKATs + , testCase "Invalid hash length" (assertEqual "" (Left "Invalid hash format") (validatePasswordEither B.empty ("$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s" :: B.ByteString))) ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/tests/KAT_Ed448.hs new/cryptonite-0.19/tests/KAT_Ed448.hs --- old/cryptonite-0.15/tests/KAT_Ed448.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/tests/KAT_Ed448.hs 2016-08-12 08:14:25.000000000 +0200 @@ -16,6 +16,8 @@ katTests = [ testCase "0" (aliceMultBob @=? B.convert (Ed448.dh alicePublic bobPrivate)) , testCase "1" (aliceMultBob @=? B.convert (Ed448.dh bobPublic alicePrivate)) + , testCase "2" (alicePublic @=? Ed448.toPublic alicePrivate) + , testCase "3" (bobPublic @=? Ed448.toPublic bobPrivate) ] tests = testGroup "Ed448" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/tests/KAT_MiyaguchiPreneel.hs new/cryptonite-0.19/tests/KAT_MiyaguchiPreneel.hs --- old/cryptonite-0.15/tests/KAT_MiyaguchiPreneel.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.19/tests/KAT_MiyaguchiPreneel.hs 2016-08-12 08:14:25.000000000 +0200 @@ -0,0 +1,50 @@ + +module KAT_MiyaguchiPreneel (tests) where + +import Crypto.Cipher.AES (AES128) +import Crypto.ConstructHash.MiyaguchiPreneel as MiyaguchiPreneel + +import Imports + +import Data.Char (digitToInt) +import qualified Data.ByteString.Char8 as B8 +import qualified Data.ByteArray as B +import Data.ByteArray.Encoding (Base (Base16), convertFromBase) + + +runMP128 :: ByteString -> ByteString +runMP128 s = B.convert (MiyaguchiPreneel.compute s :: MiyaguchiPreneel AES128) + +hxs :: String -> ByteString +hxs = either (error . ("hxs:" ++)) id . convertFromBase Base16 + . B8.pack . filter (/= ' ') + +gAES128 :: TestTree +gAES128 = + igroup "aes128" + [ runMP128 B8.empty + @?= hxs "66e94bd4 ef8a2c3b 884cfa59 ca342b2e" + , runMP128 (hxs "01000000 00000000 00000000 00000000") + @?= hxs "46711816 e91d6ff0 59bbbf2b f58e0fd3" + , runMP128 (hxs "00000000 00000000 00000000 00000001") + @?= hxs "58e2fcce fa7e3061 367f1d57 a4e7455b" + , runMP128 (hxs $ + "00000000 00000000 00000000 00000000" ++ + "01") + @?= hxs "a5ff35ae 097adf5d 646abf5e bf4c16f4" + ] + +igroup :: TestName -> [Assertion] -> TestTree +igroup nm = testGroup nm . zipWith (flip ($)) [1..] . map icase + where + icase c i = testCase (show (i :: Int)) c + +vectors :: TestTree +vectors = + testGroup "KATs" + [ gAES128 ] + +tests :: TestTree +tests = + testGroup "MiyaguchiPreneel" + [ vectors ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/tests/Number/F2m.hs new/cryptonite-0.19/tests/Number/F2m.hs --- old/cryptonite-0.15/tests/Number/F2m.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/cryptonite-0.19/tests/Number/F2m.hs 2016-08-12 08:14:25.000000000 +0200 @@ -0,0 +1,83 @@ +module Number.F2m (tests) where + +import Imports hiding ((.&.)) +import Data.Bits +import Crypto.Number.Basic (log2) +import Crypto.Number.F2m + +addTests = testGroup "addF2m" + [ testProperty "commutative" + $ \a b -> a `addF2m` b == b `addF2m` a + , testProperty "associative" + $ \a b c -> (a `addF2m` b) `addF2m` c == a `addF2m` (b `addF2m` c) + , testProperty "0 is neutral" + $ \a -> a `addF2m` 0 == a + , testProperty "nullable" + $ \a -> a `addF2m` a == 0 + , testProperty "works per bit" + $ \a b -> (a `addF2m` b) .&. b == (a .&. b) `addF2m` b + ] + +modTests = testGroup "modF2m" + [ testProperty "idempotent" + $ \(Positive m) (NonNegative a) -> modF2m m a == modF2m m (modF2m m a) + , testProperty "upper bound" + $ \(Positive m) (NonNegative a) -> modF2m m a < 2 ^ log2 m + , testProperty "reach upper" + $ \(Positive m) -> let a = 2 ^ log2 m - 1 in modF2m m (m `addF2m` a) == a + , testProperty "lower bound" + $ \(Positive m) (NonNegative a) -> modF2m m a >= 0 + , testProperty "reach lower" + $ \(Positive m) -> modF2m m m == 0 + , testProperty "additive" + $ \(Positive m) (NonNegative a) (NonNegative b) + -> modF2m m a `addF2m` modF2m m b == modF2m m (a `addF2m` b) + ] + +mulTests = testGroup "mulF2m" + [ testProperty "commutative" + $ \(Positive m) (NonNegative a) (NonNegative b) -> mulF2m m a b == mulF2m m b a + , testProperty "associative" + $ \(Positive m) (NonNegative a) (NonNegative b) (NonNegative c) + -> mulF2m m (mulF2m m a b) c == mulF2m m a (mulF2m m b c) + , testProperty "1 is neutral" + $ \(Positive m) (NonNegative a) -> mulF2m m a 1 == modF2m m a + , testProperty "0 is annihilator" + $ \(Positive m) (NonNegative a) -> mulF2m m a 0 == 0 + , testProperty "distributive" + $ \(Positive m) (NonNegative a) (NonNegative b) (NonNegative c) + -> mulF2m m a (b `addF2m` c) == mulF2m m a b `addF2m` mulF2m m a c + ] + +squareTests = testGroup "squareF2m" + [ testProperty "sqr(a) == a * a" + $ \(Positive m) (NonNegative a) -> mulF2m m a a == squareF2m m a + ] + +invTests = testGroup "invF2m" + [ testProperty "1 / a * a == 1" + $ \(Positive m) (NonNegative a) + -> maybe True (\c -> mulF2m m c a == modF2m m 1) (invF2m m a) + , testProperty "1 / a == a (mod a^2-1)" + $ \(NonNegative a) -> a < 2 || invF2m (squareF2m' a `addF2m` 1) a == Just a + ] + +divTests = testGroup "divF2m" + [ testProperty "1 / a == inv a" + $ \(Positive m) (NonNegative a) -> divF2m m 1 a == invF2m m a + , testProperty "a / b == a * inv b" + $ \(Positive m) (NonNegative a) (NonNegative b) + -> divF2m m a b == (mulF2m m a <$> invF2m m b) + , testProperty "a * b / b == a" + $ \(Positive m) (NonNegative a) (NonNegative b) + -> invF2m m b == Nothing || divF2m m (mulF2m m a b) b == Just (modF2m m a) + ] + +tests = testGroup "number.F2m" + [ addTests + , modTests + , mulTests + , squareTests + , invTests + , divTests + ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/tests/Padding.hs new/cryptonite-0.19/tests/Padding.hs --- old/cryptonite-0.15/tests/Padding.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/tests/Padding.hs 2016-08-12 08:14:25.000000000 +0200 @@ -13,6 +13,12 @@ , ("xyze", 5, "xyze\x01") ] +zeroCases = + [ ("", 4, "\NUL\NUL\NUL\NUL", Nothing) + , ("abcdef", 8, "abcdef\NUL\NUL", Nothing) + , ("0123456789abcdef", 16, "0123456789abcdef", Just "0123456789abcdef") + ] + --instance Arbitrary where testPad :: Int -> (B.ByteString, Int, B.ByteString) -> TestTree @@ -21,6 +27,13 @@ , eqTest "unpadded" (Just inp) (unpad (PKCS7 sz) padded) ] +testZeroPad :: Int -> (B.ByteString, Int, B.ByteString, Maybe B.ByteString) -> TestTree +testZeroPad n (inp, sz, padded, unpadded) = + testCase (show n) $ propertyHoldCase [ eqTest "padded" padded (pad (ZERO sz) inp) + , eqTest "unpadded" unpadded (unpad (ZERO sz) padded) + ] + tests = testGroup "Padding" [ testGroup "Cases" $ map (uncurry testPad) (zip [1..] cases) + , testGroup "ZeroCases" $ map (uncurry testZeroPad) (zip [1..] zeroCases) ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cryptonite-0.15/tests/Tests.hs new/cryptonite-0.19/tests/Tests.hs --- old/cryptonite-0.15/tests/Tests.hs 2016-04-09 18:16:13.000000000 +0200 +++ new/cryptonite-0.19/tests/Tests.hs 2016-08-12 08:14:25.000000000 +0200 @@ -4,12 +4,14 @@ import Imports import qualified Number +import qualified Number.F2m import qualified BCrypt import qualified Hash import qualified Poly1305 import qualified Salsa import qualified ChaCha import qualified ChaChaPoly1305 +import qualified KAT_MiyaguchiPreneel import qualified KAT_CMAC import qualified KAT_HMAC import qualified KAT_HKDF @@ -32,8 +34,12 @@ tests = testGroup "cryptonite" [ Number.tests + , Number.F2m.tests , Hash.tests , Padding.tests + , testGroup "ConstructHash" + [ KAT_MiyaguchiPreneel.tests + ] , testGroup "MAC" [ Poly1305.tests , KAT_CMAC.tests