{-# LANGUAGE BangPatterns #-}
module Crypto.Store.KeyWrap.AES
( wrap
, unwrap
, wrapPad
, unwrapPad
) where
import Data.Bits
import Data.ByteArray (ByteArray, ByteArrayAccess, Bytes)
import qualified Data.ByteArray as B
import Data.List
import Data.Word
import Crypto.Cipher.Types
import Foreign.Storable
import Crypto.Store.Error
import Crypto.Store.Util
type Chunked ba = [ba]
type Pair ba = (ba, ba)
aes' :: (BlockCipher aes, ByteArray ba) => aes -> Pair ba -> ba
aes' :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> ba
aes' aes
cipher (ba
msb, ba
lsb) = aes -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
forall ba. ByteArray ba => aes -> ba -> ba
ecbEncrypt aes
cipher (ba -> ba -> ba
forall bs. ByteArray bs => bs -> bs -> bs
B.append ba
msb ba
lsb)
aes :: (BlockCipher aes, ByteArray ba) => aes -> Pair ba -> Pair ba
aes :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> Pair ba
aes aes
cipher = Int -> ba -> (ba, ba)
forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
8 (ba -> (ba, ba)) -> ((ba, ba) -> ba) -> (ba, ba) -> (ba, ba)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. aes -> (ba, ba) -> ba
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> ba
aes' aes
cipher
aesrev' :: (BlockCipher aes, ByteArray ba) => aes -> ba -> Pair ba
aesrev' :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Pair ba
aesrev' aes
cipher = Int -> ba -> (ba, ba)
forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
8 (ba -> (ba, ba)) -> (ba -> ba) -> ba -> (ba, ba)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. aes -> ba -> ba
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
forall ba. ByteArray ba => aes -> ba -> ba
ecbDecrypt aes
cipher
aesrev :: (BlockCipher aes, ByteArray ba) => aes -> Pair ba -> Pair ba
aesrev :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> Pair ba
aesrev aes
cipher (ba
msb, ba
lsb) = aes -> ba -> (ba, ba)
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Pair ba
aesrev' aes
cipher (ba -> ba -> ba
forall bs. ByteArray bs => bs -> bs -> bs
B.append ba
msb ba
lsb)
wrapc :: (BlockCipher aes, ByteArray ba)
=> aes -> ba -> Chunked ba -> Chunked ba
wrapc :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Chunked ba -> Chunked ba
wrapc aes
cipher ba
iiv Chunked ba
list = (ba -> Chunked ba -> Chunked ba) -> (ba, Chunked ba) -> Chunked ba
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (:) ((ba, Chunked ba) -> Chunked ba) -> (ba, Chunked ba) -> Chunked ba
forall a b. (a -> b) -> a -> b
$ ((ba, Chunked ba) -> Word64 -> (ba, Chunked ba))
-> (ba, Chunked ba) -> [Word64] -> (ba, Chunked ba)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (ba, Chunked ba) -> Word64 -> (ba, Chunked ba)
forall {t}. ByteArray t => (t, [t]) -> Word64 -> (t, [t])
pass (ba
iiv, Chunked ba
list) [Word64
0 .. Word64
5]
where
!n :: Word64
n = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Chunked ba -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Chunked ba
list)
pass :: (t, [t]) -> Word64 -> (t, [t])
pass (t
a, [t]
l) Word64
j = t -> Word64 -> [t] -> (t, [t])
forall {t}. ByteArray t => t -> Word64 -> [t] -> (t, [t])
go t
a (Word64
n Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
j Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
1) [t]
l
go :: t -> Word64 -> [t] -> (t, [t])
go t
a !Word64
_ [] = (t
a, [])
go t
a !Word64
i (t
r : [t]
rs) =
let (t
a', t
t) = aes -> (t, t) -> (t, t)
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> Pair ba
aes aes
cipher (t
a, t
r)
in (t
t t -> [t] -> [t]
forall a. a -> [a] -> [a]
:) ([t] -> [t]) -> (t, [t]) -> (t, [t])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t -> Word64 -> [t] -> (t, [t])
go (t -> Word64 -> t
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> Word64 -> bout
xorWith t
a' Word64
i) (Word64 -> Word64
forall a. Enum a => a -> a
succ Word64
i) [t]
rs
unwrapc :: (BlockCipher aes, ByteArray ba)
=> aes -> Chunked ba -> Either StoreError (ba, Chunked ba)
unwrapc :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Chunked ba -> Either StoreError (ba, Chunked ba)
unwrapc aes
_ [] = StoreError -> Either StoreError (ba, [ba])
forall a b. a -> Either a b
Left (String -> StoreError
InvalidInput String
"KeyWrap.AES: input too short")
unwrapc aes
cipher (ba
iv:[ba]
list) = (ba, [ba]) -> Either StoreError (ba, [ba])
forall a b. b -> Either a b
Right (ba
iiv, [ba] -> [ba]
forall a. [a] -> [a]
reverse [ba]
out)
where
(ba
iiv, [ba]
out) = ((ba, [ba]) -> Word64 -> (ba, [ba]))
-> (ba, [ba]) -> [Word64] -> (ba, [ba])
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (ba, [ba]) -> Word64 -> (ba, [ba])
forall {t}. ByteArray t => (t, [t]) -> Word64 -> (t, [t])
pass (ba
iv, [ba] -> [ba]
forall a. [a] -> [a]
reverse [ba]
list) ([Word64] -> [Word64]
forall a. [a] -> [a]
reverse [Word64
0 .. Word64
5])
!n :: Word64
n = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([ba] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ba]
list)
pass :: (t, [t]) -> Word64 -> (t, [t])
pass (t
a, [t]
l) Word64
j = t -> Word64 -> [t] -> (t, [t])
forall {t}. ByteArray t => t -> Word64 -> [t] -> (t, [t])
go t
a (Word64
n Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
j Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
n) [t]
l
go :: t -> Word64 -> [t] -> (t, [t])
go t
a !Word64
_ [] = (t
a, [])
go t
a !Word64
i (t
r : [t]
rs) =
let (t
a', t
t) = aes -> (t, t) -> (t, t)
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> Pair ba
aesrev aes
cipher (t -> Word64 -> t
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> Word64 -> bout
xorWith t
a Word64
i, t
r)
in (t
t t -> [t] -> [t]
forall a. a -> [a] -> [a]
:) ([t] -> [t]) -> (t, [t]) -> (t, [t])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t -> Word64 -> [t] -> (t, [t])
go t
a' (Word64 -> Word64
forall a. Enum a => a -> a
pred Word64
i) [t]
rs
wrap :: (BlockCipher aes, ByteArray ba) => aes -> ba -> Either StoreError ba
wrap :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Either StoreError ba
wrap aes
cipher ba
bs = Chunked ba -> ba
forall ba. ByteArray ba => Chunked ba -> ba
unchunks (Chunked ba -> ba)
-> (Chunked ba -> Chunked ba) -> Chunked ba -> ba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. aes -> ba -> Chunked ba -> Chunked ba
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Chunked ba -> Chunked ba
wrapc aes
cipher ba
iiv (Chunked ba -> ba)
-> Either StoreError (Chunked ba) -> Either StoreError ba
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ba -> Either StoreError (Chunked ba)
forall ba. ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks ba
bs
where iiv :: ba
iiv = Int -> Word8 -> ba
forall ba. ByteArray ba => Int -> Word8 -> ba
B.replicate Int
8 Word8
0xA6
unwrap :: (BlockCipher aes, ByteArray ba) => aes -> ba -> Either StoreError ba
unwrap :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Either StoreError ba
unwrap aes
cipher ba
bs = Chunked ba -> ba
forall ba. ByteArray ba => Chunked ba -> ba
unchunks (Chunked ba -> ba)
-> Either StoreError (Chunked ba) -> Either StoreError ba
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((ba, Chunked ba) -> Either StoreError (Chunked ba)
forall {ba} {b}.
ByteArrayAccess ba =>
(ba, b) -> Either StoreError b
check ((ba, Chunked ba) -> Either StoreError (Chunked ba))
-> Either StoreError (ba, Chunked ba)
-> Either StoreError (Chunked ba)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< aes -> Chunked ba -> Either StoreError (ba, Chunked ba)
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Chunked ba -> Either StoreError (ba, Chunked ba)
unwrapc aes
cipher (Chunked ba -> Either StoreError (ba, Chunked ba))
-> Either StoreError (Chunked ba)
-> Either StoreError (ba, Chunked ba)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ba -> Either StoreError (Chunked ba)
forall ba. ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks ba
bs)
where
check :: (ba, b) -> Either StoreError b
check (ba
iiv, b
out)
| Word8 -> ba -> Bool
forall ba. ByteArrayAccess ba => Word8 -> ba -> Bool
constAllEq Word8
0xA6 ba
iiv = b -> Either StoreError b
forall a b. b -> Either a b
Right b
out
| Bool
otherwise = StoreError -> Either StoreError b
forall a b. a -> Either a b
Left StoreError
BadChecksum
chunks :: ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks :: forall ba. ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks ba
bs | ba -> Bool
forall a. ByteArrayAccess a => a -> Bool
B.null ba
bs = Chunked ba -> Either StoreError (Chunked ba)
forall a b. b -> Either a b
Right []
| ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
8 = StoreError -> Either StoreError (Chunked ba)
forall a b. a -> Either a b
Left (String -> StoreError
InvalidInput String
"KeyWrap.AES: input is not multiple of 8 bytes")
| Bool
otherwise = let (ba
a, ba
b) = Int -> ba -> (ba, ba)
forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
8 ba
bs in (ba
a ba -> Chunked ba -> Chunked ba
forall a. a -> [a] -> [a]
:) (Chunked ba -> Chunked ba)
-> Either StoreError (Chunked ba) -> Either StoreError (Chunked ba)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ba -> Either StoreError (Chunked ba)
forall ba. ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks ba
b
unchunks :: ByteArray ba => Chunked ba -> ba
unchunks :: forall ba. ByteArray ba => Chunked ba -> ba
unchunks = [ba] -> ba
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
[bin] -> bout
B.concat
padMask :: Bytes
padMask :: Bytes
padMask = [Word8] -> Bytes
forall a. ByteArray a => [Word8] -> a
B.pack [Word8
0xA6, Word8
0x59, Word8
0x59, Word8
0xA6, Word8
0x00, Word8
0x00, Word8
0x00, Word8
0x00]
pad :: ByteArray ba => Int -> ba -> Either StoreError (Pair ba)
pad :: forall ba. ByteArray ba => Int -> ba -> Either StoreError (Pair ba)
pad Int
inlen ba
bs | Int
inlen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = StoreError -> Either StoreError (Pair ba)
forall a b. a -> Either a b
Left (String -> StoreError
InvalidInput String
"KeyWrap.AES: input is empty")
| Int
padlen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
8 = Pair ba -> Either StoreError (Pair ba)
forall a b. b -> Either a b
Right (ba
aiv, ba
bs)
| Bool
otherwise = Pair ba -> Either StoreError (Pair ba)
forall a b. b -> Either a b
Right (ba
aiv, ba
bs ba -> ba -> ba
forall bs. ByteArray bs => bs -> bs -> bs
`B.append` Int -> ba
forall ba. ByteArray ba => Int -> ba
B.zero Int
padlen)
where padlen :: Int
padlen = Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
inlen Int
8
aiv :: ba
aiv = Bytes -> Word64 -> ba
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> Word64 -> bout
xorWith Bytes
padMask (Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
inlen)
unpad :: ByteArray ba => Int -> Pair ba -> Either StoreError ba
unpad :: forall ba. ByteArray ba => Int -> Pair ba -> Either StoreError ba
unpad Int
inlen (ba
aiv, ba
b)
| Bool
badlen = StoreError -> Either StoreError ba
forall a b. a -> Either a b
Left StoreError
BadChecksum
| Word8 -> ba -> Bool
forall ba. ByteArrayAccess ba => Word8 -> ba -> Bool
constAllEq Word8
0 ba
p = ba -> Either StoreError ba
forall a b. b -> Either a b
Right ba
bs
| Bool
otherwise = StoreError -> Either StoreError ba
forall a b. a -> Either a b
Left StoreError
BadChecksum
where aivlen :: Int
aivlen = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Bytes -> ba -> Word64
forall bx by.
(ByteArrayAccess bx, ByteArrayAccess by) =>
bx -> by -> Word64
unxor Bytes
padMask ba
aiv)
badlen :: Bool
badlen = Int
inlen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
aivlen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
8 Bool -> Bool -> Bool
|| Int
inlen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
aivlen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
16
(ba
bs, ba
p) = Int -> ba -> (ba, ba)
forall bs. ByteArray bs => Int -> bs -> (bs, bs)
B.splitAt Int
aivlen ba
b
wrapPad :: (BlockCipher aes, ByteArray ba) => aes -> ba -> Either StoreError ba
wrapPad :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Either StoreError ba
wrapPad aes
cipher ba
bs = (ba, ba) -> Either StoreError ba
forall {b}. ByteArray b => (b, b) -> Either StoreError b
doWrap ((ba, ba) -> Either StoreError ba)
-> Either StoreError (ba, ba) -> Either StoreError ba
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Int -> ba -> Either StoreError (ba, ba)
forall ba. ByteArray ba => Int -> ba -> Either StoreError (Pair ba)
pad Int
inlen ba
bs
where
inlen :: Int
inlen = ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs
doWrap :: (b, b) -> Either StoreError b
doWrap (b
aiv, b
b)
| Int
inlen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
8 = b -> Either StoreError b
forall a b. b -> Either a b
Right (b -> Either StoreError b) -> b -> Either StoreError b
forall a b. (a -> b) -> a -> b
$ aes -> (b, b) -> b
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Pair ba -> ba
aes' aes
cipher (b
aiv, b
b)
| Bool
otherwise = Chunked b -> b
forall ba. ByteArray ba => Chunked ba -> ba
unchunks (Chunked b -> b) -> (Chunked b -> Chunked b) -> Chunked b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. aes -> b -> Chunked b -> Chunked b
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Chunked ba -> Chunked ba
wrapc aes
cipher b
aiv (Chunked b -> b)
-> Either StoreError (Chunked b) -> Either StoreError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b -> Either StoreError (Chunked b)
forall ba. ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks b
b
unwrapPad :: (BlockCipher aes, ByteArray ba) => aes -> ba -> Either StoreError ba
unwrapPad :: forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Either StoreError ba
unwrapPad aes
cipher ba
bs = Int -> Pair ba -> Either StoreError ba
forall ba. ByteArray ba => Int -> Pair ba -> Either StoreError ba
unpad Int
inlen (Pair ba -> Either StoreError ba)
-> Either StoreError (Pair ba) -> Either StoreError ba
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Either StoreError (Pair ba)
doUnwrap
where
inlen :: Int
inlen = ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length ba
bs
doUnwrap :: Either StoreError (Pair ba)
doUnwrap
| Int
inlen Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
16 = let (ba
aiv, ba
b) = aes -> ba -> Pair ba
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> ba -> Pair ba
aesrev' aes
cipher ba
bs in Pair ba -> Either StoreError (Pair ba)
forall a b. b -> Either a b
Right (ba
aiv, ba
b)
| Bool
otherwise = (Chunked ba -> ba) -> (ba, Chunked ba) -> Pair ba
forall a b. (a -> b) -> (ba, a) -> (ba, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Chunked ba -> ba
forall ba. ByteArray ba => Chunked ba -> ba
unchunks ((ba, Chunked ba) -> Pair ba)
-> Either StoreError (ba, Chunked ba)
-> Either StoreError (Pair ba)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (aes -> Chunked ba -> Either StoreError (ba, Chunked ba)
forall aes ba.
(BlockCipher aes, ByteArray ba) =>
aes -> Chunked ba -> Either StoreError (ba, Chunked ba)
unwrapc aes
cipher (Chunked ba -> Either StoreError (ba, Chunked ba))
-> Either StoreError (Chunked ba)
-> Either StoreError (ba, Chunked ba)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ba -> Either StoreError (Chunked ba)
forall ba. ByteArray ba => ba -> Either StoreError (Chunked ba)
chunks ba
bs)
xorWith :: (ByteArrayAccess bin, ByteArray bout) => bin -> Word64 -> bout
xorWith :: forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> Word64 -> bout
xorWith bin
bs !Word64
i = bin -> (Ptr Any -> IO ()) -> bout
forall bs1 bs2 p.
(ByteArrayAccess bs1, ByteArray bs2) =>
bs1 -> (Ptr p -> IO ()) -> bs2
B.copyAndFreeze bin
bs ((Ptr Any -> IO ()) -> bout) -> (Ptr Any -> IO ()) -> bout
forall a b. (a -> b) -> a -> b
$ \Ptr Any
dst -> Ptr Any -> Int -> Word64 -> IO ()
forall {t} {b}. (Bits t, Integral t) => Ptr b -> Int -> t -> IO ()
loop Ptr Any
dst Int
len Word64
i
where !len :: Int
len = bin -> Int
forall ba. ByteArrayAccess ba => ba -> Int
B.length bin
bs
loop :: Ptr b -> Int -> t -> IO ()
loop Ptr b
_ Int
0 !t
_ = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
loop Ptr b
_ Int
_ t
0 = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
loop Ptr b
p Int
n t
j = do
Word8
b <- Ptr b -> Int -> IO Word8
forall b. Ptr b -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr b
p (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
let mask :: Word8
mask = t -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral t
j :: Word8
Ptr b -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr b
p (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
xor Word8
b Word8
mask)
Ptr b -> Int -> t -> IO ()
loop Ptr b
p (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (t -> Int -> t
forall a. Bits a => a -> Int -> a
shiftR t
j Int
8)
unxor :: (ByteArrayAccess bx, ByteArrayAccess by) => bx -> by -> Word64
unxor :: forall bx by.
(ByteArrayAccess bx, ByteArrayAccess by) =>
bx -> by -> Word64
unxor bx
x by
y = (Word64 -> Word8 -> Word64) -> Word64 -> [Word8] -> Word64
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Word64 -> Word8 -> Word64
forall {a} {a}. (Bits a, Integral a, Num a) => a -> a -> a
f Word64
0 ([Word8] -> Word64) -> [Word8] -> Word64
forall a b. (a -> b) -> a -> b
$ (Word8 -> Word8 -> Word8) -> [Word8] -> [Word8] -> [Word8]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
xor (bx -> [Word8]
forall a. ByteArrayAccess a => a -> [Word8]
B.unpack bx
x) (by -> [Word8]
forall a. ByteArrayAccess a => a -> [Word8]
B.unpack by
y)
where f :: a -> a -> a
f a
acc a
z = a -> Int -> a
forall a. Bits a => a -> Int -> a
shiftL a
acc Int
8 a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
z