diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/Crypto/Hash/Keccak.hs b/Crypto/Hash/Keccak.hs
--- a/Crypto/Hash/Keccak.hs
+++ b/Crypto/Hash/Keccak.hs
@@ -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
diff --git a/Crypto/Hash/SHA3.hs b/Crypto/Hash/SHA3.hs
--- a/Crypto/Hash/SHA3.hs
+++ b/Crypto/Hash/SHA3.hs
@@ -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
diff --git a/Crypto/KDF/BCrypt.hs b/Crypto/KDF/BCrypt.hs
--- a/Crypto/KDF/BCrypt.hs
+++ b/Crypto/KDF/BCrypt.hs
@@ -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).
diff --git a/Crypto/KDF/HKDF.hs b/Crypto/KDF/HKDF.hs
--- a/Crypto/KDF/HKDF.hs
+++ b/Crypto/KDF/HKDF.hs
@@ -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)
-
diff --git a/Crypto/MAC/CMAC.hs b/Crypto/MAC/CMAC.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/MAC/CMAC.hs
@@ -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
diff --git a/Crypto/PubKey/DH.hs b/Crypto/PubKey/DH.hs
--- a/Crypto/PubKey/DH.hs
+++ b/Crypto/PubKey/DH.hs
@@ -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
diff --git a/Crypto/PubKey/ECC/DH.hs b/Crypto/PubKey/ECC/DH.hs
--- a/Crypto/PubKey/ECC/DH.hs
+++ b/Crypto/PubKey/ECC/DH.hs
@@ -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
diff --git a/Crypto/PubKey/ECC/Types.hs b/Crypto/PubKey/ECC/Types.hs
--- a/Crypto/PubKey/ECC/Types.hs
+++ b/Crypto/PubKey/ECC/Types.hs
@@ -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]) ]
diff --git a/Crypto/PubKey/ElGamal.hs b/Crypto/PubKey/ElGamal.hs
--- a/Crypto/PubKey/ElGamal.hs
+++ b/Crypto/PubKey/ElGamal.hs
@@ -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
diff --git a/Crypto/Random.hs b/Crypto/Random.hs
--- a/Crypto/Random.hs
+++ b/Crypto/Random.hs
@@ -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.
 --
diff --git a/cbits/cryptonite_keccak.c b/cbits/cryptonite_keccak.c
--- a/cbits/cryptonite_keccak.c
+++ b/cbits/cryptonite_keccak.c
@@ -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)
diff --git a/cbits/cryptonite_keccak.h b/cbits/cryptonite_keccak.h
--- a/cbits/cryptonite_keccak.h
+++ b/cbits/cryptonite_keccak.h
@@ -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)
diff --git a/cbits/cryptonite_sha3.c b/cbits/cryptonite_sha3.c
--- a/cbits/cryptonite_sha3.c
+++ b/cbits/cryptonite_sha3.c
@@ -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)
diff --git a/cbits/cryptonite_sha3.h b/cbits/cryptonite_sha3.h
--- a/cbits/cryptonite_sha3.h
+++ b/cbits/cryptonite_sha3.h
@@ -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)
diff --git a/cryptonite.cabal b/cryptonite.cabal
--- a/cryptonite.cabal
+++ b/cryptonite.cabal
@@ -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
diff --git a/tests/KAT_CMAC.hs b/tests/KAT_CMAC.hs
new file mode 100644
--- /dev/null
+++ b/tests/KAT_CMAC.hs
@@ -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 ]
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -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
