packages feed

cipher-aes 0.2.8 → 0.2.9

raw patch · 6 files changed

+101/−11 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Crypto.Cipher.AES: aesIV_ :: ByteString -> AESIV
+ Crypto.Cipher.AES: data AESIV
+ Crypto.Cipher.AES: genCounter :: AES -> AESIV -> Int -> (ByteString, AESIV)
+ Crypto.Cipher.AES: instance Byteable AESIV
+ Crypto.Cipher.AES: instance Eq AESIV
+ Crypto.Cipher.AES: instance Show AESIV

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,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 ()
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 }@@ -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')     ]
cbits/aes.c view
@@ -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/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.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