-- | -- Module : Crypto.Cipher.Types.Modes -- License : BSD-style -- Maintainer : Vincent Hanquez <vincent@snarc.org> -- Stability : Stable -- Portability : Excellent -- -- block cipher modes immutable interfaces -- module Crypto.Cipher.Types.OfIO ( -- * ECB ecbEncryptOfIO , ecbDecryptOfIO {- -- * CBC , cbcEncryptOfIO , cbcDecryptOfIO -- * CFB , cfbEncryptOfIO , cfbDecryptOfIO , cfb8EncryptOfIO , cfb8DecryptOfIO -- * CTR , ctrCombineOfIO -- * XTS , xtsEncryptOfIO , xtsDecryptOfIO -} ) where import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B import Data.Byteable --import Crypto.Cipher.Types.Base import Crypto.Cipher.Types.Block import Crypto.Cipher.Types.BlockIO --import Foreign.Storable (poke) --import Foreign.Ptr isBlockSized :: (BlockCipher cipher, BlockCipherIO cipher) => cipher -> Int -> Bool isBlockSized :: forall cipher. (BlockCipher cipher, BlockCipherIO cipher) => cipher -> Int -> Bool isBlockSized cipher cipher Int bsLen = (Int bsLen Int -> Int -> Int forall a. Integral a => a -> a -> a `mod` cipher -> Int forall cipher. BlockCipher cipher => cipher -> Int blockSize cipher cipher) Int -> Int -> Bool forall a. Eq a => a -> a -> Bool == Int 0 notBlockSized :: (BlockCipher cipher, BlockCipherIO cipher) => cipher -> a notBlockSized :: forall cipher a. (BlockCipher cipher, BlockCipherIO cipher) => cipher -> a notBlockSized = cipher -> a forall a. HasCallStack => a undefined withDest :: BlockCipherIO cipher => cipher -> ByteString -> (PtrDest -> PtrSource -> BufferLength -> IO ()) -> ByteString withDest :: forall cipher. BlockCipherIO cipher => cipher -> ByteString -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString withDest cipher cipher ByteString bs PtrDest -> PtrDest -> BufferLength -> IO () f | ByteString -> Bool B.null ByteString bs = ByteString B.empty | Bool -> Bool not (cipher -> Int -> Bool forall cipher. (BlockCipher cipher, BlockCipherIO cipher) => cipher -> Int -> Bool isBlockSized cipher cipher Int len) = cipher -> ByteString forall cipher a. (BlockCipher cipher, BlockCipherIO cipher) => cipher -> a notBlockSized cipher cipher | Bool otherwise = Int -> (PtrDest -> IO ()) -> ByteString B.unsafeCreate Int len ((PtrDest -> IO ()) -> ByteString) -> (PtrDest -> IO ()) -> ByteString forall a b. (a -> b) -> a -> b $ \PtrDest dst -> ByteString -> (PtrDest -> IO ()) -> IO () forall a b. Byteable a => a -> (PtrDest -> IO b) -> IO b withBytePtr ByteString bs ((PtrDest -> IO ()) -> IO ()) -> (PtrDest -> IO ()) -> IO () forall a b. (a -> b) -> a -> b $ \PtrDest src -> PtrDest -> PtrDest -> BufferLength -> IO () f PtrDest dst PtrDest src (Int -> BufferLength forall a b. (Integral a, Num b) => a -> b fromIntegral Int len) where len :: Int len = ByteString -> Int B.length ByteString bs {- withDestIV :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> (PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()) -> ByteString withDestIV cipher (IV iv) bs f | B.null bs = B.empty | not (isBlockSized cipher len) = notBlockSized cipher | otherwise = B.unsafeCreate len $ \dst -> withBytePtr iv $ \ivPtr -> withBytePtr bs $ \src -> f ivPtr dst src (fromIntegral len) where len = B.length bs withDestIVAnySize :: BlockCipherIO cipher => IV cipher -> ByteString -> (PtrIV -> PtrDest -> PtrSource -> BufferLength -> IO ()) -> ByteString withDestIVAnySize (IV iv) bs f | B.null bs = B.empty | otherwise = B.unsafeCreate len $ \dst -> withBytePtr iv $ \ivPtr -> withBytePtr bs $ \src -> f ivPtr dst src (fromIntegral len) where len = B.length bs -} -- | Encrypt using the ECB mode. -- -- input need to be a multiple of the blocksize ecbEncryptOfIO :: BlockCipherIO cipher => cipher -> ByteString -> ByteString ecbEncryptOfIO :: forall cipher. BlockCipherIO cipher => cipher -> ByteString -> ByteString ecbEncryptOfIO cipher cipher ByteString bs = cipher -> ByteString -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString forall cipher. BlockCipherIO cipher => cipher -> ByteString -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString withDest cipher cipher ByteString bs ((PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString) -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString forall a b. (a -> b) -> a -> b $ cipher -> PtrDest -> PtrDest -> BufferLength -> IO () forall cipher. BlockCipherIO cipher => cipher -> PtrDest -> PtrDest -> BufferLength -> IO () ecbEncryptMutable cipher cipher -- | Decrypt using the ECB mode. -- -- input need to be a multiple of the blocksize ecbDecryptOfIO :: BlockCipherIO cipher => cipher -> ByteString -> ByteString ecbDecryptOfIO :: forall cipher. BlockCipherIO cipher => cipher -> ByteString -> ByteString ecbDecryptOfIO cipher cipher ByteString bs = cipher -> ByteString -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString forall cipher. BlockCipherIO cipher => cipher -> ByteString -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString withDest cipher cipher ByteString bs ((PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString) -> (PtrDest -> PtrDest -> BufferLength -> IO ()) -> ByteString forall a b. (a -> b) -> a -> b $ cipher -> PtrDest -> PtrDest -> BufferLength -> IO () forall cipher. BlockCipherIO cipher => cipher -> PtrDest -> PtrDest -> BufferLength -> IO () ecbEncryptMutable cipher cipher {- -- | encrypt using the CBC mode. -- -- input need to be a multiple of the blocksize cbcEncryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString cbcEncryptOfIO cipher iv bs = withDestIV cipher iv bs $ cbcEncryptMutable cipher -- | decrypt using the CBC mode. -- -- input need to be a multiple of the blocksize cbcDecryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString cbcDecryptOfIO cipher iv bs = withDestIV cipher iv bs $ cbcDecryptMutable cipher -- | encrypt using the CFB mode. -- -- input need to be a multiple of the blocksize cfbEncryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString cfbEncryptOfIO cipher iv bs = withDestIV cipher iv bs $ cfbEncryptMutable cipher -- | decrypt using the CFB mode. -- -- input need to be a multiple of the blocksize cfbDecryptOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString cfbDecryptOfIO cipher iv bs = withDestIV cipher iv bs $ cfbDecryptMutable cipher -- | combine using the CTR mode. -- -- CTR mode produce a stream of randomized data that is combined -- (by XOR operation) with the input stream. -- -- encryption and decryption are the same operation. -- -- input can be of any size ctrCombineOfIO :: BlockCipherIO cipher => cipher -> IV cipher -> ByteString -> ByteString ctrCombineOfIO cipher iv bs = withDestIVAnySize iv bs $ cfbDecryptMutable cipher -- | encrypt using the XTS mode. -- -- input need to be a multiple of the blocksize xtsEncryptOfIO :: BlockCipherIO cipher => (cipher, cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString xtsEncryptOfIO ciphers@(c1,_) iv ofs bs = withDestIV c1 iv bs $ \ivPtr -> xtsEncryptMutable ciphers ivPtr ofs -- | decrypt using the XTS mode. -- -- input need to be a multiple of the blocksize xtsDecryptOfIO :: BlockCipherIO cipher => (cipher, cipher) -> IV cipher -> DataUnitOffset -> ByteString -> ByteString xtsDecryptOfIO ciphers@(c1,_) iv ofs bs = withDestIV c1 iv bs $ \ivPtr -> xtsDecryptMutable ciphers ivPtr ofs -- | Encrypt using CFB mode in 8 bit output -- -- Effectively turn a Block cipher in CFB mode into a Stream cipher cfb8EncryptOfIO :: BlockCipherIO a => a -> IV a -> B.ByteString -> B.ByteString cfb8EncryptOfIO ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg where loop d iv@(IV i) m | B.null m = return () | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m) where m' = if B.length m < blockSize ctx then m `B.append` B.replicate (blockSize ctx - B.length m) 0 else B.take (blockSize ctx) m r = cfbEncryptOfIO ctx iv m' out = B.head r ni = IV (B.drop 1 i `B.snoc` out) -- | Decrypt using CFB mode in 8 bit output -- -- Effectively turn a Block cipher in CFB mode into a Stream cipher cfb8DecryptOfIO :: BlockCipherIO a => a -> IV a -> B.ByteString -> B.ByteString cfb8DecryptOfIO ctx origIv msg = B.unsafeCreate (B.length msg) $ \dst -> loop dst origIv msg where loop d iv@(IV i) m | B.null m = return () | otherwise = poke d out >> loop (d `plusPtr` 1) ni (B.drop 1 m) where m' = if B.length m < blockSize ctx then m `B.append` B.replicate (blockSize ctx - B.length m) 0 else B.take (blockSize ctx) m r = cfbDecryptOfIO ctx iv m' out = B.head r ni = IV (B.drop 1 i `B.snoc` B.head m') -}