diff --git a/Crypto/Cipher/AES.hs b/Crypto/Cipher/AES.hs
--- a/Crypto/Cipher/AES.hs
+++ b/Crypto/Cipher/AES.hs
@@ -157,7 +157,7 @@
 sizeGCM = 80
 
 sizeOCB :: Int
-sizeOCB = 96
+sizeOCB = 160
 
 keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a
 keyToPtr (AES b) f = withSecureMemPtr b (f . castPtr)
diff --git a/cbits/aes.c b/cbits/aes.c
--- a/cbits/aes.c
+++ b/cbits/aes.c
@@ -390,23 +390,30 @@
 	}
 }
 
-static void ocb_block_double(block128 *output, block128 *input)
+static inline void ocb_block_double(block128 *d, block128 *s)
 {
 	unsigned int i;
-	uint8_t tmp = input->b[0];
+	uint8_t tmp = s->b[0];
 
-	if (output != input) block128_copy(output, input);
 	for (i=0; i<15; i++)
-		output->b[i] = (input->b[i] << 1) | (input->b[i+1] >> 7);
-	output->b[15] = (input->b[15] << 1) ^ ((tmp >> 7) * 0x87);
+		d->b[i] = (s->b[i] << 1) | (s->b[i+1] >> 7);
+	d->b[15] = (s->b[15] << 1) ^ ((tmp >> 7) * 0x87);
 }
 
-static void ocb_get_L_i(block128 *l, block128 *ldollar, unsigned int i)
+static void ocb_get_L_i(block128 *l, block128 *lis, unsigned int i)
 {
-	/* TODO optimise with a table. */
-	ocb_block_double(l, ldollar);
-	for ( ; (i&1) == 0; i >>= 1) /* double for each trailing 0 */
-		ocb_block_double(l, l);
+#define L_CACHED 4
+	i = bitfn_ntz(i);
+	if (i < L_CACHED) {
+		block128_copy(l, &lis[i]);
+	} else {
+		i -= (L_CACHED - 1);
+		block128_copy(l, &lis[L_CACHED - 1]);
+		while (i--) {
+			ocb_block_double(l, l);
+		}
+	}
+#undef L_CACHED
 }
 
 void aes_ocb_init(aes_ocb *ocb, aes_key *key, uint8_t *iv, uint32_t len)
@@ -420,10 +427,15 @@
 		len = 15;
 	}
 
-	/* create L*, and L$ */
+	/* create L*, and L$,L0,L1,L2,L3 */
 	block128_zero(&tmp);
 	aes_encrypt_block(&ocb->lstar, key, &tmp);
+
 	ocb_block_double(&ocb->ldollar, &ocb->lstar);
+	ocb_block_double(&ocb->li[0], &ocb->ldollar);
+	ocb_block_double(&ocb->li[1], &ocb->li[0]);
+	ocb_block_double(&ocb->li[2], &ocb->li[1]);
+	ocb_block_double(&ocb->li[3], &ocb->li[2]);
 
 	/* create strech from the nonce */
 	block128_zero(&nonce);
@@ -434,6 +446,7 @@
 	nonce.b[15] &= 0xC0;
 	aes_encrypt_block(&ktop, key, &nonce);
 	memcpy(stretch, ktop.b, 16);
+
 	memcpy(tmp.b, ktop.b + 1, 8);
 	block128_xor(&tmp, &ktop);
 	memcpy(stretch + 16, tmp.b, 8);
@@ -460,7 +473,7 @@
 	unsigned int i;
 
 	for (i=1; i<= length/16; i++, input=input+16) {
-		ocb_get_L_i(&tmp, &ocb->ldollar, i);
+		ocb_get_L_i(&tmp, ocb->li, i);
 		block128_xor(&ocb->offset_aad, &tmp);
 
 		block128_vxor(&tmp, &ocb->offset_aad, (block128 *) input);
@@ -669,7 +682,7 @@
 
 	for (i = 1; i <= length/16; i++, input += 16, output += 16) {
 		/* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-		ocb_get_L_i(&tmp, &ocb->ldollar, i);
+		ocb_get_L_i(&tmp, ocb->li, i);
 		block128_xor(&ocb->offset_enc, &tmp);
 
 		block128_vxor(&tmp, &ocb->offset_enc, (block128 *) input);
diff --git a/cbits/aes.h b/cbits/aes.h
--- a/cbits/aes.h
+++ b/cbits/aes.h
@@ -56,12 +56,13 @@
 } aes_gcm;
 
 typedef struct {
-	block128 lstar;
-	block128 ldollar;
 	block128 offset_aad;
 	block128 offset_enc;
 	block128 sum_aad;
 	block128 sum_enc;
+	block128 lstar;
+	block128 ldollar;
+	block128 li[4];
 } aes_ocb;
 
 /* in bytes: either 16,24,32 */
diff --git a/cbits/aes_x86ni_impl.c b/cbits/aes_x86ni_impl.c
--- a/cbits/aes_x86ni_impl.c
+++ b/cbits/aes_x86ni_impl.c
@@ -236,8 +236,8 @@
 		case 15: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0x80); break;
 		default: mask = _mm_setr_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15); break;
 		}
-		memset(&block.b, 0, 16);
-		memcpy(&block.b, input, part_block_len);
+		block128_zero(&block);
+		block128_copy_bytes(&block, input, part_block_len);
 
 		/* iv += 1 */
 		iv = _mm_add_epi64(iv, one);
diff --git a/cbits/bitfn.h b/cbits/bitfn.h
--- a/cbits/bitfn.h
+++ b/cbits/bitfn.h
@@ -158,6 +158,12 @@
 }
 #endif
 
+#ifdef __GNUC__
+#define bitfn_ntz(n) __builtin_ctz(n)
+#else
+#error "define ntz for your platform"
+#endif
+
 #ifdef __MINGW32__
   # define LITTLE_ENDIAN 1234
   # define BYTE_ORDER    LITTLE_ENDIAN
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.7
+Version:             0.2.8
 Description:
     Fast AES cipher implementation with advanced mode of operations.
     .
@@ -30,6 +30,10 @@
                      cbits/*.h
                      cbits/aes_x86ni_impl.c
 
+Flag support_aesni
+  Description:       allow compilation with AESNI on system and architecture that supports it
+  Default:           True
+
 Library
   Build-Depends:     base >= 4 && < 5
                    , bytestring
@@ -42,7 +46,7 @@
                      cbits/aes.c
                      cbits/gf.c
                      cbits/cpu.c
-  if os(linux) && (arch(i386) || arch(x86_64))
+  if flag(support_aesni) && os(linux) && (arch(i386) || arch(x86_64))
     CC-options:      -mssse3 -maes -mpclmul -DWITH_AESNI
     C-sources:       cbits/aes_x86ni.c
 
