cryptonite 0.16 → 0.17
raw patch · 9 files changed
+196/−10 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Crypto.ConstructHash.MiyaguchiPreneel: compute :: (ByteArrayAccess bin, BlockCipher cipher) => bin -> MiyaguchiPreneel cipher
+ Crypto.ConstructHash.MiyaguchiPreneel: compute' :: (ByteArrayAccess bin, BlockCipher cipher) => (Bytes -> cipher) -> bin -> MiyaguchiPreneel cipher
+ Crypto.ConstructHash.MiyaguchiPreneel: data MiyaguchiPreneel a
+ Crypto.ConstructHash.MiyaguchiPreneel: instance Data.ByteArray.Types.ByteArrayAccess (Crypto.ConstructHash.MiyaguchiPreneel.MiyaguchiPreneel a)
+ Crypto.ConstructHash.MiyaguchiPreneel: instance GHC.Classes.Eq (Crypto.ConstructHash.MiyaguchiPreneel.MiyaguchiPreneel a)
+ Crypto.Data.Padding: ZERO :: Int -> Format
Files
- CHANGELOG.md +6/−0
- Crypto/ConstructHash/MiyaguchiPreneel.hs +68/−0
- Crypto/Data/Padding.hs +17/−0
- Crypto/KDF/Scrypt.hs +1/−1
- cbits/cryptonite_rdrand.c +33/−7
- cryptonite.cabal +4/−2
- tests/KAT_MiyaguchiPreneel.hs +50/−0
- tests/Padding.hs +13/−0
- tests/Tests.hs +4/−0
CHANGELOG.md view
@@ -1,3 +1,9 @@+## 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
+ Crypto/ConstructHash/MiyaguchiPreneel.hs view
@@ -0,0 +1,68 @@+-- |+-- Module : Crypto.ConstructHash.MiyaguchiPreneel+-- License : BSD-style+-- Maintainer : Kei Hibino <ex8k.hibino@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
Crypto/Data/Padding.hs view
@@ -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
Crypto/KDF/Scrypt.hs view
@@ -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
cbits/cryptonite_rdrand.c view
@@ -37,7 +37,12 @@ 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); } @@ -65,17 +70,38 @@ : \ : "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) inline_rdrand_rax(val, err)+#else+# define RDRAND_SZ 4+# define RDRAND_T uint32_t+#define inline_rdrand(val, err) inline_rdrand_eax(val, 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; } if (len > 0) {- inline_rdrand_rax(tmp, ok);+ inline_rdrand(tmp, ok); if (!ok) return (orig_len - len); memcpy(buffer, (uint8_t *) &tmp, len);
cryptonite.cabal view
@@ -1,5 +1,5 @@ Name: cryptonite-Version: 0.16+Version: 0.17 Synopsis: Cryptography Primitives sink Description: A repository of cryptographic primitives.@@ -95,6 +95,7 @@ Crypto.Cipher.Salsa Crypto.Cipher.TripleDES Crypto.Cipher.Types+ Crypto.ConstructHash.MiyaguchiPreneel Crypto.Data.AFIS Crypto.Data.Padding Crypto.Error@@ -241,7 +242,7 @@ if arch(x86_64) CPP-options: -DARCH_X86_64 - if flag(support_rdrand)+ 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@@ -310,6 +311,7 @@ KAT_Ed25519 KAT_CMAC KAT_HMAC+ KAT_MiyaguchiPreneel KAT_PBKDF2 KAT_PubKey.DSA KAT_PubKey.ECC
+ tests/KAT_MiyaguchiPreneel.hs view
@@ -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 ]
tests/Padding.hs view
@@ -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) ]
tests/Tests.hs view
@@ -10,6 +10,7 @@ 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@@ -34,6 +35,9 @@ [ Number.tests , Hash.tests , Padding.tests+ , testGroup "ConstructHash"+ [ KAT_MiyaguchiPreneel.tests+ ] , testGroup "MAC" [ Poly1305.tests , KAT_CMAC.tests