diff --git a/Crypto/Cipher/AES.hs b/Crypto/Cipher/AES.hs
--- a/Crypto/Cipher/AES.hs
+++ b/Crypto/Cipher/AES.hs
@@ -1,7 +1,9 @@
 {-# LANGUAGE ForeignFunctionInterface #-}
 {-# LANGUAGE ViewPatterns #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 -- |
 -- Module      : Crypto.Cipher.AES
 -- License     : BSD-style
@@ -17,6 +19,10 @@
     , AES192
     , AES256
 
+    -- * IV
+    , AESIV
+    , aesIV_
+
     -- * Authenticated encryption block cipher types
     , AESGCM
 
@@ -26,6 +32,7 @@
 
     -- * misc
     , genCTR
+    , genCounter
 
     -- * encryption
     , encryptECB
@@ -46,12 +53,14 @@
 
 import Data.Word
 import Foreign.Ptr
+import Foreign.ForeignPtr
 import Foreign.C.Types
 import Foreign.C.String
 import Data.ByteString.Internal
 import Data.ByteString.Unsafe
 import Data.Byteable
 import qualified Data.ByteString as B
+import qualified Data.ByteString.Internal as B (ByteString(PS), mallocByteString, memcpy)
 import System.IO.Unsafe (unsafePerformIO)
 
 import Crypto.Cipher.Types
@@ -69,6 +78,16 @@
 -- | AES with 256 bit key
 newtype AES256 = AES256 AES
 
+-- | AES IV is always 16 bytes
+newtype AESIV = AESIV ByteString
+    deriving (Show,Eq,Byteable)
+
+-- | convert a bytestring to an AESIV
+aesIV_ :: ByteString -> AESIV
+aesIV_ iv
+    | B.length iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ B.length iv)
+    | otherwise         = AESIV iv
+
 instance Cipher AES where
     cipherName    _ = "AES"
     cipherKeySize _ = KeySizeEnum [16,24,32]
@@ -165,6 +184,13 @@
 ivToPtr :: Byteable iv => iv -> (Ptr Word8 -> IO a) -> IO a
 ivToPtr iv f = withBytePtr iv (f . castPtr)
 
+ivCopyPtr :: AESIV -> (Ptr Word8 -> IO ()) -> IO AESIV
+ivCopyPtr (AESIV iv) f = do
+    newIV <- create 16 $ \newPtr -> do
+                withBytePtr iv $ \ivPtr -> B.memcpy newPtr ivPtr 16
+    withBytePtr newIV $ f
+    return $! AESIV newIV
+
 withKeyAndIV :: Byteable iv => AES -> iv -> (Ptr AES -> Ptr Word8 -> IO a) -> IO a
 withKeyAndIV ctx iv f = keyToPtr ctx $ \kptr -> ivToPtr iv $ \ivp -> f kptr ivp
 
@@ -216,7 +242,7 @@
 {-# NOINLINE encryptCBC #-}
 encryptCBC :: Byteable iv
            => AES        -- ^ AES Context
-           -> iv         -- ^ Initial vector
+           -> iv         -- ^ Initial vector of AES block size
            -> ByteString -- ^ plaintext
            -> ByteString -- ^ ciphertext
 encryptCBC = doCBC c_aes_encrypt_cbc
@@ -235,22 +261,54 @@
        -> ByteString
 genCTR ctx iv len
     | len <= 0  = B.empty
+    | byteableLength iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ byteableLength iv)
     | otherwise = unsafeCreate (nbBlocks * 16) generate
   where generate o = withKeyAndIV ctx iv $ \k i -> c_aes_gen_ctr (castPtr o) k i (fromIntegral nbBlocks)
         (nbBlocks',r) = len `quotRem` 16
         nbBlocks = if r == 0 then nbBlocks' else nbBlocks' + 1
 
+-- | generate a counter mode pad. this is generally xor-ed to an input
+-- to make the standard counter mode block operations.
+--
+-- if the length requested is not a multiple of the block cipher size,
+-- more data will be returned, so that the returned bytestring is
+-- a multiple of the block cipher size.
+--
+-- Similiar to 'genCTR' but also return the next IV for continuation
+{-# NOINLINE genCounter #-}
+genCounter :: AES
+           -> AESIV
+           -> Int
+           -> (ByteString, AESIV)
+genCounter ctx iv len
+    | len <= 0  = (B.empty, iv)
+    | otherwise = unsafePerformIO $ do
+        fptr  <- B.mallocByteString outputLength
+        newIv <- withForeignPtr fptr generate
+        let !out = B.PS fptr 0 outputLength
+        return $! (out `seq` newIv `seq` (out, newIv))
+  where generate o = keyToPtr ctx $ \k -> ivCopyPtr iv $ \i ->
+            c_aes_gen_ctr_cont (castPtr o) k i (fromIntegral nbBlocks)
+        (nbBlocks',r) = len `quotRem` 16
+        nbBlocks = if r == 0 then nbBlocks' else nbBlocks' + 1
+        outputLength = nbBlocks * 16
+
+{- TODO: when genCTR has same AESIV requirements for IV, add the following rules:
+ - RULES "snd . genCounter" forall ctx iv len .  snd (genCounter ctx iv len) = genCTR ctx iv len
+ -}
+
 -- | encrypt using Counter mode (CTR)
 --
 -- in CTR mode encryption and decryption is the same operation.
 {-# NOINLINE encryptCTR #-}
 encryptCTR :: Byteable iv
            => AES        -- ^ AES Context
-           -> iv         -- ^ initial vector, usually representing a 128 bit integer
+           -> iv         -- ^ initial vector of AES block size (usually representing a 128 bit integer)
            -> ByteString -- ^ plaintext input
            -> ByteString -- ^ ciphertext output
 encryptCTR ctx iv input
     | len <= 0  = B.empty
+    | byteableLength iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ byteableLength iv)
     | otherwise = unsafeCreate len doEncrypt
   where doEncrypt o = withKeyAndIV ctx iv $ \k v -> unsafeUseAsCString input $ \i ->
                       c_aes_encrypt_ctr (castPtr o) k v i (fromIntegral len)
@@ -362,6 +420,7 @@
       -> AES -> iv -> ByteString -> ByteString
 doCBC f ctx iv input
     | len == 0  = B.empty
+    | byteableLength iv /= 16 = error $ "AES error: IV length must be block size (16). Its length is: " ++ (show $ byteableLength iv)
     | r /= 0    = error $ "Encryption error: input length must be a multiple of block size (16). Its length is: " ++ (show len)
     | otherwise = unsafeCreate len $ \o ->
                   withKeyAndIV ctx iv $ \k v ->
@@ -555,6 +614,9 @@
 ------------------------------------------------------------------------
 foreign import ccall "aes.h aes_gen_ctr"
     c_aes_gen_ctr :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
+
+foreign import ccall "aes.h aes_gen_ctr_cont"
+    c_aes_gen_ctr_cont :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
 
 foreign import ccall "aes.h aes_encrypt_ctr"
     c_aes_encrypt_ctr :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()
diff --git a/Tests/Tests.hs b/Tests/Tests.hs
--- a/Tests/Tests.hs
+++ b/Tests/Tests.hs
@@ -23,6 +23,13 @@
 import qualified KATGCM
 import qualified KATOCB3
 
+instance Show AES.AES where
+    show _ = "AES"
+instance Arbitrary AES.AESIV where
+    arbitrary = AES.aesIV_ . B.pack <$> replicateM 16 arbitrary
+instance Arbitrary AES.AES where
+    arbitrary = AES.initAES . B.pack <$> replicateM 16 arbitrary
+
 toKatECB (k,p,c) = KAT_ECB { ecbKey = k, ecbPlaintext = p, ecbCiphertext = c }
 toKatCBC (k,iv,p,c) = KAT_CBC { cbcKey = k, cbcIV = iv, cbcPlaintext = p, cbcCiphertext = c }
 toKatXTS (k1,k2,iv,p,_,c) = KAT_XTS { xtsKey1 = k1, xtsKey2 = k2, xtsIV = iv, xtsPlaintext = p, xtsCiphertext = c }
@@ -68,4 +75,9 @@
     [ testBlockCipher kats128 (undefined :: AES.AES128)
     , testBlockCipher kats192 (undefined :: AES.AES192)
     , testBlockCipher kats256 (undefined :: AES.AES256)
+    , testProperty "genCtr" $ \(key, iv1) ->
+        let (bs1, iv2)    = AES.genCounter key iv1 32
+            (bs2, iv3)    = AES.genCounter key iv2 32
+            (bsAll, iv3') = AES.genCounter key iv1 64
+         in (B.concat [bs1,bs2] == bsAll && iv3 == iv3')
     ]
diff --git a/cbits/aes.c b/cbits/aes.c
--- a/cbits/aes.c
+++ b/cbits/aes.c
@@ -262,7 +262,7 @@
 	d(output, key, iv, input, nb_blocks);
 }
 
-void aes_gen_ctr(aes_block *output, aes_key *key, aes_block *iv, uint32_t nb_blocks)
+void aes_gen_ctr(aes_block *output, aes_key *key, const aes_block *iv, uint32_t nb_blocks)
 {
 	aes_block block;
 
@@ -274,6 +274,21 @@
 	}
 }
 
+void aes_gen_ctr_cont(aes_block *output, aes_key *key, aes_block *iv, uint32_t nb_blocks)
+{
+	aes_block block;
+
+	/* preload IV in block */
+	block128_copy(&block, iv);
+
+	for ( ; nb_blocks-- > 0; output++, block128_inc_be(&block)) {
+		aes_encrypt_block(output, key, &block);
+	}
+
+	/* copy back the IV */
+	block128_copy(iv, &block);
+}
+
 void aes_encrypt_ctr(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t len)
 {
 	ctr_f e = GET_CTR_ENCRYPT(key->strength);
@@ -674,8 +689,8 @@
 	}
 }
 
-static int ocb_generic_crypt(uint8_t *output, aes_ocb *ocb, aes_key *key,
-                             uint8_t *input, uint32_t length, int encrypt)
+static void ocb_generic_crypt(uint8_t *output, aes_ocb *ocb, aes_key *key,
+                              uint8_t *input, uint32_t length, int encrypt)
 {
 	block128 tmp, pad;
 	unsigned int i;
diff --git a/cbits/aes.h b/cbits/aes.h
--- a/cbits/aes.h
+++ b/cbits/aes.h
@@ -77,7 +77,8 @@
 void aes_encrypt_cbc(aes_block *output, aes_key *key, aes_block *iv, aes_block *input, uint32_t nb_blocks);
 void aes_decrypt_cbc(aes_block *output, aes_key *key, aes_block *iv, aes_block *input, uint32_t nb_blocks);
 
-void aes_gen_ctr(aes_block *output, aes_key *key, aes_block *iv, uint32_t nb_blocks);
+void aes_gen_ctr(aes_block *output, aes_key *key, const aes_block *iv, uint32_t nb_blocks);
+void aes_gen_ctr_cont(aes_block *output, aes_key *key, aes_block *iv, uint32_t nb_blocks);
 
 void aes_encrypt_xts(aes_block *output, aes_key *key, aes_key *key2, aes_block *sector,
                      uint32_t spoint, aes_block *input, uint32_t nb_blocks);
diff --git a/cbits/block128.h b/cbits/block128.h
--- a/cbits/block128.h
+++ b/cbits/block128.h
@@ -46,7 +46,7 @@
 	for (i = 0; i < len; i++) block->b[i] = src[i];
 }
 
-static inline void block128_copy(block128 *d, block128 *s)
+static inline void block128_copy(block128 *d, const block128 *s)
 {
 	d->q[0] = s->q[0]; d->q[1] = s->q[1];
 }
@@ -56,13 +56,13 @@
 	d->q[0] = 0; d->q[1] = 0;
 }
 
-static inline void block128_xor(block128 *d, block128 *s)
+static inline void block128_xor(block128 *d, const block128 *s)
 {
 	d->q[0] ^= s->q[0];
 	d->q[1] ^= s->q[1];
 }
 
-static inline void block128_vxor(block128 *d, block128 *s1, block128 *s2)
+static inline void block128_vxor(block128 *d, const block128 *s1, const block128 *s2)
 {
 	d->q[0] = s1->q[0] ^ s2->q[0];
 	d->q[1] = s1->q[1] ^ s2->q[1];
diff --git a/cipher-aes.cabal b/cipher-aes.cabal
--- a/cipher-aes.cabal
+++ b/cipher-aes.cabal
@@ -1,5 +1,5 @@
 Name:                cipher-aes
-Version:             0.2.8
+Version:             0.2.9
 Description:
     Fast AES cipher implementation with advanced mode of operations.
     .
@@ -46,7 +46,7 @@
                      cbits/aes.c
                      cbits/gf.c
                      cbits/cpu.c
-  if flag(support_aesni) && os(linux) && (arch(i386) || arch(x86_64))
+  if flag(support_aesni) && (os(linux) || os(freebsd)) && (arch(i386) || arch(x86_64))
     CC-options:      -mssse3 -maes -mpclmul -DWITH_AESNI
     C-sources:       cbits/aes_x86ni.c
 
