1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
-- |
-- 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 cipher bsLen = (bsLen `mod` blockSize cipher) == 0
notBlockSized :: (BlockCipher cipher, BlockCipherIO cipher) => cipher -> a
notBlockSized = undefined
withDest :: BlockCipherIO cipher
=> cipher
-> ByteString
-> (PtrDest -> PtrSource -> BufferLength -> IO ())
-> ByteString
withDest cipher bs f
| B.null bs = B.empty
| not (isBlockSized cipher len) = notBlockSized cipher
| otherwise =
B.unsafeCreate len $ \dst ->
withBytePtr bs $ \src ->
f dst src (fromIntegral len)
where len = B.length 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 cipher bs = withDest cipher bs $ ecbEncryptMutable cipher
-- | Decrypt using the ECB mode.
--
-- input need to be a multiple of the blocksize
ecbDecryptOfIO :: BlockCipherIO cipher => cipher -> ByteString -> ByteString
ecbDecryptOfIO cipher bs = withDest cipher bs $ ecbEncryptMutable 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')
-}
|