{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE Rank2Types #-}
module Crypto.Cipher.Types.Block
(
BlockCipher(..)
, BlockCipher128(..)
, IV(..)
, makeIV
, nullIV
, ivAdd
, XTS
, AEAD(..)
, AEADModeImpl(..)
, aeadAppendHeader
, aeadEncrypt
, aeadDecrypt
, aeadFinalize
) where
import Data.Word
import Crypto.Error
import Crypto.Cipher.Types.Base
import Crypto.Cipher.Types.GF
import Crypto.Cipher.Types.AEAD
import Crypto.Cipher.Types.Utils
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, withByteArray, Bytes)
import qualified Crypto.Internal.ByteArray as B
import Foreign.Ptr
import Foreign.Storable
data IV c = forall byteArray . ByteArray byteArray => IV byteArray
instance BlockCipher c => ByteArrayAccess (IV c) where
withByteArray :: IV c -> (Ptr p -> IO a) -> IO a
withByteArray (IV byteArray
z) Ptr p -> IO a
f = byteArray -> (Ptr p -> IO a) -> IO a
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray byteArray
z Ptr p -> IO a
f
length :: IV c -> Int
length (IV byteArray
z) = byteArray -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length byteArray
z
instance Eq (IV c) where
(IV byteArray
a) == :: IV c -> IV c -> Bool
== (IV byteArray
b) = byteArray -> byteArray -> Bool
forall bs1 bs2.
(ByteArrayAccess bs1, ByteArrayAccess bs2) =>
bs1 -> bs2 -> Bool
B.eq byteArray
a byteArray
b
type XTS ba cipher = (cipher, cipher)
-> IV cipher
-> DataUnitOffset
-> ba
-> ba
class Cipher cipher => BlockCipher cipher where
blockSize :: cipher -> Int
ecbEncrypt :: ByteArray ba => cipher -> ba -> ba
ecbDecrypt :: ByteArray ba => cipher -> ba -> ba
cbcEncrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
cbcEncrypt = cipher -> IV cipher -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher cipher) =>
cipher -> IV cipher -> ba -> ba
cbcEncryptGeneric
cbcDecrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
cbcDecrypt = cipher -> IV cipher -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher cipher) =>
cipher -> IV cipher -> ba -> ba
cbcDecryptGeneric
cfbEncrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
cfbEncrypt = cipher -> IV cipher -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher cipher) =>
cipher -> IV cipher -> ba -> ba
cfbEncryptGeneric
cfbDecrypt :: ByteArray ba => cipher -> IV cipher -> ba -> ba
cfbDecrypt = cipher -> IV cipher -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher cipher) =>
cipher -> IV cipher -> ba -> ba
cfbDecryptGeneric
ctrCombine :: ByteArray ba => cipher -> IV cipher -> ba -> ba
ctrCombine = cipher -> IV cipher -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher cipher) =>
cipher -> IV cipher -> ba -> ba
ctrCombineGeneric
aeadInit :: ByteArrayAccess iv => AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
aeadInit AEADMode
_ cipher
_ iv
_ = CryptoError -> CryptoFailable (AEAD cipher)
forall a. CryptoError -> CryptoFailable a
CryptoFailed CryptoError
CryptoError_AEADModeNotSupported
class BlockCipher cipher => BlockCipher128 cipher where
xtsEncrypt :: ByteArray ba
=> (cipher, cipher)
-> IV cipher
-> DataUnitOffset
-> ba
-> ba
xtsEncrypt = (cipher, cipher) -> IV cipher -> DataUnitOffset -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher128 cipher) =>
XTS ba cipher
xtsEncryptGeneric
xtsDecrypt :: ByteArray ba
=> (cipher, cipher)
-> IV cipher
-> DataUnitOffset
-> ba
-> ba
xtsDecrypt = (cipher, cipher) -> IV cipher -> DataUnitOffset -> ba -> ba
forall ba cipher.
(ByteArray ba, BlockCipher128 cipher) =>
XTS ba cipher
xtsDecryptGeneric
makeIV :: (ByteArrayAccess b, BlockCipher c) => b -> Maybe (IV c)
makeIV :: b -> Maybe (IV c)
makeIV b
b = c -> Maybe (IV c)
forall c. BlockCipher c => c -> Maybe (IV c)
toIV c
forall a. HasCallStack => a
undefined
where toIV :: BlockCipher c => c -> Maybe (IV c)
toIV :: c -> Maybe (IV c)
toIV c
cipher
| b -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length b
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
sz = IV c -> Maybe (IV c)
forall a. a -> Maybe a
Just (IV c -> Maybe (IV c)) -> IV c -> Maybe (IV c)
forall a b. (a -> b) -> a -> b
$ Bytes -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV (b -> Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
B.convert b
b :: Bytes)
| Bool
otherwise = Maybe (IV c)
forall a. Maybe a
Nothing
where sz :: Int
sz = c -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize c
cipher
nullIV :: BlockCipher c => IV c
nullIV :: IV c
nullIV = c -> IV c
forall c. BlockCipher c => c -> IV c
toIV c
forall a. HasCallStack => a
undefined
where toIV :: BlockCipher c => c -> IV c
toIV :: c -> IV c
toIV c
cipher = Bytes -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV (Int -> Bytes
forall ba. ByteArray ba => Int -> ba
B.zero (c -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize c
cipher) :: Bytes)
ivAdd :: IV c -> Int -> IV c
ivAdd :: IV c -> Int -> IV c
ivAdd (IV byteArray
b) Int
i = byteArray -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV (byteArray -> IV c) -> byteArray -> IV c
forall a b. (a -> b) -> a -> b
$ byteArray -> byteArray
forall bs. ByteArray bs => bs -> bs
copy byteArray
b
where copy :: ByteArray bs => bs -> bs
copy :: bs -> bs
copy bs
bs = bs -> (Ptr Word8 -> IO ()) -> bs
forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
B.copyAndFreeze bs
bs ((Ptr Word8 -> IO ()) -> bs) -> (Ptr Word8 -> IO ()) -> bs
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Ptr Word8 -> IO ()
loop Int
i (bs -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length bs
bs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
loop :: Int -> Int -> Ptr Word8 -> IO ()
loop :: Int -> Int -> Ptr Word8 -> IO ()
loop Int
acc Int
ofs Ptr Word8
p
| Int
ofs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = do
Word8
v <- Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
ofs) :: IO Word8
let accv :: Int
accv = Int
acc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
v
(Int
hi,Int
lo) = Int
accv Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
256
Ptr Word8 -> Word8 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
ofs) (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
lo :: Word8)
Int -> Int -> Ptr Word8 -> IO ()
loop Int
hi (Int
ofs Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Ptr Word8
p
cbcEncryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
cbcEncryptGeneric :: cipher -> IV cipher -> ba -> ba
cbcEncryptGeneric cipher
cipher IV cipher
ivini ba
input = [ba] -> ba
forall a. Monoid a => [a] -> a
mconcat ([ba] -> ba) -> [ba] -> ba
forall a b. (a -> b) -> a -> b
$ IV cipher -> [ba] -> [ba]
forall a c a.
(ByteArray a, BlockCipher c, ByteArrayAccess a) =>
IV c -> [a] -> [a]
doEnc IV cipher
ivini ([ba] -> [ba]) -> [ba] -> [ba]
forall a b. (a -> b) -> a -> b
$ Int -> ba -> [ba]
forall b. ByteArray b => Int -> b -> [b]
chunk (cipher -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize cipher
cipher) ba
input
where doEnc :: IV c -> [a] -> [a]
doEnc IV c
_ [] = []
doEnc IV c
iv (a
i:[a]
is) =
let o :: a
o = cipher -> a -> a
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt cipher
cipher (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ IV c -> a -> a
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor IV c
iv a
i
in a
o a -> [a] -> [a]
forall a. a -> [a] -> [a]
: IV c -> [a] -> [a]
doEnc (a -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV a
o) [a]
is
cbcDecryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
cbcDecryptGeneric :: cipher -> IV cipher -> ba -> ba
cbcDecryptGeneric cipher
cipher IV cipher
ivini ba
input = [ba] -> ba
forall a. Monoid a => [a] -> a
mconcat ([ba] -> ba) -> [ba] -> ba
forall a b. (a -> b) -> a -> b
$ IV cipher -> [ba] -> [ba]
forall byteArray a c.
(ByteArray a, ByteArray byteArray, BlockCipher c) =>
IV c -> [byteArray] -> [a]
doDec IV cipher
ivini ([ba] -> [ba]) -> [ba] -> [ba]
forall a b. (a -> b) -> a -> b
$ Int -> ba -> [ba]
forall b. ByteArray b => Int -> b -> [b]
chunk (cipher -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize cipher
cipher) ba
input
where
doDec :: IV c -> [byteArray] -> [a]
doDec IV c
_ [] = []
doDec IV c
iv (byteArray
i:[byteArray]
is) =
let o :: a
o = IV c -> byteArray -> a
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor IV c
iv (byteArray -> a) -> byteArray -> a
forall a b. (a -> b) -> a -> b
$ cipher -> byteArray -> byteArray
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbDecrypt cipher
cipher byteArray
i
in a
o a -> [a] -> [a]
forall a. a -> [a] -> [a]
: IV c -> [byteArray] -> [a]
doDec (byteArray -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV byteArray
i) [byteArray]
is
cfbEncryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
cfbEncryptGeneric :: cipher -> IV cipher -> ba -> ba
cfbEncryptGeneric cipher
cipher IV cipher
ivini ba
input = [ba] -> ba
forall a. Monoid a => [a] -> a
mconcat ([ba] -> ba) -> [ba] -> ba
forall a b. (a -> b) -> a -> b
$ IV cipher -> [ba] -> [ba]
forall a a c.
(ByteArray a, ByteArrayAccess a) =>
IV c -> [a] -> [a]
doEnc IV cipher
ivini ([ba] -> [ba]) -> [ba] -> [ba]
forall a b. (a -> b) -> a -> b
$ Int -> ba -> [ba]
forall b. ByteArray b => Int -> b -> [b]
chunk (cipher -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize cipher
cipher) ba
input
where
doEnc :: IV c -> [a] -> [a]
doEnc IV c
_ [] = []
doEnc (IV byteArray
iv) (a
i:[a]
is) =
let o :: a
o = a -> byteArray -> a
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor a
i (byteArray -> a) -> byteArray -> a
forall a b. (a -> b) -> a -> b
$ cipher -> byteArray -> byteArray
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt cipher
cipher byteArray
iv
in a
o a -> [a] -> [a]
forall a. a -> [a] -> [a]
: IV c -> [a] -> [a]
doEnc (a -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV a
o) [a]
is
cfbDecryptGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
cfbDecryptGeneric :: cipher -> IV cipher -> ba -> ba
cfbDecryptGeneric cipher
cipher IV cipher
ivini ba
input = [ba] -> ba
forall a. Monoid a => [a] -> a
mconcat ([ba] -> ba) -> [ba] -> ba
forall a b. (a -> b) -> a -> b
$ IV cipher -> [ba] -> [ba]
forall a a c. (ByteArray a, ByteArray a) => IV c -> [a] -> [a]
doDec IV cipher
ivini ([ba] -> [ba]) -> [ba] -> [ba]
forall a b. (a -> b) -> a -> b
$ Int -> ba -> [ba]
forall b. ByteArray b => Int -> b -> [b]
chunk (cipher -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize cipher
cipher) ba
input
where
doDec :: IV c -> [a] -> [a]
doDec IV c
_ [] = []
doDec (IV byteArray
iv) (a
i:[a]
is) =
let o :: a
o = a -> byteArray -> a
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor a
i (byteArray -> a) -> byteArray -> a
forall a b. (a -> b) -> a -> b
$ cipher -> byteArray -> byteArray
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt cipher
cipher byteArray
iv
in a
o a -> [a] -> [a]
forall a. a -> [a] -> [a]
: IV c -> [a] -> [a]
doDec (a -> IV c
forall c byteArray. ByteArray byteArray => byteArray -> IV c
IV a
i) [a]
is
ctrCombineGeneric :: (ByteArray ba, BlockCipher cipher) => cipher -> IV cipher -> ba -> ba
ctrCombineGeneric :: cipher -> IV cipher -> ba -> ba
ctrCombineGeneric cipher
cipher IV cipher
ivini ba
input = [ba] -> ba
forall a. Monoid a => [a] -> a
mconcat ([ba] -> ba) -> [ba] -> ba
forall a b. (a -> b) -> a -> b
$ IV cipher -> [ba] -> [ba]
forall a a c.
(ByteArray a, ByteArrayAccess a) =>
IV c -> [a] -> [a]
doCnt IV cipher
ivini ([ba] -> [ba]) -> [ba] -> [ba]
forall a b. (a -> b) -> a -> b
$ Int -> ba -> [ba]
forall b. ByteArray b => Int -> b -> [b]
chunk (cipher -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize cipher
cipher) ba
input
where doCnt :: IV c -> [a] -> [a]
doCnt IV c
_ [] = []
doCnt iv :: IV c
iv@(IV byteArray
ivd) (a
i:[a]
is) =
let ivEnc :: byteArray
ivEnc = cipher -> byteArray -> byteArray
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt cipher
cipher byteArray
ivd
in a -> byteArray -> a
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor a
i byteArray
ivEnc a -> [a] -> [a]
forall a. a -> [a] -> [a]
: IV c -> [a] -> [a]
doCnt (IV c -> Int -> IV c
forall c. IV c -> Int -> IV c
ivAdd IV c
iv Int
1) [a]
is
xtsEncryptGeneric :: (ByteArray ba, BlockCipher128 cipher) => XTS ba cipher
xtsEncryptGeneric :: XTS ba cipher
xtsEncryptGeneric = (cipher -> ba -> ba) -> XTS ba cipher
forall ba cipher.
(ByteArray ba, BlockCipher128 cipher) =>
(cipher -> ba -> ba)
-> (cipher, cipher) -> IV cipher -> DataUnitOffset -> ba -> ba
xtsGeneric cipher -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt
xtsDecryptGeneric :: (ByteArray ba, BlockCipher128 cipher) => XTS ba cipher
xtsDecryptGeneric :: XTS ba cipher
xtsDecryptGeneric = (cipher -> ba -> ba) -> XTS ba cipher
forall ba cipher.
(ByteArray ba, BlockCipher128 cipher) =>
(cipher -> ba -> ba)
-> (cipher, cipher) -> IV cipher -> DataUnitOffset -> ba -> ba
xtsGeneric cipher -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbDecrypt
xtsGeneric :: (ByteArray ba, BlockCipher128 cipher)
=> (cipher -> ba -> ba)
-> (cipher, cipher)
-> IV cipher
-> DataUnitOffset
-> ba
-> ba
xtsGeneric :: (cipher -> ba -> ba)
-> (cipher, cipher) -> IV cipher -> DataUnitOffset -> ba -> ba
xtsGeneric cipher -> ba -> ba
f (cipher
cipher, cipher
tweakCipher) (IV byteArray
iv) DataUnitOffset
sPoint ba
input =
[ba] -> ba
forall a. Monoid a => [a] -> a
mconcat ([ba] -> ba) -> [ba] -> ba
forall a b. (a -> b) -> a -> b
$ byteArray -> [ba] -> [ba]
forall b a a.
(ByteArray b, ByteArray a, ByteArrayAccess a) =>
b -> [a] -> [a]
doXts byteArray
iniTweak ([ba] -> [ba]) -> [ba] -> [ba]
forall a b. (a -> b) -> a -> b
$ Int -> ba -> [ba]
forall b. ByteArray b => Int -> b -> [b]
chunk (cipher -> Int
forall cipher. BlockCipher cipher => cipher -> Int
blockSize cipher
cipher) ba
input
where encTweak :: byteArray
encTweak = cipher -> byteArray -> byteArray
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt cipher
tweakCipher byteArray
iv
iniTweak :: byteArray
iniTweak = (byteArray -> byteArray) -> byteArray -> [byteArray]
forall a. (a -> a) -> a -> [a]
iterate byteArray -> byteArray
forall bs. ByteArray bs => bs -> bs
xtsGFMul byteArray
encTweak [byteArray] -> Int -> byteArray
forall a. [a] -> Int -> a
!! DataUnitOffset -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral DataUnitOffset
sPoint
doXts :: b -> [a] -> [a]
doXts b
_ [] = []
doXts b
tweak (a
i:[a]
is) =
let o :: a
o = ba -> b -> a
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor (cipher -> ba -> ba
f cipher
cipher (ba -> ba) -> ba -> ba
forall a b. (a -> b) -> a -> b
$ a -> b -> ba
forall a b c.
(ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
a -> b -> c
B.xor a
i b
tweak) b
tweak
in a
o a -> [a] -> [a]
forall a. a -> [a] -> [a]
: b -> [a] -> [a]
doXts (b -> b
forall bs. ByteArray bs => bs -> bs
xtsGFMul b
tweak) [a]
is