diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/Crypto/ConstructHash/MiyaguchiPreneel.hs b/Crypto/ConstructHash/MiyaguchiPreneel.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/ConstructHash/MiyaguchiPreneel.hs
@@ -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
diff --git a/Crypto/Data/Padding.hs b/Crypto/Data/Padding.hs
--- a/Crypto/Data/Padding.hs
+++ b/Crypto/Data/Padding.hs
@@ -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 --git a/Crypto/KDF/Scrypt.hs b/Crypto/KDF/Scrypt.hs
--- a/Crypto/KDF/Scrypt.hs
+++ b/Crypto/KDF/Scrypt.hs
@@ -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 --git a/cbits/cryptonite_rdrand.c b/cbits/cryptonite_rdrand.c
--- a/cbits/cryptonite_rdrand.c
+++ b/cbits/cryptonite_rdrand.c
@@ -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);
diff --git a/cryptonite.cabal b/cryptonite.cabal
--- a/cryptonite.cabal
+++ b/cryptonite.cabal
@@ -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
diff --git a/tests/KAT_MiyaguchiPreneel.hs b/tests/KAT_MiyaguchiPreneel.hs
new file mode 100644
--- /dev/null
+++ b/tests/KAT_MiyaguchiPreneel.hs
@@ -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 --git a/tests/Padding.hs b/tests/Padding.hs
--- a/tests/Padding.hs
+++ b/tests/Padding.hs
@@ -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 --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_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
