packages feed

cryptonite 0.13 → 0.14

raw patch · 18 files changed

+440/−41 lines, 18 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Crypto.PubKey.DH: instance GHC.Classes.Ord Crypto.PubKey.DH.SharedKey
- Crypto.PubKey.DH: instance GHC.Enum.Enum Crypto.PubKey.DH.SharedKey
- Crypto.PubKey.DH: instance GHC.Num.Num Crypto.PubKey.DH.SharedKey
- Crypto.PubKey.DH: instance GHC.Read.Read Crypto.PubKey.DH.SharedKey
- Crypto.PubKey.DH: instance GHC.Real.Real Crypto.PubKey.DH.SharedKey
+ Crypto.MAC.CMAC: cmac :: (ByteArrayAccess bin, BlockCipher cipher) => cipher -> bin -> CMAC cipher
+ Crypto.MAC.CMAC: data CMAC a
+ Crypto.MAC.CMAC: instance Data.ByteArray.Types.ByteArrayAccess (Crypto.MAC.CMAC.CMAC a)
+ Crypto.MAC.CMAC: instance GHC.Classes.Eq (Crypto.MAC.CMAC.CMAC a)
+ Crypto.MAC.CMAC: subKeys :: (BlockCipher k, ByteArray ba) => k -> (ba, ba)
+ Crypto.PubKey.DH: [params_bits] :: Params -> Int
+ Crypto.PubKey.DH: instance Data.ByteArray.Types.ByteArrayAccess Crypto.PubKey.DH.SharedKey
+ Crypto.PubKey.ECC.Types: instance GHC.Enum.Bounded Crypto.PubKey.ECC.Types.CurveName
+ Crypto.Random: data Seed
+ Crypto.Random: drgNewSeed :: Seed -> ChaChaDRG
+ Crypto.Random: instance Data.ByteArray.Types.ByteArrayAccess Crypto.Random.Seed
+ Crypto.Random: seedFromInteger :: Integer -> Seed
+ Crypto.Random: seedNew :: MonadRandom randomly => randomly Seed
+ Crypto.Random: seedToInteger :: Seed -> Integer
- Crypto.PubKey.DH: Params :: Integer -> Integer -> Params
+ Crypto.PubKey.DH: Params :: Integer -> Integer -> Int -> Params
- Crypto.PubKey.DH: SharedKey :: Integer -> SharedKey
+ Crypto.PubKey.DH: SharedKey :: ScrubbedBytes -> SharedKey
- Crypto.PubKey.ECC.DH: SharedKey :: Integer -> SharedKey
+ Crypto.PubKey.ECC.DH: SharedKey :: ScrubbedBytes -> SharedKey

Files

CHANGELOG.md view
@@ -1,3 +1,16 @@+## 0.14++* Reduce size of SHA3 context instead of allocating all-size fit memory. save+  up to 72 bytes of memory per context for SHA3-512.+* Add a Seed capability to the main DRG, to be able to debug/reproduce randomized program+  where you would want to disable the randomness.+* Add support for Cipher-based Message Authentication Code (CMAC) (Kei Hibino)+* *CHANGE* Change the `SharedKey` for `Crypto.PubKey.DH` and `Crypto.PubKey.ECC.DH`,+  from an Integer newtype to a ScrubbedBytes newtype. Prevent mistake where the+  bytes representation is generated without the right padding (when needed).+* *CHANGE* Keep The field size in bits, in the `Params` in `Crypto.PubKey.DH`,+  moving from 2 elements to 3 elements in the structure.+ ## 0.13  * *SECURITY* Fix buffer overflow issue in SHA384, copying 16 extra bytes from
Crypto/Hash/Keccak.hs view
@@ -25,7 +25,7 @@ instance HashAlgorithm Keccak_224 where     hashBlockSize  _          = 144     hashDigestSize _          = 28-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 352     hashInternalInit p        = c_keccak_init p 224     hashInternalUpdate        = c_keccak_update     hashInternalFinalize p    = c_keccak_finalize p 224@@ -37,7 +37,7 @@ instance HashAlgorithm Keccak_256 where     hashBlockSize  _          = 136     hashDigestSize _          = 32-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 344     hashInternalInit p        = c_keccak_init p 256     hashInternalUpdate        = c_keccak_update     hashInternalFinalize p    = c_keccak_finalize p 256@@ -49,7 +49,7 @@ instance HashAlgorithm Keccak_384 where     hashBlockSize  _          = 104     hashDigestSize _          = 48-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 312     hashInternalInit p        = c_keccak_init p 384     hashInternalUpdate        = c_keccak_update     hashInternalFinalize p    = c_keccak_finalize p 384@@ -61,7 +61,7 @@ instance HashAlgorithm Keccak_512 where     hashBlockSize  _          = 72     hashDigestSize _          = 64-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 280     hashInternalInit p        = c_keccak_init p 512     hashInternalUpdate        = c_keccak_update     hashInternalFinalize p    = c_keccak_finalize p 512
Crypto/Hash/SHA3.hs view
@@ -25,7 +25,7 @@ instance HashAlgorithm SHA3_224 where     hashBlockSize  _          = 144     hashDigestSize _          = 28-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 352     hashInternalInit p        = c_sha3_init p 224     hashInternalUpdate        = c_sha3_update     hashInternalFinalize p    = c_sha3_finalize p 224@@ -37,7 +37,7 @@ instance HashAlgorithm SHA3_256 where     hashBlockSize  _          = 136     hashDigestSize _          = 32-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 344     hashInternalInit p        = c_sha3_init p 256     hashInternalUpdate        = c_sha3_update     hashInternalFinalize p    = c_sha3_finalize p 256@@ -49,7 +49,7 @@ instance HashAlgorithm SHA3_384 where     hashBlockSize  _          = 104     hashDigestSize _          = 48-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 312     hashInternalInit p        = c_sha3_init p 384     hashInternalUpdate        = c_sha3_update     hashInternalFinalize p    = c_sha3_finalize p 384@@ -61,7 +61,7 @@ instance HashAlgorithm SHA3_512 where     hashBlockSize  _          = 72     hashDigestSize _          = 64-    hashInternalContextSize _ = 360+    hashInternalContextSize _ = 280     hashInternalInit p        = c_sha3_init p 512     hashInternalUpdate        = c_sha3_update     hashInternalFinalize p    = c_sha3_finalize p 512
Crypto/KDF/BCrypt.hs view
@@ -1,7 +1,7 @@  -- | Password encoding and validation using bcrypt. ----- Example usasge:+-- Example usage: -- -- >>> import Crypto.KDF.BCrypt (hashPassword, validatePassword) -- >>> import qualified Data.ByteString.Char8 as B@@ -78,6 +78,8 @@     return $ bcrypt cost (salt :: Bytes) password  -- | Create a bcrypt hash for a password with a provided cost value and salt.+--+-- Cost value under 4 will be automatically adjusted back to 10 for safety reason. bcrypt :: (ByteArray salt, ByteArray password, ByteArray output)        => Int        -- ^ The cost parameter. Should be between 4 and 31 (inclusive).
Crypto/KDF/HKDF.hs view
@@ -7,10 +7,9 @@ -- -- Key Derivation Function based on HMAC ----- See rfc5869+-- See RFC5869 -- {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Crypto.KDF.HKDF     ( PRK     , extract@@ -35,7 +34,10 @@         -> PRK a -- ^ Pseudo random key extract salt ikm = PRK $ hmac salt ikm --- | Create a PRK directly from the input key material, skipping any hmacing+-- | Create a PRK directly from the input key material.+--+-- Only use when guaranteed to have a good quality and random data to use directly as key.+-- This effectively skip a HMAC with key=salt and data=key. extractSkip :: (HashAlgorithm a, ByteArrayAccess ikm)             => ikm             -> PRK a@@ -74,4 +76,3 @@                 r       = n - hashLen              in (if n >= hashLen then ti else B.take n ti)               : loop hF ti r (i+1)-
+ Crypto/MAC/CMAC.hs view
@@ -0,0 +1,132 @@+-- |+-- Module      : Crypto.MAC.CMAC+-- License     : BSD-style+-- Maintainer  : Kei Hibino <ex8k.hibino@gmail.com>+-- Stability   : experimental+-- Portability : unknown+--+-- provide the CMAC (Cipher based Message Authentification Code) base algorithm.+-- <http://en.wikipedia.org/wiki/CMAC>+-- <http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf>+--+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Crypto.MAC.CMAC+    ( cmac+    , CMAC+    , subKeys+    ) where++import           Data.Word+import           Data.Bits (setBit, testBit, shiftL)+import           Data.List (foldl')++import           Crypto.Cipher.Types+import           Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, Bytes)+import qualified Crypto.Internal.ByteArray as B++-- | Authentication code+newtype CMAC a = CMAC Bytes+    deriving (ByteArrayAccess)++instance Eq (CMAC a) where+  CMAC b1 == CMAC b2  =  B.constEq b1 b2++-- | compute a MAC using the supplied cipher+cmac :: (ByteArrayAccess bin, BlockCipher cipher)+     => cipher      -- ^ key to compute CMAC with+     -> bin         -- ^ input message+     -> CMAC cipher -- ^ output tag+cmac k msg =+    CMAC $ foldl' (\c m -> ecbEncrypt k $ bxor c m) zeroV ms+  where+    bytes = blockSize k+    zeroV = B.replicate bytes 0 :: Bytes+    (k1, k2) = subKeys k+    ms = cmacChunks k k1 k2 $ B.convert msg++cmacChunks :: (BlockCipher k, ByteArray ba) => k -> ba -> ba -> ba -> [ba]+cmacChunks k k1 k2  =  rec'  where+    rec' msg+      | B.null tl  =  if lack == 0+                      then  [bxor k1 hd]+                      else  [bxor k2 $ hd `B.append` B.pack (0x80 : replicate (lack - 1) 0)]+      | otherwise  =        hd : rec' tl+      where+          bytes = blockSize k+          (hd, tl) = B.splitAt bytes msg+          lack = bytes - B.length hd++-- | make sub-keys used in CMAC+subKeys :: (BlockCipher k, ByteArray ba)+        => k         -- ^ key to compute CMAC with+        -> (ba, ba)  -- ^ sub-keys to compute CMAC+subKeys k = (k1, k2)   where+    ipt = cipherIPT k+    k0 = ecbEncrypt k $ B.replicate (blockSize k) 0+    k1 = subKey ipt k0+    k2 = subKey ipt k1++-- polynomial multiply operation to culculate subkey+subKey :: (ByteArray ba) => [Word8] -> ba -> ba+subKey ipt ws  =  case B.unpack ws of+    []                  ->  B.empty+    w:_  | testBit w 7  ->  B.pack ipt `bxor` shiftL1 ws+         | otherwise    ->  shiftL1 ws++shiftL1 :: (ByteArray ba) => ba -> ba+shiftL1 = B.pack . shiftL1W . B.unpack++shiftL1W :: [Word8] -> [Word8]+shiftL1W []         =  []+shiftL1W ws@(_:ns)  =  rec' $ zip ws (ns ++ [0])   where+    rec'  []         =  []+    rec' ((x,y):ps)  =  w : rec' ps+      where+          w | testBit y 7  =  setBit sl1 0+            | otherwise    =  sl1+            where     sl1 = shiftL x 1++bxor :: ByteArray ba => ba -> ba -> ba+bxor = B.xor+++-----+++cipherIPT :: BlockCipher k => k -> [Word8]+cipherIPT = expandIPT . blockSize   where++-- Data type which represents the smallest irreducibule binary polynomial+-- against specified degree.+--+-- Maximum degree bit and degree 0 bit are omitted.+-- For example, The value /Q 7 2 1/ corresponds to the degree /128/.+-- It represents that the smallest irreducible binary polynomial of degree 128+-- is x^128 + x^7 + x^2 + x^1 + 1.+data IPolynomial+  = Q Int Int Int+---  | T Int++iPolynomial :: Int -> Maybe IPolynomial+iPolynomial = d  where+    d   64  =  Just $ Q 4 3 1+    d  128  =  Just $ Q 7 2 1+    d    _  =  Nothing++-- Expand a tail bit pattern of irreducible binary polynomial+expandIPT :: Int -> [Word8]+expandIPT bytes = expandIPT' bytes ipt  where+    ipt = maybe (error $ "Irreducible binary polynomial not defined against " ++ show nb ++ " bit") id+          $ iPolynomial nb+    nb = bytes * 8++-- Expand a tail bit pattern of irreducible binary polynomial+expandIPT' :: Int         -- ^ width in byte+           -> IPolynomial -- ^ irreducible binary polynomial definition+           -> [Word8]     -- ^ result bit pattern+expandIPT' bytes (Q x y z) =+    reverse . setB x . setB y . setB z . setB 0 $ replicate bytes 0+  where+    setB i ws =  hd ++ setBit (head tl) r : tail tl  where+        (q, r) = i `quotRem` 8+        (hd, tl) = splitAt q ws
Crypto/PubKey/DH.hs view
@@ -23,13 +23,16 @@ import Crypto.Number.ModArithmetic (expSafe) import Crypto.Number.Prime (generateSafePrime) import Crypto.Number.Generate (generateMax)+import Crypto.Number.Serialize (i2ospOf_) import Crypto.Random.Types+import Data.ByteArray (ByteArrayAccess, ScrubbedBytes) import Data.Data  -- | Represent Diffie Hellman parameters namely P (prime), and G (generator). data Params = Params     { params_p :: Integer     , params_g :: Integer+    , params_bits :: Int     } deriving (Show,Read,Eq,Data,Typeable)  -- | Represent Diffie Hellman public number Y.@@ -41,8 +44,8 @@     deriving (Show,Read,Eq,Enum,Real,Num,Ord)  -- | Represent Diffie Hellman shared secret.-newtype SharedKey = SharedKey Integer-    deriving (Show,Read,Eq,Enum,Real,Num,Ord)+newtype SharedKey = SharedKey ScrubbedBytes+    deriving (Show,Eq,ByteArrayAccess)  -- | generate params from a specific generator (2 or 5 are common values) -- we generate a safe prime (a prime number of the form 2p+1 where p is also prime)@@ -51,17 +54,17 @@                -> Integer               -- ^ generator                -> m Params generateParams bits generator =-    (\p -> Params p generator) <$> generateSafePrime bits+    (\p -> Params p generator bits) <$> generateSafePrime bits  -- | generate a private number with no specific property -- this number is usually called X in DH text. generatePrivate :: MonadRandom m => Params -> m PrivateNumber-generatePrivate (Params p _) = PrivateNumber <$> generateMax p+generatePrivate (Params p _ _) = PrivateNumber <$> generateMax p  -- | calculate the public number from the parameters and the private key -- this number is usually called Y in DH text. calculatePublic :: Params -> PrivateNumber -> PublicNumber-calculatePublic (Params p g) (PrivateNumber x) = PublicNumber $ expSafe g x p+calculatePublic (Params p g _) (PrivateNumber x) = PublicNumber $ expSafe g x p  -- | calculate the public number from the parameters and the private key -- this number is usually called Y in DH text.@@ -73,4 +76,4 @@  -- | generate a shared key using our private number and the other party public number getShared :: Params -> PrivateNumber -> PublicNumber -> SharedKey-getShared (Params p _) (PrivateNumber x) (PublicNumber y) = SharedKey $ expSafe y x p+getShared (Params p _ bits) (PrivateNumber x) (PublicNumber y) = SharedKey $ i2ospOf_ (bits + 7 `div` 8) $ expSafe y x p
Crypto/PubKey/ECC/DH.hs view
@@ -19,10 +19,11 @@     ) where  import Crypto.Number.Generate (generateMax)+import Crypto.Number.Serialize (i2ospOf_) import Crypto.PubKey.ECC.Prim (pointMul) import Crypto.Random.Types import Crypto.PubKey.DH (SharedKey(..))-import Crypto.PubKey.ECC.Types (PublicPoint, PrivateNumber, Curve, Point(..))+import Crypto.PubKey.ECC.Types (PublicPoint, PrivateNumber, Curve, Point(..), curveSizeBits) import Crypto.PubKey.ECC.Types (ecc_n, ecc_g, common_curve)  -- | Generating a private number d.@@ -41,6 +42,7 @@ -- | Generating a shared key using our private number and --   the other party public point. getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey-getShared curve db qa = SharedKey x+getShared curve db qa = SharedKey $ i2ospOf_ (nbBits + 7 `div` 8) x   where     Point x _ = pointMul curve db qa+    nbBits    = curveSizeBits curve
Crypto/PubKey/ECC/Types.hs view
@@ -121,7 +121,7 @@     | SEC_t409r1     | SEC_t571k1     | SEC_t571r1-    deriving (Show,Read,Eq,Ord,Enum,Data,Typeable)+    deriving (Show,Read,Eq,Ord,Enum,Bounded,Data,Typeable)  {- curvesOIDs :: [ (CurveName, [Integer]) ]
Crypto/PubKey/ElGamal.hs view
@@ -68,12 +68,12 @@ -- | generate a public number that is for the other party benefits. -- this number is usually called h=g^a generatePublic :: Params -> PrivateNumber -> PublicNumber-generatePublic (Params p g) (PrivateNumber a) = PublicNumber $ expSafe g a p+generatePublic (Params p g _) (PrivateNumber a) = PublicNumber $ expSafe g a p  -- | encrypt with a specified ephemeral key -- do not reuse ephemeral key. encryptWith :: EphemeralKey -> Params -> PublicNumber -> Integer -> (Integer,Integer)-encryptWith (EphemeralKey b) (Params p g) (PublicNumber h) m = (c1,c2)+encryptWith (EphemeralKey b) (Params p g _) (PublicNumber h) m = (c1,c2)     where s  = expSafe h b p           c1 = expSafe g b p           c2 = (s * m) `mod` p@@ -81,12 +81,12 @@ -- | encrypt a message using params and public keys -- will generate b (called the ephemeral key) encrypt :: MonadRandom m => Params -> PublicNumber -> Integer -> m (Integer,Integer)-encrypt params@(Params p _) public m = (\b -> encryptWith b params public m) <$> generateEphemeral q+encrypt params@(Params p _ _) public m = (\b -> encryptWith b params public m) <$> generateEphemeral q     where q = p-1 -- p is prime, hence order of the group is p-1  -- | decrypt message decrypt :: Params -> PrivateNumber -> (Integer, Integer) -> Integer-decrypt (Params p _) (PrivateNumber a) (c1,c2) = (c2 * sm1) `mod` p+decrypt (Params p _ _) (PrivateNumber a) (c1,c2) = (c2 * sm1) `mod` p     where s   = expSafe c1 a p           sm1 = fromJust $ inverse s p -- always inversible in Zp @@ -104,7 +104,7 @@          -> hash            -- ^ collision resistant hash algorithm          -> msg             -- ^ message to sign          -> Maybe Signature-signWith k (Params p g) (PrivateNumber x) hashAlg msg+signWith k (Params p g _) (PrivateNumber x) hashAlg msg     | k >= p-1 || d > 1 = Nothing -- gcd(k,p-1) is not 1     | s == 0            = Nothing     | otherwise         = Just $ Signature (r,s)@@ -125,7 +125,7 @@      -> hash           -- ^ collision resistant hash algorithm      -> msg            -- ^ message to sign      -> m Signature-sign params@(Params p _) priv hashAlg msg = do+sign params@(Params p _ _) priv hashAlg msg = do     k <- generateMax (p-1)     case signWith k params priv hashAlg msg of         Nothing  -> sign params priv hashAlg msg@@ -139,7 +139,7 @@        -> msg        -> Signature        -> Bool-verify (Params p g) (PublicNumber y) hashAlg msg (Signature (r,s))+verify (Params p g _) (PublicNumber y) hashAlg msg (Signature (r,s))     | or [r <= 0,r >= p,s <= 0,s >= (p-1)] = False     | otherwise                            = lhs == rhs     where h   = os2ip $ hashWith hashAlg msg
Crypto/Random.hs view
@@ -5,14 +5,21 @@ -- Stability   : stable -- Portability : good --+{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Crypto.Random     (     -- * Deterministic instances       ChaChaDRG     , SystemDRG+    , Seed+    -- * Seed+    , seedNew+    , seedFromInteger+    , seedToInteger     -- * Deterministic Random class     , getSystemDRG     , drgNew+    , drgNewSeed     , drgNewTest     , withDRG     , withRandomBytes@@ -25,14 +32,37 @@ import Crypto.Random.Types import Crypto.Random.ChaChaDRG import Crypto.Random.SystemDRG-import Data.ByteArray (ByteArray, ScrubbedBytes)+import Data.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes) import Crypto.Internal.Imports +import qualified Crypto.Number.Serialize as Serialize++newtype Seed = Seed ScrubbedBytes+    deriving (ByteArrayAccess)++-- Length for ChaCha DRG seed+seedLength :: Int+seedLength = 40++-- | Create a new Seed from system entropy+seedNew :: MonadRandom randomly => randomly Seed+seedNew = Seed `fmap` getRandomBytes seedLength++-- | Convert a Seed to an integer+seedToInteger :: Seed -> Integer+seedToInteger (Seed b) = Serialize.os2ip b++-- | Convert an integer to a Seed+seedFromInteger :: Integer -> Seed+seedFromInteger i = Seed $ Serialize.i2ospOf_ seedLength (i `mod` 2^(seedLength * 8))+ -- | Create a new DRG from system entropy drgNew :: MonadRandom randomly => randomly ChaChaDRG-drgNew = do-    b <- getRandomBytes 40-    return $ initialize (b :: ScrubbedBytes)+drgNew = drgNewSeed `fmap` seedNew++-- | Create a new DRG from a seed+drgNewSeed :: Seed -> ChaChaDRG+drgNewSeed (Seed seed) = initialize seed  -- | Create a new DRG from 5 Word64. --
cbits/cryptonite_keccak.c view
@@ -99,8 +99,9 @@  void cryptonite_keccak_init(struct keccak_ctx *ctx, uint32_t hashlen) {-	memset(ctx, 0, sizeof(*ctx));-	ctx->bufsz = 200 - 2 * (hashlen / 8);+	int bufsz = 200 - 2 * (hashlen / 8);+	memset(ctx, 0, sizeof(*ctx) + bufsz);+	ctx->bufsz = bufsz; }  void cryptonite_keccak_update(struct keccak_ctx *ctx, uint8_t *data, uint32_t len)
cbits/cryptonite_keccak.h view
@@ -31,7 +31,7 @@ 	uint32_t bufindex; 	uint32_t bufsz; 	uint64_t state[25];-	uint8_t  buf[144]; /* minimum SHA3-224, otherwise buffer need increases */+	uint8_t  buf[0]; /* maximum SHA3-224 = 144, otherwise buffer need decrease */ };  #define SHA3_CTX_SIZE		sizeof(struct keccak_ctx)
cbits/cryptonite_sha3.c view
@@ -99,8 +99,9 @@  void cryptonite_sha3_init(struct sha3_ctx *ctx, uint32_t hashlen) {-	memset(ctx, 0, sizeof(*ctx));-	ctx->bufsz = 200 - 2 * (hashlen / 8);+	int bufsz = 200 - 2 * (hashlen / 8);+	memset(ctx, 0, sizeof(*ctx) + bufsz);+	ctx->bufsz = bufsz; }  void cryptonite_sha3_update(struct sha3_ctx *ctx, const uint8_t *data, uint32_t len)
cbits/cryptonite_sha3.h view
@@ -31,7 +31,7 @@ 	uint32_t bufindex; 	uint32_t bufsz; 	uint64_t state[25];-	uint8_t  buf[144]; /* minimum SHA3-224, otherwise buffer need increases */+	uint8_t  buf[0]; /* maximum SHA3-224 is 144 bytes, otherwise buffer can be decreases */ };  #define SHA3_CTX_SIZE		sizeof(struct sha3_ctx)
cryptonite.cabal view
@@ -1,5 +1,5 @@ Name:                cryptonite-Version:             0.13+Version:             0.14 Synopsis:            Cryptography Primitives sink Description:     A repository of cryptographic primitives.@@ -57,7 +57,7 @@   Manual:            True  Flag support_rdrand-  Description:       allow compilation with AESNI on system and architecture that supports it+  Description:       allow compilation with RDRAND on system and architecture that supports it   Default:           True   Manual:            True @@ -100,6 +100,7 @@                      Crypto.Data.AFIS                      Crypto.Data.Padding                      Crypto.Error+                     Crypto.MAC.CMAC                      Crypto.MAC.Poly1305                      Crypto.MAC.HMAC                      Crypto.Number.Basic@@ -303,6 +304,7 @@                      KAT_Curve25519                      KAT_DES                      KAT_Ed25519+                     KAT_CMAC                      KAT_HMAC                      KAT_PBKDF2                      KAT_PubKey.DSA
+ tests/KAT_CMAC.hs view
@@ -0,0 +1,210 @@++module KAT_CMAC (tests) where++import qualified Crypto.MAC.CMAC as CMAC+import           Crypto.Cipher.Types (Cipher, cipherInit, BlockCipher, ecbEncrypt, blockSize)+import           Crypto.Error (eitherCryptoError)+import           Crypto.Cipher.AES (AES128, AES192, AES256)+import           Crypto.Cipher.TripleDES (DES_EDE3, DES_EDE2)++import           Imports++import           Data.Char (digitToInt)+import qualified Data.ByteString as BS+import qualified Data.ByteArray as B+++hxs :: String -> ByteString+hxs = BS.pack . rec' where+    dtoW8 = fromIntegral . digitToInt+    rec' (' ':xs)  =  rec' xs+    rec' (x:y:xs)  =  dtoW8 x * 16 + dtoW8 y : rec' xs+    rec' [_]       =  error "hxs: invalid hex pattern."+    rec' []        =  []++unsafeCipher :: Cipher k => ByteString -> k+unsafeCipher = either (error . show) id . eitherCryptoError . cipherInit++ecb0 :: BlockCipher k => k -> ByteString+ecb0 k = ecbEncrypt k $ BS.replicate (blockSize k) 0++{- Test vectors from NIST data-sheet+   (AES128-CMAC, AES192-CMAC, AES256-CMAC, Three Key TDEA, Two Key TDEA)+   http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf+   The data of AES128-CMAC is same as them in RFC4493.+ -}++msg512 :: ByteString+msg512 =+  hxs $+  "6bc1bee2 2e409f96 e93d7e11 7393172a" +++  "ae2d8a57 1e03ac9c 9eb76fac 45af8e51" +++  "30c81c46 a35ce411 e5fbc119 1a0a52ef" +++  "f69f2445 df4f9b17 ad2b417b e66c3710"++msg320 :: ByteString+msg320 = BS.take 40 msg512++msg256 :: ByteString+msg256 = BS.take 32 msg512++msg160 :: ByteString+msg160 = BS.take 20 msg512++msg128 :: ByteString+msg128 = BS.take 16 msg512++msg64 :: ByteString+msg64 = BS.take 8 msg512++msg0 :: ByteString+msg0 = BS.empty++bsCMAC :: BlockCipher k => k -> ByteString -> ByteString+bsCMAC k = B.convert . CMAC.cmac k++gAES128 :: TestTree+gAES128 =+    igroup "aes128"+    [ ecb0 aes128key @?=  hxs "7df76b0c 1ab899b3 3e42f047 b91b546f"+    , aes128k1 @?=        hxs "fbeed618 35713366 7c85e08f 7236a8de"+    , aes128k2 @?=        hxs "f7ddac30 6ae266cc f90bc11e e46d513b"++    , bsCMAC aes128key msg0+      @?=                 hxs "bb1d6929 e9593728 7fa37d12 9b756746"+    , bsCMAC aes128key msg128+      @?=                 hxs "070a16b4 6b4d4144 f79bdd9d d04a287c"+    , bsCMAC aes128key msg320+      @?=                 hxs "dfa66747 de9ae630 30ca3261 1497c827"+    , bsCMAC aes128key msg512+      @?=                 hxs "51f0bebf 7e3b9d92 fc497417 79363cfe"+    ]+  where+    aes128key :: AES128+    aes128key =+        unsafeCipher $ hxs+        "2b7e1516 28aed2a6 abf71588 09cf4f3c"++    aes128k1, aes128k2 :: ByteString+    (aes128k1, aes128k2) = CMAC.subKeys aes128key+++gAES192 :: TestTree+gAES192 =+    igroup "aes192"+    [ ecb0 aes192key @?=  hxs "22452d8e 49a8a593 9f7321ce ea6d514b"+    , aes192k1 @?=        hxs "448a5b1c 93514b27 3ee6439d d4daa296"+    , aes192k2 @?=        hxs "8914b639 26a2964e 7dcc873b a9b5452c"++    , bsCMAC aes192key msg0+      @?=                 hxs "d17ddf46 adaacde5 31cac483 de7a9367"+    , bsCMAC aes192key msg128+      @?=                 hxs "9e99a7bf 31e71090 0662f65e 617c5184"+    , bsCMAC aes192key msg320+      @?=                 hxs "8a1de5be 2eb31aad 089a82e6 ee908b0e"+    , bsCMAC aes192key msg512+      @?=                 hxs "a1d5df0e ed790f79 4d775896 59f39a11"+    ]+  where+    aes192key :: AES192+    aes192key =+        unsafeCipher . hxs $+        "8e73b0f7 da0e6452 c810f32b 809079e5" +++        "62f8ead2 522c6b7b"++    aes192k1, aes192k2 :: ByteString+    (aes192k1, aes192k2) = CMAC.subKeys aes192key++gAES256 :: TestTree+gAES256 =+    igroup "aes256"+    [ ecb0 aes256key @?=  hxs "e568f681 94cf76d6 174d4cc0 4310a854"+    , aes256k1 @?=        hxs "cad1ed03 299eedac 2e9a9980 8621502f"+    , aes256k2 @?=        hxs "95a3da06 533ddb58 5d353301 0c42a0d9"++    , bsCMAC aes256key msg0+      @?=                 hxs "028962f6 1b7bf89e fc6b551f 4667d983"+    , bsCMAC aes256key msg128+      @?=                 hxs "28a7023f 452e8f82 bd4bf28d 8c37c35c"+    , bsCMAC aes256key msg320+      @?=                 hxs "aaf3d8f1 de5640c2 32f5b169 b9c911e6"+    , bsCMAC aes256key msg512+      @?=                 hxs "e1992190 549f6ed5 696a2c05 6c315410"+    ]+  where+    aes256key :: AES256+    aes256key =+        unsafeCipher . hxs $+        "603deb10 15ca71be 2b73aef0 857d7781" +++        "1f352c07 3b6108d7 2d9810a3 0914dff4"++    aes256k1, aes256k2 :: ByteString+    (aes256k1, aes256k2) = CMAC.subKeys aes256key++gTDEA3 :: TestTree+gTDEA3 =+    igroup "Three Key TDEA"+    [ ecb0 tdea3key @?=  hxs "c8cc74e9 8a7329a2"+    , tdea3k1 @?=        hxs "9198e9d3 14e6535f"+    , tdea3k2 @?=        hxs "2331d3a6 29cca6a5"++    , bsCMAC tdea3key msg0+      @?=                hxs "b7a688e1 22ffaf95"+    , bsCMAC tdea3key msg64+      @?=                hxs "8e8f2931 36283797"+    , bsCMAC tdea3key msg160+      @?=                hxs "743ddbe0 ce2dc2ed"+    , bsCMAC tdea3key msg256+      @?=                hxs "33e6b109 2400eae5"+    ]+  where+    tdea3key :: DES_EDE3+    tdea3key =+        unsafeCipher . hxs $+        "8aa83bf8 cbda1062" +++        "0bc1bf19 fbb6cd58" +++        "bc313d4a 371ca8b5"++    tdea3k1, tdea3k2 :: ByteString+    (tdea3k1, tdea3k2) = CMAC.subKeys tdea3key++gTDEA2 :: TestTree+gTDEA2 =+    igroup "Two Key TDEA"+    [ ecb0 tdea2key @?=  hxs "c7679b9f 6b8d7d7a"+    , tdea2k1 @?=        hxs "8ecf373e d71afaef"+    , tdea2k2 @?=        hxs "1d9e6e7d ae35f5c5"++    , bsCMAC tdea2key msg0+      @?=                hxs "bd2ebf9a 3ba00361"+    , bsCMAC tdea2key msg64+      @?=                hxs "4ff2ab81 3c53ce83"+    , bsCMAC tdea2key msg160+      @?=                hxs "62dd1b47 1902bd4e"+    , bsCMAC tdea2key msg256+      @?=                hxs "31b1e431 dabc4eb8"+    ]+  where+    tdea2key :: DES_EDE2+    tdea2key =+          unsafeCipher . hxs $+          "4cf15134 a2850dd5" +++          "8a3d10ba 80570d38"++    tdea2k1, tdea2k2 :: ByteString+    (tdea2k1, tdea2k2) = CMAC.subKeys tdea2key++igroup :: TestName -> [Assertion] -> TestTree+igroup nm = testGroup nm . zipWith (flip ($)) [1..] . map icase+  where+    icase c i = testCase (show (i :: Int)) c++nistVectors :: TestTree+nistVectors =+    testGroup "KAT - NIST test vectors"+    [ gAES128, gAES192, gAES256, gTDEA3, gTDEA2 ]++tests :: TestTree+tests =+    testGroup "CMAC"+    [ nistVectors ]
tests/Tests.hs view
@@ -10,6 +10,7 @@ import qualified Salsa import qualified ChaCha import qualified ChaChaPoly1305+import qualified KAT_CMAC import qualified KAT_HMAC import qualified KAT_HKDF import qualified KAT_PBKDF2@@ -35,6 +36,7 @@     , Padding.tests     , testGroup "MAC"         [ Poly1305.tests+        , KAT_CMAC.tests         , KAT_HMAC.tests         ]     , KAT_Curve25519.tests