packages feed

cipher-aes 0.2.8 → 0.2.11

raw patch · 8 files changed

Files

Crypto/Cipher/AES.hs view
@@ -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 ()
Tests/KATGCM.hs view
@@ -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 = []
Tests/Tests.hs view
@@ -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')     ]
cbits/aes.c view
@@ -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;
cbits/aes.h view
@@ -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);
cbits/aes_generic.c view
@@ -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),
cbits/block128.h view
@@ -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];
cipher-aes.cabal view
@@ -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