diff --git a/Codec/Crypto/ConvertRNG.hs b/Codec/Crypto/ConvertRNG.hs
--- a/Codec/Crypto/ConvertRNG.hs
+++ b/Codec/Crypto/ConvertRNG.hs
@@ -15,7 +15,7 @@
 @
 
     Specifically, a block cipher can be converted to generate a
-    @CryptoRandomGen@, which in turn can be converted to provide the
+    'CryptoRandomGen', which in turn can be converted to provide the
     @RandomGen@ interface.
 
   -}
@@ -26,7 +26,7 @@
 module Codec.Crypto.ConvertRNG 
   ( BCtoCRG(..), convertCRG     
   , CRGtoRG()
-  , CRGtoRG0(..) -- Inefficient version for testing...
+  , CRGtoRG_Unbuffered(..) -- Inefficient version for testing...
   )
 where
 
@@ -72,22 +72,22 @@
 
 
 -- | Converting CryptoRandomGen to RandomGen.
---   This naive version is probably pretty inefficent:
-data CRGtoRG0 a = CRGtoRG0 a
-instance CryptoRandomGen g => RandomGen (CRGtoRG0 g) where 
-   next  (CRGtoRG0 g) = 
+--   This naive version is inefficent and should not be used in most cases.
+data CRGtoRG_Unbuffered a = CRGtoRG_Unbuffered a
+instance CryptoRandomGen g => RandomGen (CRGtoRG_Unbuffered g) where 
+   next  (CRGtoRG_Unbuffered g) = 
 --       case genBytes (max bytes_in_int (keyLength g `quot` 8)) g of 
        case genBytes bytes_in_int g of 
          Left err -> error$ "CryptoRandomGen genBytes error: " ++ show err
 	 Right (bytes,g') -> 
            case decode bytes of 
 	      Left err -> error$ "Deserialization error:"++ show err
-	      Right n -> (n, CRGtoRG0 g')
+	      Right n -> (n, CRGtoRG_Unbuffered g')
 	     
-   split (CRGtoRG0 g) = 
+   split (CRGtoRG_Unbuffered g) = 
        case splitGen g of 
          Left err      -> error$ "CryptoRandomGen splitGen error:"++ show err
-	 Right (g1,g2) -> (CRGtoRG0 g1, CRGtoRG0 g2)
+	 Right (g1,g2) -> (CRGtoRG_Unbuffered g1, CRGtoRG_Unbuffered g2)
 
 -- Another option would be to amortize overhead by generating a large
 -- buffer of random bits at once.
@@ -98,8 +98,9 @@
 -- steps = 128 `quot` bits_in_int
 
 ------------------------------------------------------------
--- | Converting CryptoRandomGen to RandomGen.
---   Keep a buffer of random bits and an index into that buffer.
+-- | Convert CryptoRandomGen to RandomGen.  This version is buffered.
+--   That is, it fills a sizable buffer with random bits in bulk and
+--   advances an index into that buffer as random bits are requested.
 data CRGtoRG a = CRGtoRG a 
     {-#UNPACK#-}!         (FP.ForeignPtr Int)
     {-#UNPACK#-}!         Int
@@ -139,8 +140,8 @@
 -- Again there's the tension with UndecidableInstances vs explicit lifting.
 
 -- | A BlockCipher can generate random numbers.
---   When lifting we include a counter which increments as random numbers are generated:
 data BCtoCRG a = BCtoCRG a Word64
+-- When lifting we include a counter which increments as random numbers are generated.
 
 instance BlockCipher x => CryptoRandomGen (BCtoCRG x) where 
   newGen  bytes = case buildKey bytes of Nothing -> Left NotEnoughEntropy 
diff --git a/Codec/Crypto/GladmanAES.hsc b/Codec/Crypto/GladmanAES.hsc
--- a/Codec/Crypto/GladmanAES.hsc
+++ b/Codec/Crypto/GladmanAES.hsc
@@ -18,7 +18,8 @@
 import Crypto.Classes
 import Crypto.Types
 import Data.Tagged
-import Data.Serialize
+-- use import list for Serialize to avoid conflict with `ensure` function
+import Data.Serialize(Serialize, Get, get, put, getByteString, putByteString)
 
 import Foreign
 import Control.Applicative
diff --git a/Codec/Crypto/IntelAES.hs b/Codec/Crypto/IntelAES.hs
deleted file mode 100644
--- a/Codec/Crypto/IntelAES.hs
+++ /dev/null
@@ -1,129 +0,0 @@
-{-|
-     Module      :  Codec.Crypto.IntelAES
-     Copyright   :  (c) Ryan Newton 2011
-     License     :  BSD-style (see the file LICENSE)
-     Maintainer  :  rrnewton@gmail.com
-     Stability   :  experimental
-     Portability :  linux only (NEEDS PORTING)
-
-     This module provides an AES implementation that will test the CPU
-     ID and use hardware acceleration where available, otherwise it will
-     fall back to Dr. Brian Gladman's software implementation.
-
-     This module also exports a random number generator based on AES
-     both using the System.Random.RandomGen interface and the
-     Codec.Crypto.Random.
-
-  -}
-{-# OPTIONS_GHC -fwarn-unused-imports #-}
-{-# LANGUAGE ForeignFunctionInterface, CPP, ScopedTypeVariables  #-}
-
-module Codec.Crypto.IntelAES
-    (
-      mkAESGen,
-      CompoundAESRNG(), 
-      supportsAESNI,
-     -- Plus, instances exported of course.
-      testIntelAES
-    )
-where 
-
-import qualified Codec.Crypto.IntelAES.AESNI      as NI
-import qualified Codec.Crypto.GladmanAES as GA
-import GHC.IO (unsafeDupablePerformIO)
-import Data.Tagged
-import Data.Word
-import Data.Serialize
-import qualified Data.ByteString as B
-import Crypto.Random (CryptoRandomGen(..), GenError(..), splitGen, genBytes)
-import Crypto.Types
-import Codec.Crypto.ConvertRNG 
-import Debug.Trace
-
-newtype CompoundCRG = 
-  CompoundCRG 
-   (Either (BCtoCRG (NI.IntelAES NI.N128))
-	   (BCtoCRG (GA.AES GA.N128)))
-
--- | A type representing an AES-based random number generator which
---   will use AESNI instructions when available, and invoke the
---   portable Gladman implementation when not.
-type CompoundAESRNG = CRGtoRG CompoundCRG
-
--- | Simple function to create a random number generator from an Int,
---   analogous to `System.Random.newStdGen`.  Only 128-bit encryption
---   is provided for now.
-mkAESGen :: Int -> CompoundAESRNG
-mkAESGen int = convertCRG gen
-   where
-  Right (gen :: CompoundCRG) = newGen (B.append halfseed halfseed )
-  halfseed = encode word64
-  word64 = fromIntegral int :: Word64
-
-
-
--- foreign import ccall unsafe "iaesni.h" check_for_aes_instructions :: IO Bool
-foreign import ccall unsafe "iaesni.h" check_for_aes_instructions :: Bool
-
--- | Does the machine support AESNI instructions?
-supportsAESNI :: Bool
-supportsAESNI = check_for_aes_instructions
-
-{-# INLINE mapRight #-}
-mapRight fn x@(Left _) = x
-mapRight fn (Right x)  = Right$ fn x
-
-{-# INLINE mapSnd #-}
-mapSnd fn (x,y) = (x,fn y)
-
-
-instance CryptoRandomGen CompoundCRG where 
-
---  newGen :: B.ByteString -> Either GenError CompoundCRG
-  newGen = 
---     if unsafeDupablePerformIO check_for_aes_instructions
---     trace ("Checked for AES instructions: "++ show check_for_aes_instructions)$
-     if check_for_aes_instructions
-     -- Ick, boilerplate:
-     then \bytes -> case newGen bytes of Left err  -> Left err
-					 Right gen -> Right$ CompoundCRG$ Left gen
-     else \bytes -> case newGen bytes of Left err  -> Left err
-					 Right gen -> Right$ CompoundCRG$ Right gen
-
-  genSeedLength = Tagged 128
-
- 
-  -- ByteLength -> CompoundCRG -> Either GenError (B.ByteString, CompoundCRG)
-  genBytes req (CompoundCRG (Left gen)) = 
--- Let's try to reduce that boilerplate if we can...
-#if 0
-    mapRight (mapSnd (CompoundCRG . Left) ) $ genBytes req gen
-#else
-    case genBytes req gen of 
-      Left  err  -> Left err
-      Right (bytes,gen') -> Right (bytes, CompoundCRG (Left gen'))
-#endif
-
--- <boilerplate> OUCH
-  genBytes req (CompoundCRG (Right gen)) = 
-    case genBytes req gen of 
-      Left  err  -> Left err
-      Right (bytes,gen') -> Right (bytes, CompoundCRG (Right gen'))
-  reseed bs (CompoundCRG (Left gen)) = 
-    case reseed bs gen of 
-      Left  err  -> Left err
-      Right gen' -> Right (CompoundCRG (Left gen'))
-  reseed bs (CompoundCRG (Right gen)) = 
-    case reseed bs gen of 
-      Left  err  -> Left err
-      Right gen' -> Right (CompoundCRG (Right gen'))
--- </boilerplate>
-
-
-
-testIntelAES = do 
-  putStrLn$ "Running crude tests."
---  b <- check_for_aes_instructions
-  let b = check_for_aes_instructions
-  putStrLn$ "Machine supports AESNI: "++ show b
-
diff --git a/Codec/Crypto/IntelAES/AESNI.hs b/Codec/Crypto/IntelAES/AESNI.hs
--- a/Codec/Crypto/IntelAES/AESNI.hs
+++ b/Codec/Crypto/IntelAES/AESNI.hs
@@ -29,7 +29,7 @@
     , mkAESGen192, mkAESGen256
 
     -- Inefficient version for testing:
-    , mkAESGen0, SimpleAESRNG0
+    , mkAESGen0, SimpleAESRNG_Unbuffered
     , IntelAES, N128, N192, N256
      -- Plus, instances exported of course.
     )
@@ -87,9 +87,9 @@
 
 
 -- | TEMP: Inefficient version for testing.
-type SimpleAESRNG0 = CRGtoRG0 (BCtoCRG (IntelAES N128))
-mkAESGen0 :: Int -> SimpleAESRNG0
-mkAESGen0 int = CRGtoRG0 gen
+type SimpleAESRNG_Unbuffered = CRGtoRG_Unbuffered (BCtoCRG (IntelAES N128))
+mkAESGen0 :: Int -> SimpleAESRNG_Unbuffered
+mkAESGen0 int = CRGtoRG_Unbuffered gen
  where
   Right (gen :: BCtoCRG (IntelAES N128)) = newGen (B.append halfseed halfseed )
   halfseed = encode word64
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -39,6 +39,7 @@
   setCurrentDirectory "./cbits/"
   system "make clean"
   setCurrentDirectory ".."
+  system "rm -f benchmark-intel-aes-rng"
   putStrLn$ "  [intel-aes] Done.  Now running normal cabal clean action.\n"
   (cleanHook simpleUserHooks) desc () hooks flags
 
@@ -79,8 +80,8 @@
       -- I'm not sure what the best policy is.  For now I'm adding
       -- BOTH the build dir and the eventual install dir...
       -- This will allow the package to function when it is built-but-not-installed.
-      newO = ("-Wl,-rpath=" ++ libd) : 
-	     ("-Wl,-rpath=" ++ cbitsd) : 
+      newO = ("-Wl,-rpath," ++ libd) :
+	     ("-Wl,-rpath," ++ cbitsd) :
 	     oldO
       cbitsd = root++"/cbits/"
       newlbi = lbi { ldOptions = newO 
@@ -88,7 +89,7 @@
       -- Whew... nested record updates are painful:
       desc3 = desc { library = Just (lib { libBuildInfo = newlbi})}
 
-  putStrLn$ "  [intel-aes] Modified package info. " 
+  putStrLn$ "  [intel-aes] Modified package description structure with extra options. " 
   return desc3
 
 
@@ -109,11 +110,7 @@
 my_preBuild args flags = do 
   putStrLn$ "\n================================================================================"
   let 
-      ext = case Info.os of 
-	      "linux"   -> ".so"
-	      "mac"     -> ".dylib"
-	      "windows" -> ".dll"
-	      _         -> error$ "Unexpected "
+      ext = libext
       cached_so = "./cbits/prebuilt/libintel_aes_"++ Info.os ++"_"++ Info.arch ++ ext
       dest = "./cbits/libintel_aes"++ext
   e <- doesFileExist cached_so
@@ -147,11 +144,18 @@
   putStrLn$ "\n================================================================================"
   desc2 <- patchDesc desc linfo
   libd <- readFile tmpfile 
-  let dest = (libd ++ "/libintel_aes.so")
+  let dest = (libd ++ "/libintel_aes" ++ libext)
   putStrLn$ "  [intel-aes] Copying shared library to: " ++ show dest
   system$ "mkdir -p "++ libd -- NONPORTABLE
-  copyFile "./cbits/libintel_aes.so" dest
+  copyFile ("./cbits/libintel_aes"++libext) dest
   putStrLn$ "  [intel-aes] Done copying."
   -- removeFile tmpfile -- Might install more than once, right?
   putStrLn$ "================================================================================\n"
   (instHook simpleUserHooks) desc2 linfo hooks flags
+
+libext :: String
+libext = case Info.os of
+	      "linux"   -> ".so"
+	      "darwin"  -> ".dylib"
+	      "windows" -> ".dll"
+	      _         -> error$ "Unexpected OS: " ++ (Info.os)
diff --git a/SimpleRNGBench.hs b/SimpleRNGBench.hs
deleted file mode 100644
--- a/SimpleRNGBench.hs
+++ /dev/null
@@ -1,367 +0,0 @@
-#!/usr/bin/env runhaskell
-{-# LANGUAGE BangPatterns, ScopedTypeVariables, ForeignFunctionInterface #-}
--- | A simple script to do some very basic timing of the RNGs.
-
---   It is important that we also run established stastical tests on
---   these RNGs a some point...
-
-module Main where
-
-import qualified Codec.Encryption.BurtonRNGSlow as BS
-
---import qualified Codec.Crypto.IntelAES.GladmanAES  as GA
-import qualified Codec.Crypto.GladmanAES           as GA
-import qualified Codec.Crypto.IntelAES.AESNI       as NI
-import qualified Codec.Crypto.IntelAES             as IA
-import qualified Codec.Crypto.ConvertRNG           as CR
--- import qualified Codec.Crypto.AES.Random        as Svein
-
-import System.Exit (exitSuccess, exitFailure)
-import System.Environment
-import System.Random
--- import System.PosixCompat (sleep)
-import System.Posix (sleep)
-import System.CPUTime  (getCPUTime)
--- import Data.Time.Clock (diffUTCTime)
-import System.CPUTime.Rdtsc
-import System.Console.GetOpt
-
-import GHC.Conc
-import Control.Concurrent
-import Control.Monad 
-import Control.Concurrent.Chan
-import Control.Exception
-
-import Crypto.Random (CryptoRandomGen(..))
-
-import Data.IORef
-import Data.List
-import Data.Int
-import Data.Word
-import Data.List.Split
-import Data.Serialize
-import qualified Data.ByteString as B
-import Text.Printf
-
-import Foreign.Ptr
-import Foreign.ForeignPtr
-import Foreign.Storable (peek,poke)
-
-import Benchmark.BinSearch
-
-----------------------------------------------------------------------------------------------------
--- TEMP: MOVE ME ELSEWHERE:
-
-mkAESGen_gladman :: Int -> CR.CRGtoRG (CR.BCtoCRG (GA.AES GA.N128))
-mkAESGen_gladman int = CR.convertCRG gen
- where
-  Right (gen :: CR.BCtoCRG (GA.AES GA.N128)) = newGen (B.append halfseed halfseed )
-  halfseed = encode word64
-  word64 = fromIntegral int :: Word64
-
-
-mkAESGen_gladman0 :: Int -> CR.CRGtoRG0 (CR.BCtoCRG (GA.AES GA.N128))
-mkAESGen_gladman0 int = CR.CRGtoRG0 gen
- where
-  Right (gen :: CR.BCtoCRG (GA.AES GA.N128)) = newGen (B.append halfseed halfseed )
-  halfseed = encode word64
-  word64 = fromIntegral int :: Word64
-
-
-----------------------------------------------------------------------------------------------------
--- Miscellaneous helpers:
-
--- I cannot *believe* there is not a standard call or an
--- easily-findable hackage library supporting locale-based printing of
--- numbers. [2011.01.28]
-commaint :: Integral a => a -> String
-commaint n = 
-   reverse $
-   concat $
-   intersperse "," $ 
-   chunk 3 $ 
-   reverse (show n)
-
-padleft n str | length str >= n = str
-padleft n str | otherwise       = take (n - length str) (repeat ' ') ++ str
-
-padright n str | length str >= n = str
-padright n str | otherwise       = str ++ take (n - length str) (repeat ' ')
-
-fmt_num n = if n < 100 
-	    then printf "%.2f" n
-	    else commaint (round n)
-
--- WARNING! This is not actually good enough.  Even if we use forkOS
--- we would have to go further and pin the OS thread (e.g. in linux)
--- to keep the OS from waking up the process on a different core.
-measure_freq :: IO Int64
-measure_freq = do 
-   -- We measure the clock frequency on a bound thread.
-   -- Otherwise we can get really screwy results from rdtsc if we
-   -- migrate physical threads when we sleep or threadDelay.
-   tmpchan <- newChan
-   forkOS $ do 
-      t1 <- rdtsc
-      -- sleep 1
-      threadDelay (1000*1000)
-      t2 <- rdtsc
-      -- Just to be careful let's make sure this doesn't happen (this was how I found the problem before forkOS):
-      when (t2 < t1) $ 
-        putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"
-      writeChan tmpchan (if t2>t1 then t2-t1 else t1-t2)
-   freq <- readChan tmpchan
-   return (fromIntegral freq)
-
--- This version simply busy-waits to stay on the same core:
--- WOW! I'm STILL experiencing the non-monotonic rdtsc, even when not compiled with -threaded.
--- It can't be overflow can it?  The counter should be 64 bit...
---
--- UPDATE: [2011.01.28] This was a bug in the rdtsc package that dropping the precision to 32 bits.
-measure_freq2 :: IO Int64
-measure_freq2 = do 
-  let second = 1000 * 1000 * 1000 * 1000 -- picoseconds are annoying
-  t1 <- rdtsc 
-  start <- getCPUTime
-  let loop !n !last = 
-       do t2 <- rdtsc 
-	  when (t2 < last) $
-	       putStrLn$ "COUNTERS WRAPPED "++ show (last,t2) 
-	  cput <- getCPUTime		
-	  if (cput - start < second) 
-	   then loop (n+1) t2
-	   else return (n,t2)
-  (n,t2) <- loop 0 t1
-  putStrLn$ "  Approx getCPUTime calls per second: "++ commaint n
-  when (t2 < t1) $ 
-    putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"
-
-  return$ fromIntegral (t2 - t1)
-
-----------------------------------------------------------------------------------------------------
--- Drivers to get random numbers repeatedly.
-
-incr !counter = 
-  do -- modifyIORef counter (+1)d
-     -- Incrementing counter strictly (avoiding stack overflow) is annoying:
-     c <- readIORef counter
-     let c' = c+1
-     evaluate c'
-     writeIORef counter c'     
-
-loop :: RandomGen g => IORef Int -> (Int,g) -> IO b
-loop !counter !(!n,!g) = 
-  do incr counter
---     putStr (show n); putChar ' '
-     loop counter (next g)
-
-data NoopRNG = NoopRNG
-instance RandomGen NoopRNG where 
-  split g = (g,g)
-  next g  = (0,g)
-
---foreign import ccall "cbits/c_test.c" blast_rands :: Ptr Int -> Ptr Int -> IO ()
-
-type Kern = Int -> Ptr Int -> IO ()
-
--- [2011.01.28] Changing this to take "count" and "accumulator ptr" as arguments:
-foreign import ccall "cbits/c_test.c" blast_rands :: Kern
-foreign import ccall "cbits/c_test.c" store_loop  :: Kern
-foreign import ccall unsafe "stdlib.hs" rand :: IO Int
-
-loop2 :: IORef Int -> IO ()
-loop2 !counter = 
-  do incr counter
-     n <- rand
-     loop2 counter 
-
-
-----------------------------------------------------------------------------------------------------
--- Timing:
-
-timeit numthreads freq msg mkgen =
-  do 
-     counters <- forM [1..numthreads] (const$ newIORef 1) 
-     tids <- forM counters $ \counter -> 
-	        forkIO $ loop counter (next$ mkgen 23852358661234)   
-     threadDelay (1000*1000) -- One second
-     mapM_ killThread tids
-
-     finals <- mapM readIORef counters
-     let mean :: Double = fromIntegral (foldl1 (+) finals) / fromIntegral numthreads
-         cycles_per :: Double = fromIntegral freq / mean
-     print_result (round mean) msg cycles_per
-
-print_result total msg cycles_per = 
-     putStrLn$ "    "++ padleft 11 (commaint total) ++" random ints generated "++ padright 27 ("["++msg++"]") ++" ~ "
-	       ++ fmt_num cycles_per ++" cycles/int"
-
-
--- FIXME: This isn't working yet because when the C call goes into a tight infinite loop killThread hangs...
--- KEEPING AROUND ONLY FOR FUTURE INVESTIGATION
-------------------------------------------------------------
-time_c :: Int -> Int64 -> (Ptr Int -> Ptr Int -> IO ()) -> IO Int
-time_c numthreads freq ffn = do 
-  counter :: ForeignPtr Int <- mallocForeignPtr
-  sum     :: ForeignPtr Int <- mallocForeignPtr
-  tid <- forkOS $ 
-	 withForeignPtr counter $ \ cntr ->
-	 withForeignPtr sum $ \ sm ->
-          ffn cntr sm
-  threadDelay (1000*1000) -- One second
-  stat <- threadStatus tid
-  putStrLn$ "Thread making foreign call's status: "++ show stat
-  putStrLn$ "Killing thread running the foreign C call...\n"
-  killThread tid -- This will hang!!!
-  putStrLn$ "Killed.\n"
-  total <- withForeignPtr counter peek 
-  putStrLn$ "Got total: " ++ show total
-  return total
-------------------------------------------------------------
-
-
--- This version flips things around, and assume something about the
--- timing so that we can run a fixed number of randoms and time it.
--- (We could do binary search here.)
-time_c2 :: Int -> Int64 -> String -> (Int -> Ptr Int -> IO ()) -> IO Int
-time_c2 numthreads freq msg ffn = do 
-  ptr     :: ForeignPtr Int <- mallocForeignPtr
-
-  let kern = if numthreads == 1
-	     then ffn
-	     else replicate_kernel numthreads ffn 
-      wrapped n = withForeignPtr ptr (kern$ fromIntegral n)
-  (n,t) <- binSearch False 1 (1.0, 1.05) wrapped
-
-  -- ONLY if we're in multi-threaded mode do we then run again with
-  -- that input size on all threads:
-----------------------------------------
--- NOTE, this approach is TOO SLOW.  For workloads that take a massive
--- parallel slowdown it doesn't make sense to use the same input size
--- in serial and in parallel.
--- DISABLING:
-{-
-  (n2,t2) <- 
-    if numthreads > 1 then do
-      ptrs <- mapM (const mallocForeignPtr) [1..numthreads]
-      tmpchan <- newChan
-      putStrLn$ "       [forking threads for multithreaded measurement, input size "++ show n++"]"
-      start <- getCPUTime
-      tids <- forM ptrs $ \ptr -> forkIO $ 
-	       do withForeignPtr ptr (ffn$ fromIntegral n)
-		  writeChan tmpchan ()     
-      forM ptrs $ \_ -> readChan tmpchan
-      end <- getCPUTime
-      let t2 :: Double = fromIntegral (end-start) / 1000000000000.0
-      putStrLn$ "       [joined threads, time "++ show t2 ++"]"
-      return (n * fromIntegral numthreads, t2)
-    else do 
-      return (n,t)
--}
-----------------------------------------
-
-  let total_per_second = round $ fromIntegral n * (1 / t)
-      cycles_per = fromIntegral freq * t / fromIntegral n
-  print_result total_per_second msg cycles_per
-  return total_per_second
-
--- This lifts the C kernel to operate 
-replicate_kernel :: Int -> Kern -> Kern
-replicate_kernel numthreads kern n ptr = do
-  ptrs <- forM [1..numthreads]
-	    (const mallocForeignPtr) 
-  tmpchan <- newChan
-  -- let childwork = ceiling$ fromIntegral n / fromIntegral numthreads
-  let childwork = n -- Keep it the same.. interested in per-thread throughput.
-  -- Fork/join pattern:
-  tids <- forM ptrs $ \ptr -> forkIO $ 
-	   withForeignPtr ptr $ \p -> do
-	      kern (fromIntegral childwork) p
-	      result <- peek p
-	      writeChan tmpchan result
-
-  results <- forM [1..numthreads] $ \_ -> 
-	       readChan tmpchan
-  -- Meaningless semantics here... sum the child ptrs and write to the input one:
-  poke ptr (foldl1 (+) results)
-  return ()
-
-----------------------------------------------------------------------------------------------------
--- Main Script
-
-data Flag = NoC | Help | Test
-  deriving (Show, Eq)
-
-options = 
-   [ Option ['h']  ["help"]  (NoArg Help)  "print program help"
-   , Option []     ["noC"]   (NoArg NoC)   "omit C benchmarks, haskell only"
-   , Option ['t']  ["test"]  (NoArg Test)  "run some basic tests"
-   ]
-
-  
-main = do 
-   argv <- getArgs
-   let (opts,_,other) = getOpt Permute options argv
-
-   when (Test `elem` opts)$ do
-       IA.testIntelAES
-       NI.testAESNI
-       exitSuccess
-
-   when (not$ null other) $ do
-       putStrLn$ "ERROR: Unrecognized options: " 
-       mapM_ putStr other
-       exitFailure
-
-   when (Help `elem` opts) $ do
-       putStr$ usageInfo "Benchmark random number generation" options
-       exitSuccess
-
-   putStrLn$ "\nHow many random numbers can we generate in a second on one thread?"
-
-   t1 <- rdtsc
-   t2 <- rdtsc
-   putStrLn ("  Cost of rdtsc (ffi call):    " ++ show (t2 - t1))
-
-   freq <- measure_freq2
-   putStrLn$ "  Approx clock frequency:  " ++ commaint freq
-
---   svein <- Svein.newAESGen
-
-   let gamut th = do
-       putStrLn$ "  First, timing with System.Random interface:"
-       timeit th freq "constant zero gen" (const NoopRNG)
-       timeit th freq "System.Random stdGen" mkStdGen
-       timeit th freq "PureHaskell/reference" BS.mkBurtonGen_reference
-       timeit th freq "PureHaskell"           BS.mkBurtonGen
---       timeit th freq "Gladman inefficient"     GA.mkAESGen0
---       timeit th freq "Gladman"                 GA.mkAESGen
-       timeit th freq "Gladman inefficient"     mkAESGen_gladman0
-       timeit th freq "Gladman"                 mkAESGen_gladman
-       timeit th freq "Compound gladman/intel"  IA.mkAESGen
---       timeit th freq "Svein's Gladman package" (const svein)
-
-       if IA.supportsAESNI then do 
-	  timeit th freq "IntelAES inefficient"    NI.mkAESGen0
-	  timeit th freq "IntelAES"                NI.mkAESGen
-         else 
-          putStrLn$ "   [Skipping AESNI-only tests, current machine does not support these instructions.]"
-
-       when (not$ NoC `elem` opts) $ do
-	  putStrLn$ "  Comparison to C's rand():"
-	  time_c2 th freq "ptr store in C loop"   store_loop
-	  time_c2 th freq "rand/store in C loop"  blast_rands
-	  time_c2 th freq "rand in Haskell loop" (\n ptr -> forM_ [1..n]$ \_ -> rand )
-	  time_c2 th freq "rand/store in Haskell loop"  (\n ptr -> forM_ [1..n]$ \_ -> do n <- rand; poke ptr n )
-	  return ()
-          -- timeit 1 freq "rand / Haskell loop" mkBurtonGen
-
-   gamut 1
-
-   when (numCapabilities > 1) $ do 
---   when (False) $ do 
-       putStrLn$ "\nNow "++ show numCapabilities ++" threads, reporting mean randoms-per-second-per-thread:"
-       gamut numCapabilities
-       return ()
-
-   putStrLn$ "Finished."
diff --git a/System/Random/AES.hs b/System/Random/AES.hs
new file mode 100644
--- /dev/null
+++ b/System/Random/AES.hs
@@ -0,0 +1,134 @@
+{-|
+     Module      :  System.Random.AES
+     Copyright   :  (c) Ryan Newton 2011
+     License     :  BSD-style (see the file LICENSE)
+     Maintainer  :  rrnewton@gmail.com
+     Stability   :  experimental
+     Portability :  Mac OS, Linux, Untested on Windows
+
+     This module provides cryptographic-strength random number
+     generators based on AES.
+
+     The generators are exposed both using the
+     'System.Random.RandomGen' interface and the
+     'Codec.Crypto.CryptoRandomGen' one.
+
+     Internally, this module uses two different AES implementations.
+     If the CPU ID indicates that AESNI instructions are available, it
+     will use an Intel-provided hardware-accelerated implementation,
+     otherwise, it will fall back to Dr. Brian Gladman's well-known
+     software implementation.
+
+  -}
+{-# OPTIONS_GHC -fwarn-unused-imports #-}
+{-# LANGUAGE ForeignFunctionInterface, CPP, ScopedTypeVariables  #-}
+
+module System.Random.AES
+    (
+      mkAESGen, mkAESGenCRG,
+      AesCRG(), AesRG(),
+      supportsAESNI,
+     -- Plus, instances exported of course.
+--      testIntelAES
+    )
+where 
+
+import qualified Codec.Crypto.IntelAES.AESNI  as NI
+import qualified Codec.Crypto.GladmanAES      as GA
+-- import GHC.IO (unsafeDupablePerformIO)
+import Data.Tagged
+import Data.Word
+import Data.Serialize
+import qualified Data.ByteString as B
+-- import Crypto.Random (CryptoRandomGen(..), GenError(..), splitGen, genBytes)
+import Crypto.Random (CryptoRandomGen(..))
+-- import Crypto.Types
+import Codec.Crypto.ConvertRNG 
+
+-- This type represents an RNG which may have one of two different
+-- representations, corresponding to the software or the hardware
+-- supported version.
+newtype AesCRG = 
+  AesCRG 
+   (Either (BCtoCRG (NI.IntelAES NI.N128))
+	   (BCtoCRG (GA.AES GA.N128)))
+
+-- | A type representing an AES-based random number generator which
+--   will use AESNI instructions when available, and invoke the
+--   portable Gladman implementation when not.
+type AesRG = CRGtoRG AesCRG
+
+-- | Simple function to create a random number generator from an Int,
+--   exposing the 'System.Random.RandomGen' interface, analogous to
+--   'System.Random.newStdGen'.  Only 128-bit encryption is currently
+--   provided.
+mkAESGen :: Int -> AesRG
+mkAESGen int = convertCRG (mkAESGenCRG int)
+
+-- | This variant creates an random number generator which exposes the
+--   'Crypto.Random.CryptoRandomGen' interface.
+mkAESGenCRG :: Int -> AesCRG
+mkAESGenCRG int = gen
+   where
+  Right (gen :: AesCRG) = newGen (B.append halfseed halfseed )
+  halfseed = encode word64
+  word64 = fromIntegral int :: Word64
+
+
+
+foreign import ccall unsafe "iaesni.h" check_for_aes_instructions :: Bool
+
+-- | Does the machine support AESNI instructions?
+supportsAESNI :: Bool
+supportsAESNI = check_for_aes_instructions
+
+-- | This instance provides the CryptoRandomGen interface, which
+--   allows bulk generation of random bytes.
+instance CryptoRandomGen AesCRG where 
+
+--  newGen :: B.ByteString -> Either GenError AesCRG
+  newGen = 
+     if check_for_aes_instructions
+     -- Ick, boilerplate:
+     then \bytes -> case newGen bytes of Left err  -> Left err
+					 Right gen -> Right$ AesCRG$ Left gen
+     else \bytes -> case newGen bytes of Left err  -> Left err
+					 Right gen -> Right$ AesCRG$ Right gen
+
+  genSeedLength = Tagged 128
+ 
+  -- ByteLength -> AesCRG -> Either GenError (B.ByteString, AesCRG)
+  genBytes req (AesCRG (Left gen)) = 
+
+#if 0
+    -- UNFINISHED: Let's try to reduce that boilerplate if we can...
+    mapRight (mapSnd (AesCRG . Left) ) $ genBytes req gen
+#else
+    case genBytes req gen of 
+      Left  err  -> Left err
+      Right (bytes,gen') -> Right (bytes, AesCRG (Left gen'))
+#endif
+
+
+-- <boilerplate> OUCH
+  genBytes req (AesCRG (Right gen)) = 
+    case genBytes req gen of 
+      Left  err  -> Left err
+      Right (bytes,gen') -> Right (bytes, AesCRG (Right gen'))
+  reseed bs (AesCRG (Left gen)) = 
+    case reseed bs gen of 
+      Left  err  -> Left err
+      Right gen' -> Right (AesCRG (Left gen'))
+  reseed bs (AesCRG (Right gen)) = 
+    case reseed bs gen of 
+      Left  err  -> Left err
+      Right gen' -> Right (AesCRG (Right gen'))
+-- </boilerplate>
+
+-- UNFINISHED Refactoring:
+{-# INLINE mapRight #-}
+mapRight fn x@(Left _) = x
+mapRight fn (Right x)  = Right$ fn x
+{-# INLINE mapSnd #-}
+mapSnd fn (x,y) = (x,fn y)
+
diff --git a/System/Random/AES/Tests.hs b/System/Random/AES/Tests.hs
new file mode 100644
--- /dev/null
+++ b/System/Random/AES/Tests.hs
@@ -0,0 +1,365 @@
+{-# LANGUAGE BangPatterns, ScopedTypeVariables, ForeignFunctionInterface #-}
+
+{- | A simple script to do some very basic timing of 'System.Random.RandomGen's.  
+
+   This module is located here to be part of the same compilation unit
+   as the library itself (e.g. to access hidden modules).
+
+   TODO: It is important that we also run established stastical tests on
+   these RNGs a some point...
+ -}
+
+module System.Random.AES.Tests (runTests) where
+
+import qualified System.Random.AES                 as IA
+import qualified Codec.Encryption.BurtonRNGSlow    as BS
+import qualified Codec.Crypto.GladmanAES           as GA
+import qualified Codec.Crypto.IntelAES.AESNI       as NI
+import qualified Codec.Crypto.ConvertRNG           as CR
+
+import System.Exit (exitSuccess, exitFailure)
+import System.Environment
+import System.Random
+import System.Posix (sleep)
+import System.CPUTime  (getCPUTime)
+import System.CPUTime.Rdtsc
+import System.Console.GetOpt
+
+import GHC.Conc
+import Control.Concurrent
+import Control.Monad 
+import Control.Concurrent.Chan
+import Control.Exception
+
+import Crypto.Random (CryptoRandomGen(..))
+
+import Data.IORef
+import Data.List
+import Data.Int
+import Data.Word
+import Data.List.Split
+import Data.Serialize
+import qualified Data.ByteString as B
+import Text.Printf
+
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.Storable (peek,poke)
+
+import Benchmark.BinSearch
+
+----------------------------------------------------------------------------------------------------
+-- TEMP: MOVE ME ELSEWHERE:
+
+mkAESGen_gladman :: Int -> CR.CRGtoRG (CR.BCtoCRG (GA.AES GA.N128))
+mkAESGen_gladman int = CR.convertCRG gen
+ where
+  Right (gen :: CR.BCtoCRG (GA.AES GA.N128)) = newGen (B.append halfseed halfseed )
+  halfseed = encode word64
+  word64 = fromIntegral int :: Word64
+
+
+mkAESGen_gladman_unbuffered :: Int -> CR.CRGtoRG_Unbuffered (CR.BCtoCRG (GA.AES GA.N128))
+mkAESGen_gladman_unbuffered int = CR.CRGtoRG_Unbuffered gen
+ where
+  Right (gen :: CR.BCtoCRG (GA.AES GA.N128)) = newGen (B.append halfseed halfseed )
+  halfseed = encode word64
+  word64 = fromIntegral int :: Word64
+
+
+----------------------------------------------------------------------------------------------------
+-- Miscellaneous helpers:
+
+-- I cannot *believe* there is not a standard call or an
+-- easily-findable hackage library supporting locale-based printing of
+-- numbers. [2011.01.28]
+commaint :: Integral a => a -> String
+commaint n = 
+   reverse $
+   concat $
+   intersperse "," $ 
+   chunk 3 $ 
+   reverse (show n)
+
+padleft n str | length str >= n = str
+padleft n str | otherwise       = take (n - length str) (repeat ' ') ++ str
+
+padright n str | length str >= n = str
+padright n str | otherwise       = str ++ take (n - length str) (repeat ' ')
+
+fmt_num n = if n < 100 
+	    then printf "%.2f" n
+	    else commaint (round n)
+
+-- WARNING! This is not actually good enough.  Even if we use forkOS
+-- we would have to go further and pin the OS thread (e.g. in linux)
+-- to keep the OS from waking up the process on a different core.
+measure_freq :: IO Int64
+measure_freq = do 
+   -- We measure the clock frequency on a bound thread.
+   -- Otherwise we can get really screwy results from rdtsc if we
+   -- migrate physical threads when we sleep or threadDelay.
+   tmpchan <- newChan
+   forkOS $ do 
+      t1 <- rdtsc
+      -- sleep 1
+      threadDelay (1000*1000)
+      t2 <- rdtsc
+      -- Just to be careful let's make sure this doesn't happen (this was how I found the problem before forkOS):
+      when (t2 < t1) $ 
+        putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"
+      writeChan tmpchan (if t2>t1 then t2-t1 else t1-t2)
+   freq <- readChan tmpchan
+   return (fromIntegral freq)
+
+-- This version simply busy-waits to stay on the same core:
+-- WOW! I'm STILL experiencing the non-monotonic rdtsc, even when not compiled with -threaded.
+-- It can't be overflow can it?  The counter should be 64 bit...
+--
+-- UPDATE: [2011.01.28] This was a bug in the rdtsc package that dropping the precision to 32 bits.
+measure_freq2 :: IO Int64
+measure_freq2 = do 
+  let second = 1000 * 1000 * 1000 * 1000 -- picoseconds are annoying
+  t1 <- rdtsc 
+  start <- getCPUTime
+  let loop !n !last = 
+       do t2 <- rdtsc 
+	  when (t2 < last) $
+	       putStrLn$ "COUNTERS WRAPPED "++ show (last,t2) 
+	  cput <- getCPUTime		
+	  if (cput - start < second) 
+	   then loop (n+1) t2
+	   else return (n,t2)
+  (n,t2) <- loop 0 t1
+  putStrLn$ "  Approx getCPUTime calls per second: "++ commaint n
+  when (t2 < t1) $ 
+    putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"
+
+  return$ fromIntegral (t2 - t1)
+
+----------------------------------------------------------------------------------------------------
+-- Drivers to get random numbers repeatedly.
+
+incr !counter = 
+  do -- modifyIORef counter (+1)d
+     -- Incrementing counter strictly (avoiding stack overflow) is annoying:
+     c <- readIORef counter
+     let c' = c+1
+     evaluate c'
+     writeIORef counter c'     
+
+loop :: RandomGen g => IORef Int -> (Int,g) -> IO b
+loop !counter !(!n,!g) = 
+  do incr counter
+--     putStr (show n); putChar ' '
+     loop counter (next g)
+
+data NoopRNG = NoopRNG
+instance RandomGen NoopRNG where 
+  split g = (g,g)
+  next g  = (0,g)
+
+--foreign import ccall "cbits/c_test.c" blast_rands :: Ptr Int -> Ptr Int -> IO ()
+
+type Kern = Int -> Ptr Int -> IO ()
+
+-- [2011.01.28] Changing this to take "count" and "accumulator ptr" as arguments:
+foreign import ccall "cbits/c_test.c" blast_rands :: Kern
+foreign import ccall "cbits/c_test.c" store_loop  :: Kern
+foreign import ccall unsafe "stdlib.hs" rand :: IO Int
+
+loop2 :: IORef Int -> IO ()
+loop2 !counter = 
+  do incr counter
+     n <- rand
+     loop2 counter 
+
+
+----------------------------------------------------------------------------------------------------
+-- Timing:
+
+timeit numthreads freq msg mkgen =
+  do 
+     counters <- forM [1..numthreads] (const$ newIORef 1) 
+     tids <- forM counters $ \counter -> 
+	        forkIO $ loop counter (next$ mkgen 23852358661234)   
+     threadDelay (1000*1000) -- One second
+     mapM_ killThread tids
+
+     finals <- mapM readIORef counters
+     let mean :: Double = fromIntegral (foldl1 (+) finals) / fromIntegral numthreads
+         cycles_per :: Double = fromIntegral freq / mean
+     print_result (round mean) msg cycles_per
+
+print_result total msg cycles_per = 
+     putStrLn$ "    "++ padleft 11 (commaint total) ++" random ints generated "++ padright 27 ("["++msg++"]") ++" ~ "
+	       ++ fmt_num cycles_per ++" cycles/int"
+
+
+-- FIXME: This isn't working yet because when the C call goes into a tight infinite loop killThread hangs...
+-- KEEPING AROUND ONLY FOR FUTURE INVESTIGATION
+------------------------------------------------------------
+time_c :: Int -> Int64 -> (Ptr Int -> Ptr Int -> IO ()) -> IO Int
+time_c numthreads freq ffn = do 
+  counter :: ForeignPtr Int <- mallocForeignPtr
+  sum     :: ForeignPtr Int <- mallocForeignPtr
+  tid <- forkOS $ 
+	 withForeignPtr counter $ \ cntr ->
+	 withForeignPtr sum $ \ sm ->
+          ffn cntr sm
+  threadDelay (1000*1000) -- One second
+  stat <- threadStatus tid
+  putStrLn$ "Thread making foreign call's status: "++ show stat
+  putStrLn$ "Killing thread running the foreign C call...\n"
+  killThread tid -- This will hang!!!
+  putStrLn$ "Killed.\n"
+  total <- withForeignPtr counter peek 
+  putStrLn$ "Got total: " ++ show total
+  return total
+------------------------------------------------------------
+
+
+-- This version flips things around, and assume something about the
+-- timing so that we can run a fixed number of randoms and time it.
+-- (We could do binary search here.)
+time_c2 :: Int -> Int64 -> String -> (Int -> Ptr Int -> IO ()) -> IO Int
+time_c2 numthreads freq msg ffn = do 
+  ptr     :: ForeignPtr Int <- mallocForeignPtr
+
+  let kern = if numthreads == 1
+	     then ffn
+	     else replicate_kernel numthreads ffn 
+      wrapped n = withForeignPtr ptr (kern$ fromIntegral n)
+  (n,t) <- binSearch False 1 (1.0, 1.05) wrapped
+
+  -- ONLY if we're in multi-threaded mode do we then run again with
+  -- that input size on all threads:
+----------------------------------------
+-- NOTE, this approach is TOO SLOW.  For workloads that take a massive
+-- parallel slowdown it doesn't make sense to use the same input size
+-- in serial and in parallel.
+-- DISABLING:
+{-
+  (n2,t2) <- 
+    if numthreads > 1 then do
+      ptrs <- mapM (const mallocForeignPtr) [1..numthreads]
+      tmpchan <- newChan
+      putStrLn$ "       [forking threads for multithreaded measurement, input size "++ show n++"]"
+      start <- getCPUTime
+      tids <- forM ptrs $ \ptr -> forkIO $ 
+	       do withForeignPtr ptr (ffn$ fromIntegral n)
+		  writeChan tmpchan ()     
+      forM ptrs $ \_ -> readChan tmpchan
+      end <- getCPUTime
+      let t2 :: Double = fromIntegral (end-start) / 1000000000000.0
+      putStrLn$ "       [joined threads, time "++ show t2 ++"]"
+      return (n * fromIntegral numthreads, t2)
+    else do 
+      return (n,t)
+-}
+----------------------------------------
+
+  let total_per_second = round $ fromIntegral n * (1 / t)
+      cycles_per = fromIntegral freq * t / fromIntegral n
+  print_result total_per_second msg cycles_per
+  return total_per_second
+
+-- This lifts the C kernel to operate 
+replicate_kernel :: Int -> Kern -> Kern
+replicate_kernel numthreads kern n ptr = do
+  ptrs <- forM [1..numthreads]
+	    (const mallocForeignPtr) 
+  tmpchan <- newChan
+  -- let childwork = ceiling$ fromIntegral n / fromIntegral numthreads
+  let childwork = n -- Keep it the same.. interested in per-thread throughput.
+  -- Fork/join pattern:
+  tids <- forM ptrs $ \ptr -> forkIO $ 
+	   withForeignPtr ptr $ \p -> do
+	      kern (fromIntegral childwork) p
+	      result <- peek p
+	      writeChan tmpchan result
+
+  results <- forM [1..numthreads] $ \_ -> 
+	       readChan tmpchan
+  -- Meaningless semantics here... sum the child ptrs and write to the input one:
+  poke ptr (foldl1 (+) results)
+  return ()
+
+----------------------------------------------------------------------------------------------------
+-- Main Script
+
+data Flag = NoC | Help | Test
+  deriving (Show, Eq)
+
+options = 
+   [ Option ['h']  ["help"]  (NoArg Help)  "print program help"
+   , Option []     ["noC"]   (NoArg NoC)   "omit C benchmarks, haskell only"
+   , Option ['t']  ["test"]  (NoArg Test)  "run some basic tests"
+   ]
+
+runTests = do 
+   argv <- getArgs
+   let (opts,_,other) = getOpt Permute options argv
+
+   putStrLn$ "Does machine supports AESNI?: " ++ show IA.supportsAESNI
+   when (Test `elem` opts)$ do
+       NI.testAESNI
+       exitSuccess
+
+   when (not$ null other) $ do
+       putStrLn$ "ERROR: Unrecognized options: " 
+       mapM_ putStr other
+       exitFailure
+
+   when (Help `elem` opts) $ do
+       putStr$ usageInfo "Benchmark random number generation" options
+       exitSuccess
+
+   putStrLn$ "\nHow many random numbers can we generate in a second on one thread?"
+
+   t1 <- rdtsc
+   t2 <- rdtsc
+   putStrLn ("  Cost of rdtsc (ffi call):    " ++ show (t2 - t1))
+
+   freq <- measure_freq2
+   putStrLn$ "  Approx clock frequency:  " ++ commaint freq
+
+--   svein <- Svein.newAESGen
+
+   let gamut th = do
+       putStrLn$ "  First, timing with System.Random interface:"
+       timeit th freq "constant zero gen" (const NoopRNG)
+       timeit th freq "System.Random stdGen" mkStdGen
+       timeit th freq "PureHaskell/reference" BS.mkBurtonGen_reference
+       timeit th freq "PureHaskell"           BS.mkBurtonGen
+--       timeit th freq "Gladman unbuffered"     GA.mkAESGen0
+--       timeit th freq "Gladman"                 GA.mkAESGen
+       timeit th freq "Gladman unbuffered"     mkAESGen_gladman_unbuffered
+       timeit th freq "Gladman"                mkAESGen_gladman
+       timeit th freq "Compound gladman/intel"  IA.mkAESGen
+--       timeit th freq "Svein's Gladman package" (const svein)
+
+       if IA.supportsAESNI then do 
+	  timeit th freq "IntelAES unbuffered"    NI.mkAESGen0
+	  timeit th freq "IntelAES"                NI.mkAESGen
+         else 
+          putStrLn$ "   [Skipping AESNI-only tests, current machine does not support these instructions.]"
+
+       when (not$ NoC `elem` opts) $ do
+	  putStrLn$ "  Comparison to C's rand():"
+	  time_c2 th freq "ptr store in C loop"   store_loop
+	  time_c2 th freq "rand/store in C loop"  blast_rands
+	  time_c2 th freq "rand in Haskell loop" (\n ptr -> forM_ [1..n]$ \_ -> rand )
+	  time_c2 th freq "rand/store in Haskell loop"  (\n ptr -> forM_ [1..n]$ \_ -> do n <- rand; poke ptr n )
+	  return ()
+          -- timeit 1 freq "rand / Haskell loop" mkBurtonGen
+
+   gamut 1
+
+   when (numCapabilities > 1) $ do 
+--   when (False) $ do 
+       putStrLn$ "\nNow "++ show numCapabilities ++" threads, reporting mean randoms-per-second-per-thread:"
+       gamut numCapabilities
+       return ()
+
+   putStrLn$ "Finished."
diff --git a/benchmark-intel-aes-rng.hs b/benchmark-intel-aes-rng.hs
new file mode 100644
--- /dev/null
+++ b/benchmark-intel-aes-rng.hs
@@ -0,0 +1,8 @@
+#!/usr/bin/env runhaskell -i
+
+-- Note the -i to prevent GHC from searching ./ as part of the library search path.
+
+module Main where 
+import System.Random.AES.Tests (runTests)
+
+main = runTests
diff --git a/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile b/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile
--- a/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile
+++ b/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/Makefile
@@ -1,5 +1,6 @@
 
 UNAME=$(shell uname -m)
+OS:=$(shell uname -s)
 
 # Must be 86 (for 32bit compiler) or 64 (for 64bit compiler)
 ARCH=64
@@ -7,9 +8,14 @@
 # Must be 32 or 64:
 SZ=64
 #SZ=32
+LIBDIR=lib/x$(ARCH)
 
-STATIC=lib/x$(ARCH)/libintel_aes.a
-DYNAMIC=lib/x$(ARCH)/libintel_aes.so
+STATIC=libintel_aes.a
+ifeq (Darwin,$(OS))
+DYNAMIC=libintel_aes.dylib
+else
+DYNAMIC=libintel_aes.so
+endif
 
 SRC= src/intel_aes.c \
      asm/x$(ARCH)/iaesx$(ARCH).s \
@@ -22,18 +28,27 @@
 # GCC=gcc -m32
 GCC=gcc 
 YASM=yasm
+ifeq (Darwin,$(OS))
+YASMFLAGS= -D__linux__ -g null -f macho$(SZ) --prefix=_
+L=libtool
+LFLAGS=-dynamic -install_name @rpath/$(DYNAMIC) -macosx_version_min 10.5 -lSystem
+else
 YASMFLAGS= -D__linux__ -g dwarf2 -f elf$(SZ) 
+L=gcc
+LFLAGS=-shared -dynamic
+endif
 
-all: $(STATIC) $(DYNAMIC)
-	cp lib/x$(ARCH)/* ../../
+all: $(LIBDIR)/$(STATIC) $(LIBDIR)/$(DYNAMIC)
+	cp $(LIBDIR)/* ../../
 
-$(STATIC): $(OBJ)
-	@mkdir -p lib/x$(ARCH)
+$(LIBDIR)/$(STATIC): $(OBJ)
+	@mkdir -p $(LIBDIR)
 	ar -r $@ $(OBJ)
 
-$(DYNAMIC): $(OBJ)
-	@mkdir -p lib/x$(ARCH)
-	$(GCC) -shared -dynamic  -o $(DYNAMIC) $(OBJ)
+$(LIBDIR)/$(DYNAMIC): $(OBJ)
+	@mkdir -p $(LIBDIR)
+	$(L) $(LFLAGS) -o $(DYNAMIC) $(OBJ)
+	mv $(DYNAMIC) $(LIBDIR)
 
 obj/x$(ARCH)/do_rdtsc.o:  asm/x$(ARCH)/do_rdtsc.s
 	@mkdir -p obj/x$(ARCH)
@@ -48,4 +63,4 @@
 	$(GCC) -fPIC -O3 -g -Iinclude/ -c $< -o $@
 
 clean:
-	rm -f $(STATIC) $(DYNAMIC) $(OBJ)
+	rm -f $(STATIC) $(DYNAMIC) $(LIBDIR)/$(STATIC) $(LIBDIR)/$(DYNAMIC) $(OBJ)
diff --git a/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_lice b/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_lice
new file mode 100644
--- /dev/null
+++ b/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_lice
@@ -0,0 +1,34 @@
+/* intel_aes_lib source files come from Intel.
+ * Modified by Patrick Fay
+ *
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+    * Neither the name of Intel Corporation nor the names of its contributors 
+      may be used to endorse or promote products derived from this software 
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ---------------------------------------------------------------------------
+ Issue Date: Aug 6, 2010
+ */
+
+Other source code files use the license shown in the source code file.
diff --git a/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_license.txt b/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_license.txt
deleted file mode 100644
--- a/cbits/Intel_AESNI_Sample_Library_v1.0/intel_aes_lib/where_files_come_from_and_license.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-/* intel_aes_lib source files come from Intel.
- * Modified by Patrick Fay
- *
-Copyright (c) 2010, Intel Corporation
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without 
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice, 
-      this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright notice, 
-      this list of conditions and the following disclaimer in the documentation 
-      and/or other materials provided with the distribution.
-    * Neither the name of Intel Corporation nor the names of its contributors 
-      may be used to endorse or promote products derived from this software 
-      without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- ---------------------------------------------------------------------------
- Issue Date: Aug 6, 2010
- */
-
-Other source code files use the license shown in the source code file.
diff --git a/cbits/Makefile b/cbits/Makefile
--- a/cbits/Makefile
+++ b/cbits/Makefile
@@ -6,4 +6,4 @@
 
 clean:
 	cd Intel_AESNI_Sample_Library_v1.0/intel_aes_lib; $(MAKE) clean
-	rm -f libintel_aes.a libintel_aes.so
+	rm -f libintel_aes.a libintel_aes.so libintel_aes.dylib
diff --git a/intel-aes.cabal b/intel-aes.cabal
--- a/intel-aes.cabal
+++ b/intel-aes.cabal
@@ -1,6 +1,9 @@
 Name:           intel-aes
-Version:        0.1.2.3
+Version:        0.2.0.0
 
+-- 0.1.2.4  -- minor bump for David (dmpots) Mac OS support
+-- 0.2.0.0  -- major bump for API reorg
+
 License:                BSD3
 License-file:           LICENSE
 Stability:              Beta
@@ -50,7 +53,7 @@
 Category: Cryptography
 Cabal-Version: >=1.8
 Tested-With: GHC == 7.0.1
--- Portability:            Untested on Windows.
+-- Portability: Works on Linux, Mac OS.  Untested on Windows.
 
 build-type: Custom
 
@@ -86,41 +89,34 @@
 library
   build-depends:  base >= 4 && < 5, random, DRBG, split, process, haskell98, time,
                   crypto-api >= 0.5, 
-                  bytestring, cereal, tagged, largeword
+                  bytestring, cereal, tagged, largeword,
+                  -- For AES.Tests only:
+                  rdtsc, unix
 
-  exposed-modules:  Codec.Encryption.BurtonRNGSlow
-                 ,  Codec.Crypto.IntelAES
-                 ,  Codec.Crypto.IntelAES.AESNI
+  exposed-modules: 
+                    System.Random.AES
                  ,  Codec.Crypto.ConvertRNG
---                 ,  Codec.Crypto.IntelAES.GladmanAES
-                 ,  Codec.Crypto.GladmanAES
+                 ,  System.Random.AES.Tests
   other-modules:  
                     Benchmark.BinSearch
                  ,  Codec.Encryption.AES
                  ,  Codec.Encryption.AESAux
                  ,  Codec.Utils
+                 ,  Codec.Encryption.BurtonRNGSlow
+                 ,  Codec.Crypto.IntelAES.AESNI
+                 ,  Codec.Crypto.GladmanAES
   GHC-Options: -O2 
   extra-libraries: intel_aes
 
   -- The gladman sources are straightforward and can be built by Cabal (unlike the intel C/asm)
   C-sources: cbits/gladman/aescrypt.c, cbits/gladman/aeskey.c, cbits/gladman/aestab.c,
              cbits/gladman/aes_modes.c, cbits/gladman/ctr_inc.c
-  Include-Dirs: cbits
 
+  -- Include this script as well:
+  -- data-files: benchmark-intel-aes-rng.hs
+  Include-Dirs: cbits
 
 -- ----------------------------------------------------------------------------------------------------
-Executable benchmark-intel-aes-rng
-  Main-is:        SimpleRNGBench.hs
-  Build-Depends:  base >= 4 && < 5, split, rdtsc, random, DRBG
-                , crypto-api >= 0.5
---                , unix-compat
-                , unix
-                , tagged, cereal, bytestring, process, haskell98, time, largeword
-                , intel-aes
-  GHC-Options:    -O2 -threaded -rtsopts 
-  C-sources:	   cbits/c_test.c
-  Include-dirs:    cbits
 
-
-
---  cabal haddock --hoogle --executables --hyperlink-source --haddock-options="--html"
+-- Example documentation generation command:
+--    cabal haddock --hoogle --executables --hyperlink-source --haddock-options="--html"
