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,56 @@
        -> 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 $ \o ->
+                    keyToPtr ctx $ \k ->
+                    ivCopyPtr iv $ \i -> do
+                        c_aes_gen_ctr_cont (castPtr o) k i (fromIntegral nbBlocks)
+        let !out = B.PS fptr 0 outputLength
+        return $! (out `seq` newIv `seq` (out, newIv))
+  where
+        (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 +422,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 +616,9 @@
 ------------------------------------------------------------------------
 foreign import ccall "aes.h aes_gen_ctr"
     c_aes_gen_ctr :: CString -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()
+
+foreign import ccall unsafe "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/KATGCM.hs b/Tests/KATGCM.hs
--- a/Tests/KATGCM.hs
+++ b/Tests/KATGCM.hs
@@ -58,8 +58,36 @@
         , {-tag = -}"\x94\xd1\x47\xc3\xa2\xca\x93\xe9\x66\x93\x1e\x3b\xb3\xbb\x67\x01")
     ]
 
+vectors_aes256_enc :: [KATGCM]
+vectors_aes256_enc =
+    [
+        ( "\xb5\x2c\x50\x5a\x37\xd7\x8e\xda\x5d\xd3\x4f\x20\xc2\x25\x40\xea\x1b\x58\x96\x3c\xf8\xe5\xbf\x8f\xfa\x85\xf9\xf2\x49\x25\x05\xb4"
+        , "\x51\x6c\x33\x92\x9d\xf5\xa3\x28\x4f\xf4\x63\xd7"
+        , ""
+        , ""
+        , ""
+        , 16
+        , "\xbd\xc1\xac\x88\x4d\x33\x24\x57\xa1\xd2\x66\x4f\x16\x8c\x76\xf0")
+    ,   ( "\x78\xdc\x4e\x0a\xaf\x52\xd9\x35\xc3\xc0\x1e\xea\x57\x42\x8f\x00\xca\x1f\xd4\x75\xf5\xda\x86\xa4\x9c\x8d\xd7\x3d\x68\xc8\xe2\x23"
+        , "\xd7\x9c\xf2\x2d\x50\x4c\xc7\x93\xc3\xfb\x6c\x8a"
+        , "\xb9\x6b\xaa\x8c\x1c\x75\xa6\x71\xbf\xb2\xd0\x8d\x06\xbe\x5f\x36"
+        , ""
+        , ""
+        , 16
+        , "\x3e\x5d\x48\x6a\xa2\xe3\x0b\x22\xe0\x40\xb8\x57\x23\xa0\x6e\x76")
+    ,   ( "\xc3\xf1\x05\x86\xf2\x46\xaa\xca\xdc\xce\x37\x01\x44\x17\x70\xc0\x3c\xfe\xc9\x40\xaf\xe1\x90\x8c\x4c\x53\x7d\xf4\xe0\x1c\x50\xa0"
+        , "\x4f\x52\xfa\xa1\xfa\x67\xa0\xe5\xf4\x19\x64\x52"
+        , "\x46\xf9\xa2\x2b\x4e\x52\xe1\x52\x65\x13\xa9\x52\xdb\xee\x3b\x91\xf6\x95\x95\x50\x1e\x01\x77\xd5\x0f\xf3\x64\x63\x85\x88\xc0\x8d\x92\xfa\xb8\xc5\x8a\x96\x9b\xdc\xc8\x4c\x46\x8d\x84\x98\xc4\xf0\x63\x92\xb9\x9e\xd5\xe0\xc4\x84\x50\x7f\xc4\x8d\xc1\x8d\x87\xc4\x0e\x2e\xd8\x48\xb4\x31\x50\xbe\x9d\x36\xf1\x4c\xf2\xce\xf1\x31\x0b\xa4\xa7\x45\xad\xcc\x7b\xdc\x41\xf6"
+        , "\x79\xd9\x7e\xa3\xa2\xed\xd6\x50\x45\x82\x1e\xa7\x45\xa4\x47\x42"
+        , "\x56\x0c\xf7\x16\xe5\x61\x90\xe9\x39\x7c\x2f\x10\x36\x29\xeb\x1f"
+        , 16
+        , "\xff\x7c\x91\x24\x87\x96\x44\xe8\x05\x55\x68\x7d\x27\x3c\x55\xd8"
+        )
+    ]
+
 vectors_encrypt =
-	[ ("AES128 Enc", vectors_aes128_enc)
+    [ ("AES128 Enc", vectors_aes128_enc)
+    , ("AES256 Enc", vectors_aes256_enc)
     ]
 
 vectors_decrypt = []
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 }
@@ -62,10 +69,16 @@
     { kat_ECB  = map toKatECB KATECB.vectors_aes256_enc
     , kat_CBC  = map toKatCBC KATCBC.vectors_aes256_enc
     , kat_XTS  = map toKatXTS KATXTS.vectors_aes256_enc
+    , kat_AEAD = map toKatGCM KATGCM.vectors_aes256_enc
     }
 
 main = defaultMain
     [ 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
@@ -169,7 +169,7 @@
 #define aes_decrypt_block(o,k,i) \
 	(((block_f) (branch_table[DECRYPT_BLOCK_128 + k->strength]))(o,k,i))
 #else
-#define GET_INIT(strenght) aes_generic_init
+#define GET_INIT(strength) aes_generic_init
 #define GET_ECB_ENCRYPT(strength) aes_generic_encrypt_ecb
 #define GET_ECB_DECRYPT(strength) aes_generic_decrypt_ecb
 #define GET_CBC_ENCRYPT(strength) aes_generic_encrypt_cbc
@@ -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/aes_generic.c b/cbits/aes_generic.c
--- a/cbits/aes_generic.c
+++ b/cbits/aes_generic.c
@@ -89,7 +89,7 @@
 };
 
 #define G(a,b,c,d,e,f) { a,b,c,d,e,f }
-uint8_t gmtab[256][6] =
+static uint8_t gmtab[256][6] =
 {
 	G(0x00, 0x00, 0x00, 0x00, 0x00, 0x00), G(0x02, 0x03, 0x09, 0x0b, 0x0d, 0x0e),
 	G(0x04, 0x06, 0x12, 0x16, 0x1a, 0x1c), G(0x06, 0x05, 0x1b, 0x1d, 0x17, 0x12),
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.11
 Description:
     Fast AES cipher implementation with advanced mode of operations.
     .
@@ -24,7 +24,7 @@
 Synopsis:            Fast AES cipher implementation with advanced mode of operations
 Category:            Cryptography
 Build-Type:          Simple
-Homepage:            http://github.com/vincenthz/hs-cipher-aes
+Homepage:            https://github.com/vincenthz/hs-cipher-aes
 Cabal-Version:       >=1.8
 Extra-Source-Files:  Tests/*.hs
                      cbits/*.h
@@ -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
 
@@ -78,4 +78,4 @@
 
 source-repository head
   type:     git
-  location: git://github.com/vincenthz/hs-cipher-aes
+  location: https://github.com/vincenthz/hs-cipher-aes
