packages feed

cipher-aes 0.2.6 → 0.2.7

raw patch · 6 files changed

+417/−5 lines, 6 files

Files

Crypto/Cipher/AES.hs view
@@ -33,6 +33,7 @@     , encryptCTR     , encryptXTS     , encryptGCM+    , encryptOCB      -- * decryption     , decryptECB@@ -40,6 +41,7 @@     , decryptCTR     , decryptXTS     , decryptGCM+    , decryptOCB     ) where  import Data.Word@@ -97,6 +99,7 @@     xtsEncrypt = encryptXTS     xtsDecrypt = decryptXTS     aeadInit AEAD_GCM aes iv = Just $ AEAD aes $ AEADState $ gcmInit aes iv+    aeadInit AEAD_OCB aes iv = Just $ AEAD aes $ AEADState $ ocbInit aes iv     aeadInit _        _    _ = Nothing  instance AEADModeImpl AES AESGCM where@@ -105,6 +108,12 @@     aeadStateDecrypt = gcmAppendDecrypt     aeadStateFinalize = gcmFinish +instance AEADModeImpl AES AESOCB where+    aeadStateAppendHeader = ocbAppendAAD+    aeadStateEncrypt = ocbAppendEncrypt+    aeadStateDecrypt = ocbAppendDecrypt+    aeadStateFinalize = ocbFinish+ #define INSTANCE_BLOCKCIPHER(CSTR) \ instance BlockCipher CSTR where \     { blockSize _ = 16 \@@ -116,6 +125,7 @@     ; xtsEncrypt (CSTR aes1, CSTR aes2) = encryptXTS (aes1,aes2) \     ; xtsDecrypt (CSTR aes1, CSTR aes2) = decryptXTS (aes1,aes2) \     ; aeadInit AEAD_GCM cipher@(CSTR aes) iv = Just $ AEAD cipher $ AEADState $ gcmInit aes iv \+    ; aeadInit AEAD_OCB cipher@(CSTR aes) iv = Just $ AEAD cipher $ AEADState $ ocbInit aes iv \     ; aeadInit _        _                  _ = Nothing \     }; \ \@@ -124,6 +134,13 @@     ; aeadStateEncrypt (CSTR aes) gcmState input = gcmAppendEncrypt aes gcmState input \     ; aeadStateDecrypt (CSTR aes) gcmState input = gcmAppendDecrypt aes gcmState input \     ; aeadStateFinalize (CSTR aes) gcmState len  = gcmFinish aes gcmState len \+    }; \+\+instance AEADModeImpl CSTR AESOCB where \+    { aeadStateAppendHeader (CSTR aes) ocbState bs = ocbAppendAAD aes ocbState bs \+    ; aeadStateEncrypt (CSTR aes) ocbState input = ocbAppendEncrypt aes ocbState input \+    ; aeadStateDecrypt (CSTR aes) ocbState input = ocbAppendDecrypt aes ocbState input \+    ; aeadStateFinalize (CSTR aes) ocbState len  = ocbFinish aes ocbState len \     }  INSTANCE_BLOCKCIPHER(AES128)@@ -133,9 +150,15 @@ -- | AESGCM State newtype AESGCM = AESGCM SecureMem +-- | AESOCB State+newtype AESOCB = AESOCB SecureMem+ sizeGCM :: Int sizeGCM = 80 +sizeOCB :: Int+sizeOCB = 96+ keyToPtr :: AES -> (Ptr AES -> IO a) -> IO a keyToPtr (AES b) f = withSecureMemPtr b (f . castPtr) @@ -159,6 +182,13 @@ withNewGCMSt :: AESGCM -> (Ptr AESGCM -> IO ()) -> IO AESGCM withNewGCMSt (AESGCM gcmSt) f = withSecureMemCopy gcmSt (f . castPtr) >>= \sm2 -> return (AESGCM sm2) +withOCBKeyAndCopySt :: AES -> AESOCB -> (Ptr AESOCB -> Ptr AES -> IO a) -> IO (a, AESOCB)+withOCBKeyAndCopySt aes (AESOCB gcmSt) f =+    keyToPtr aes $ \aesPtr -> do+        newSt <- secureMemCopy gcmSt+        a     <- withSecureMemPtr newSt $ \gcmStPtr -> f (castPtr gcmStPtr) aesPtr+        return (a, AESOCB newSt)+ -- | Initialize a new context with a key -- -- Key need to be of length 16, 24 or 32 bytes. any other values will cause undefined behavior@@ -240,6 +270,17 @@            -> (ByteString, AuthTag) -- ^ ciphertext and tag encryptGCM = doGCM gcmAppendEncrypt +-- | encrypt using OCB v3+-- return the encrypted bytestring and the tag associated+{-# NOINLINE encryptOCB #-}+encryptOCB :: Byteable iv+           => AES        -- ^ AES Context+           -> iv         -- ^ IV initial vector of any size+           -> ByteString -- ^ data to authenticate (AAD)+           -> ByteString -- ^ data to encrypt+           -> (ByteString, AuthTag) -- ^ ciphertext and tag+encryptOCB = doOCB ocbAppendEncrypt+ -- | encrypt using XTS -- -- the first key is the normal block encryption key@@ -293,6 +334,16 @@            -> (ByteString, AuthTag) -- ^ plaintext and tag decryptGCM = doGCM gcmAppendDecrypt +-- | decrypt using Offset Codebook Mode (OCB)+{-# NOINLINE decryptOCB #-}+decryptOCB :: Byteable iv+           => AES        -- ^ Key+           -> iv         -- ^ IV initial vector of any size+           -> ByteString -- ^ data to authenticate (AAD)+           -> ByteString -- ^ data to decrypt+           -> (ByteString, AuthTag) -- ^ plaintext and tag+decryptOCB = doOCB ocbAppendDecrypt+ {-# INLINE doECB #-} doECB :: (Ptr b -> Ptr AES -> CString -> CUInt -> IO ())       -> AES -> ByteString -> ByteString@@ -335,6 +386,10 @@   where (nbBlocks, r) = len `quotRem` 16         len           = B.length input +------------------------------------------------------------------------+-- GCM+------------------------------------------------------------------------+ {-# INLINE doGCM #-} doGCM :: Byteable iv       => (AES -> AESGCM -> ByteString -> (ByteString, AESGCM))@@ -402,33 +457,109 @@   where computeTag = unsafeCreate 16 $ \t ->                         withGCMKeyAndCopySt ctx gcm (c_aes_gcm_finish (castPtr t)) >> return () +------------------------------------------------------------------------+-- OCB v3+------------------------------------------------------------------------++{-# INLINE doOCB #-}+doOCB :: Byteable iv+      => (AES -> AESOCB -> ByteString -> (ByteString, AESOCB))+      -> AES+      -> iv+      -> ByteString+      -> ByteString+      -> (ByteString, AuthTag)+doOCB f ctx iv aad input = (output, tag)+  where tag             = ocbFinish ctx after 16+        (output, after) = f ctx afterAAD input+        afterAAD        = ocbAppendAAD ctx ini aad+        ini             = ocbInit ctx iv++-- | initialize an ocb context+{-# NOINLINE ocbInit #-}+ocbInit :: Byteable iv => AES -> iv -> AESOCB+ocbInit ctx iv = unsafePerformIO $ do+    sm <- createSecureMem sizeOCB $ \ocbStPtr ->+            withKeyAndIV ctx iv $ \k v ->+            c_aes_ocb_init (castPtr ocbStPtr) k v (fromIntegral $ byteableLength iv)+    return $ AESOCB sm++-- | append data which is going to just be authentified to the OCB context.+--+-- need to happen after initialization and before appending encryption/decryption data.+{-# NOINLINE ocbAppendAAD #-}+ocbAppendAAD :: AES -> AESOCB -> ByteString -> AESOCB+ocbAppendAAD ctx ocb input = unsafePerformIO (snd `fmap` withOCBKeyAndCopySt ctx ocb doAppend)+  where doAppend ocbStPtr aesPtr =+            unsafeUseAsCString input $ \i ->+            c_aes_ocb_aad ocbStPtr aesPtr i (fromIntegral $ B.length input)++-- | append data to encrypt and append to the OCB context+--+-- bytestring need to be multiple of AES block size, unless it's the last call to this function.+-- need to happen after AAD appending, or after initialization if no AAD data.+{-# NOINLINE ocbAppendEncrypt #-}+ocbAppendEncrypt :: AES -> AESOCB -> ByteString -> (ByteString, AESOCB)+ocbAppendEncrypt ctx ocb input = unsafePerformIO $ withOCBKeyAndCopySt ctx ocb doEnc+  where len = B.length input+        doEnc ocbStPtr aesPtr =+            create len $ \o ->+            unsafeUseAsCString input $ \i ->+            c_aes_ocb_encrypt (castPtr o) ocbStPtr aesPtr i (fromIntegral len)++-- | append data to decrypt and append to the OCB context+--+-- bytestring need to be multiple of AES block size, unless it's the last call to this function.+-- need to happen after AAD appending, or after initialization if no AAD data.+{-# NOINLINE ocbAppendDecrypt #-}+ocbAppendDecrypt :: AES -> AESOCB -> ByteString -> (ByteString, AESOCB)+ocbAppendDecrypt ctx ocb input = unsafePerformIO $ withOCBKeyAndCopySt ctx ocb doDec+  where len = B.length input+        doDec ocbStPtr aesPtr =+            create len $ \o ->+            unsafeUseAsCString input $ \i ->+            c_aes_ocb_decrypt (castPtr o) ocbStPtr aesPtr i (fromIntegral len)++-- | Generate the Tag from OCB context+{-# NOINLINE ocbFinish #-}+ocbFinish :: AES -> AESOCB -> Int -> AuthTag+ocbFinish ctx ocb taglen = AuthTag $ B.take taglen computeTag+  where computeTag = unsafeCreate 16 $ \t ->+                        withOCBKeyAndCopySt ctx ocb (c_aes_ocb_finish (castPtr t)) >> return ()++------------------------------------------------------------------------ foreign import ccall "aes.h aes_initkey"     c_aes_init :: Ptr AES -> CString -> CUInt -> IO () +------------------------------------------------------------------------ foreign import ccall "aes.h aes_encrypt_ecb"     c_aes_encrypt_ecb :: CString -> Ptr AES -> CString -> CUInt -> IO ()  foreign import ccall "aes.h aes_decrypt_ecb"     c_aes_decrypt_ecb :: CString -> Ptr AES -> CString -> CUInt -> IO () +------------------------------------------------------------------------ foreign import ccall "aes.h aes_encrypt_cbc"     c_aes_encrypt_cbc :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO ()  foreign import ccall "aes.h aes_decrypt_cbc"     c_aes_decrypt_cbc :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO () +------------------------------------------------------------------------ foreign import ccall "aes.h aes_encrypt_xts"     c_aes_encrypt_xts :: CString -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO ()  foreign import ccall "aes.h aes_decrypt_xts"     c_aes_decrypt_xts :: CString -> Ptr AES -> Ptr AES -> Ptr Word8 -> CUInt -> CString -> CUInt -> IO () +------------------------------------------------------------------------ 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_encrypt_ctr"     c_aes_encrypt_ctr :: CString -> Ptr AES -> Ptr Word8 -> CString -> CUInt -> IO () +------------------------------------------------------------------------ foreign import ccall "aes.h aes_gcm_init"     c_aes_gcm_init :: Ptr AESGCM -> Ptr AES -> Ptr Word8 -> CUInt -> IO () @@ -443,3 +574,19 @@  foreign import ccall "aes.h aes_gcm_finish"     c_aes_gcm_finish :: CString -> Ptr AESGCM -> Ptr AES -> IO ()++------------------------------------------------------------------------+foreign import ccall "aes.h aes_ocb_init"+    c_aes_ocb_init :: Ptr AESOCB -> Ptr AES -> Ptr Word8 -> CUInt -> IO ()++foreign import ccall "aes.h aes_ocb_aad"+    c_aes_ocb_aad :: Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()++foreign import ccall "aes.h aes_ocb_encrypt"+    c_aes_ocb_encrypt :: CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()++foreign import ccall "aes.h aes_ocb_decrypt"+    c_aes_ocb_decrypt :: CString -> Ptr AESOCB -> Ptr AES -> CString -> CUInt -> IO ()++foreign import ccall "aes.h aes_ocb_finish"+    c_aes_ocb_finish :: CString -> Ptr AESOCB -> Ptr AES -> IO ()
+ Tests/KATOCB3.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE OverloadedStrings #-}+module KATOCB3 where++import qualified Data.ByteString as B+import Data.ByteString.Char8 ()++-- (key, iv, aad, input, out, taglen, tag)+type KATOCB3 = (B.ByteString, B.ByteString, B.ByteString, B.ByteString, B.ByteString, Int, B.ByteString)++key1   = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"+nonce1 = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b"++vectors_aes128_enc :: [KATOCB3]+vectors_aes128_enc =+    [ ( {-key = -} key1+      , {-iv = -} nonce1+      , {-aad = -}""+      , {-input = -}""+      , {-out = -}""+      , {-taglen = -} 16+      , {-tag = -} "\x19\x7b\x9c\x3c\x44\x1d\x3c\x83\xea\xfb\x2b\xef\x63\x3b\x91\x82")+    , ( key1, nonce1+      , "\x00\x01\x02\x03\x04\x05\x06\x07"+      , "\x00\x01\x02\x03\x04\x05\x06\x07"+      , "\x92\xb6\x57\x13\x0a\x74\xb8\x5a"+      , 16+      , "\x16\xdc\x76\xa4\x6d\x47\xe1\xea\xd5\x37\x20\x9e\x8a\x96\xd1\x4e")+    , ( key1, nonce1+      , "\x00\x01\x02\x03\x04\x05\x06\x07"+      , ""+      , ""+      , 16+      , "\x98\xb9\x15\x52\xc8\xc0\x09\x18\x50\x44\xe3\x0a\x6e\xb2\xfe\x21")+    , ( key1, nonce1+      , ""+      , "\x00\x01\x02\x03\x04\x05\x06\x07"+      , "\x92\xb6\x57\x13\x0a\x74\xb8\x5a"+      , 16+      , "\x97\x1e\xff\xca\xe1\x9a\xd4\x71\x6f\x88\xe8\x7b\x87\x1f\xbe\xed")+    , ( key1, nonce1+      , "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"+      , "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"+      , "\xbe\xa5\xe8\x79\x8d\xbe\x71\x10\x03\x1c\x14\x4d\xa0\xb2\x61\x22"+      , 16+      , "\x77\x6c\x99\x24\xd6\x72\x3a\x1f\xc4\x52\x45\x32\xac\x3e\x5b\xeb")+    ]++vectors_encrypt =+    [ ("AES128 Enc", vectors_aes128_enc)+    ]++vectors_decrypt = []
Tests/Tests.hs view
@@ -21,12 +21,13 @@ import qualified KATCBC import qualified KATXTS import qualified KATGCM+import qualified KATOCB3  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 }-toKatGCM (k,iv,h,p,c,taglen,tag) =-    KAT_AEAD { aeadMode       = AEAD_GCM+toKatAEAD mode (k,iv,h,p,c,taglen,tag) =+    KAT_AEAD { aeadMode       = mode              , aeadKey        = k              , aeadIV         = iv              , aeadHeader     = h@@ -35,6 +36,8 @@              , aeadTaglen     = taglen              , aeadTag        = AuthTag tag              }+toKatGCM = toKatAEAD AEAD_GCM+toKatOCB = toKatAEAD AEAD_OCB  kats128 = defaultKATs     { kat_ECB  = map toKatECB KATECB.vectors_aes128_enc@@ -46,7 +49,8 @@                            }                  ]     , kat_XTS  = map toKatXTS KATXTS.vectors_aes128_enc-    , kat_AEAD = map toKatGCM KATGCM.vectors_aes128_enc+    , kat_AEAD = map toKatGCM KATGCM.vectors_aes128_enc +++                 map toKatOCB KATOCB3.vectors_aes128_enc     }  kats192 = defaultKATs
cbits/aes.c view
@@ -49,6 +49,8 @@                              uint32_t spoint, aes_block *input, uint32_t nb_blocks); void aes_generic_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length); void aes_generic_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length);+void aes_generic_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);+void aes_generic_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);  enum { 	/* init */@@ -67,9 +69,12 @@ 	/* xts */ 	ENCRYPT_XTS_128, ENCRYPT_XTS_192, ENCRYPT_XTS_256, 	DECRYPT_XTS_128, DECRYPT_XTS_192, DECRYPT_XTS_256,-	/* xts */+	/* gcm */ 	ENCRYPT_GCM_128, ENCRYPT_GCM_192, ENCRYPT_GCM_256, 	DECRYPT_GCM_128, DECRYPT_GCM_192, DECRYPT_GCM_256,+	/* ocb */+	ENCRYPT_OCB_128, ENCRYPT_OCB_192, ENCRYPT_OCB_256,+	DECRYPT_OCB_128, DECRYPT_OCB_192, DECRYPT_OCB_256, };  void *branch_table[] = {@@ -116,6 +121,13 @@ 	[DECRYPT_GCM_128]   = aes_generic_gcm_decrypt, 	[DECRYPT_GCM_192]   = aes_generic_gcm_decrypt, 	[DECRYPT_GCM_256]   = aes_generic_gcm_decrypt,+	/* OCB */+	[ENCRYPT_OCB_128]   = aes_generic_ocb_encrypt,+	[ENCRYPT_OCB_192]   = aes_generic_ocb_encrypt,+	[ENCRYPT_OCB_256]   = aes_generic_ocb_encrypt,+	[DECRYPT_OCB_128]   = aes_generic_ocb_decrypt,+	[DECRYPT_OCB_192]   = aes_generic_ocb_decrypt,+	[DECRYPT_OCB_256]   = aes_generic_ocb_decrypt, };  typedef void (*init_f)(aes_key *, uint8_t *, uint8_t);@@ -124,6 +136,7 @@ typedef void (*ctr_f)(uint8_t *output, aes_key *key, aes_block *iv, uint8_t *input, uint32_t length); typedef void (*xts_f)(aes_block *output, aes_key *k1, aes_key *k2, aes_block *dataunit, uint32_t spoint, aes_block *input, uint32_t nb_blocks); typedef void (*gcm_crypt_f)(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length);+typedef void (*ocb_crypt_f)(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length); typedef void (*block_f)(aes_block *output, aes_key *key, aes_block *input);  #ifdef WITH_AESNI@@ -147,6 +160,10 @@ 	((gcm_crypt_f) (branch_table[ENCRYPT_GCM_128 + strength])) #define GET_GCM_DECRYPT(strength) \ 	((gcm_crypt_f) (branch_table[DECRYPT_GCM_128 + strength]))+#define GET_OCB_ENCRYPT(strength) \+	((ocb_crypt_f) (branch_table[ENCRYPT_OCB_128 + strength]))+#define GET_OCB_DECRYPT(strength) \+	((ocb_crypt_f) (branch_table[DECRYPT_OCB_128 + strength])) #define aes_encrypt_block(o,k,i) \ 	(((block_f) (branch_table[ENCRYPT_BLOCK_128 + k->strength]))(o,k,i)) #define aes_decrypt_block(o,k,i) \@@ -162,6 +179,8 @@ #define GET_XTS_DECRYPT(strength) aes_generic_decrypt_xts #define GET_GCM_ENCRYPT(strength) aes_generic_gcm_encrypt #define GET_GCM_DECRYPT(strength) aes_generic_gcm_decrypt+#define GET_OCB_ENCRYPT(strength) aes_generic_ocb_encrypt+#define GET_OCB_DECRYPT(strength) aes_generic_ocb_decrypt #define aes_encrypt_block(o,k,i) aes_generic_encrypt_block(o,k,i) #define aes_decrypt_block(o,k,i) aes_generic_decrypt_block(o,k,i) #endif@@ -197,6 +216,11 @@ 	/* GCM */ 	branch_table[ENCRYPT_GCM_128] = aes_ni_gcm_encrypt128; 	branch_table[ENCRYPT_GCM_256] = aes_ni_gcm_encrypt256;+	/* OCB */+	/*+	branch_table[ENCRYPT_OCB_128] = aes_ni_ocb_encrypt128;+	branch_table[ENCRYPT_OCB_256] = aes_ni_ocb_encrypt256;+	*/ } #endif @@ -281,6 +305,18 @@ 	d(output, gcm, key, input, length); } +void aes_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length)+{+	ocb_crypt_f e = GET_OCB_ENCRYPT(key->strength);+	e(output, ocb, key, input, length);+}++void aes_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length)+{+	ocb_crypt_f d = GET_OCB_DECRYPT(key->strength);+	d(output, ocb, key, input, length);+}+ static void gcm_ghash_add(aes_gcm *gcm, block128 *b) { 	block128_xor(&gcm->tag, b);@@ -354,6 +390,106 @@ 	} } +static void ocb_block_double(block128 *output, block128 *input)+{+	unsigned int i;+	uint8_t tmp = input->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);+}++static void ocb_get_L_i(block128 *l, block128 *ldollar, 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);+}++void aes_ocb_init(aes_ocb *ocb, aes_key *key, uint8_t *iv, uint32_t len)+{+	block128 tmp, nonce, ktop;+	unsigned char stretch[24];+	unsigned bottom, byteshift, bitshift, i;++	/* we don't accept more than 15 bytes, any bytes higher will be ignored. */+	if (len > 15) {+		len = 15;+	}++	/* create L*, and L$ */+	block128_zero(&tmp);+	aes_encrypt_block(&ocb->lstar, key, &tmp);+	ocb_block_double(&ocb->ldollar, &ocb->lstar);++	/* create strech from the nonce */+	block128_zero(&nonce);+	memcpy(nonce.b + 4, iv, 12);+	nonce.b[0] = (unsigned char)(((16 * 8) % 128) << 1);+	nonce.b[16-12-1] |= 0x01;+	bottom = nonce.b[15] & 0x3F;+	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);++	/* initialize the encryption offset from stretch */+	byteshift = bottom / 8;+	bitshift = bottom % 8;+	if (bitshift != 0)+		for (i = 0; i < 16; i++)+			ocb->offset_enc.b[i] = (stretch[i+byteshift] << bitshift)+			                     | (stretch[i+byteshift+1] >> (8-bitshift));+	else+		for (i = 0; i < 16; i++)+			ocb->offset_enc.b[i] = stretch[i+byteshift];+	/* initialize checksum for aad and encryption, and the aad offset */+	block128_zero(&ocb->sum_aad);+	block128_zero(&ocb->sum_enc);+	block128_zero(&ocb->offset_aad);+}++void aes_ocb_aad(aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length)+{+	block128 tmp;+	unsigned int i;++	for (i=1; i<= length/16; i++, input=input+16) {+		ocb_get_L_i(&tmp, &ocb->ldollar, i);+		block128_xor(&ocb->offset_aad, &tmp);++		block128_vxor(&tmp, &ocb->offset_aad, (block128 *) input);+		aes_encrypt_block(&tmp, key, &tmp);+		block128_xor(&ocb->sum_aad, &tmp);+	}++	length = length % 16; /* Bytes in final block */+	if (length > 0) {+		block128_xor(&ocb->offset_aad, &ocb->lstar);+		block128_zero(&tmp);+		block128_copy_bytes(&tmp, input, length);+		tmp.b[length] = 0x80;+		block128_xor(&tmp, &ocb->offset_aad);+		aes_encrypt_block(&tmp, key, &tmp);+		block128_xor(&ocb->sum_aad, &tmp);+	}+}++void aes_ocb_finish(uint8_t *tag, aes_ocb *ocb, aes_key *key)+{+	block128 tmp;++	block128_vxor(&tmp, &ocb->sum_enc, &ocb->offset_enc);+	block128_xor(&tmp, &ocb->ldollar);+	aes_encrypt_block((block128 *) tag, key, &tmp);+	block128_xor((block128 *) tag, &ocb->sum_aad);+}+ void aes_generic_encrypt_ecb(aes_block *output, aes_key *key, aes_block *input, uint32_t nb_blocks) { 	for ( ; nb_blocks-- > 0; input++, output++) {@@ -525,3 +661,61 @@ 	} } +static int 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;++	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);+		block128_xor(&ocb->offset_enc, &tmp);++		block128_vxor(&tmp, &ocb->offset_enc, (block128 *) input);+		if (encrypt) {+			aes_encrypt_block(&tmp, key, &tmp);+			block128_vxor((block128 *) output, &ocb->offset_enc, &tmp);+			block128_xor(&ocb->sum_enc, (block128 *) input);+		} else {+			aes_decrypt_block(&tmp, key, &tmp);+			block128_vxor((block128 *) output, &ocb->offset_enc, &tmp);+			block128_xor(&ocb->sum_enc, (block128 *) output);+		}+	}++	/* process the last partial block if any */+	length = length % 16;+	if (length > 0) {+		block128_xor(&ocb->offset_enc, &ocb->lstar);+		aes_encrypt_block(&pad, key, &ocb->offset_enc);++		if (encrypt) {+			block128_zero(&tmp);+			block128_copy_bytes(&tmp, input, length);+			tmp.b[length] = 0x80;+			block128_xor(&ocb->sum_enc, &tmp);+			block128_xor(&pad, &tmp);+			memcpy(output, pad.b, length);+			output += length;+		} else {+			block128_copy(&tmp, &pad);+			block128_copy_bytes(&tmp, input, length);+			block128_xor(&tmp, &pad);+			tmp.b[length] = 0x80;+			memcpy(output, tmp.b, length);+			block128_xor(&ocb->sum_enc, &tmp);+			input += length;+		}+	}+}++void aes_generic_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length)+{+	ocb_generic_crypt(output, ocb, key, input, length, 1);+}++void aes_generic_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length)+{+	ocb_generic_crypt(output, ocb, key, input, length, 0);+}
cbits/aes.h view
@@ -55,6 +55,15 @@ 	uint64_t length_input; } aes_gcm; +typedef struct {+	block128 lstar;+	block128 ldollar;+	block128 offset_aad;+	block128 offset_enc;+	block128 sum_aad;+	block128 sum_enc;+} aes_ocb;+ /* in bytes: either 16,24,32 */ void aes_initkey(aes_key *ctx, uint8_t *key, uint8_t size); @@ -79,5 +88,11 @@ void aes_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length); void aes_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *key, uint8_t *input, uint32_t length); void aes_gcm_finish(uint8_t *tag, aes_gcm *gcm, aes_key *key);++void aes_ocb_init(aes_ocb *ocb, aes_key *key, uint8_t *iv, uint32_t len);+void aes_ocb_aad(aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);+void aes_ocb_encrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);+void aes_ocb_decrypt(uint8_t *output, aes_ocb *ocb, aes_key *key, uint8_t *input, uint32_t length);+void aes_ocb_finish(uint8_t *tag, aes_ocb *ocb, aes_key *key);  #endif
cipher-aes.cabal view
@@ -1,5 +1,5 @@ Name:                cipher-aes-Version:             0.2.6+Version:             0.2.7 Description:     Fast AES cipher implementation with advanced mode of operations.     .