{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Network.QUIC.Crypto.Nite (
    niteEncrypt
  , niteEncrypt'
  , niteDecrypt
  , niteDecrypt'
  , protectionMask
  , aes128gcmEncrypt
  , makeNonce
  , makeNiteEncrypt
  , makeNiteDecrypt
  , makeNiteProtector
  ) where

import Crypto.Cipher.AES
import Crypto.Cipher.Types hiding (Cipher, IV)
import Crypto.Error (maybeCryptoError)
import qualified Data.ByteArray as Byte (convert)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BS
import Foreign.ForeignPtr (withForeignPtr, newForeignPtr_)
import Foreign.Marshal.Alloc (mallocBytes)
import Foreign.Ptr (Ptr, plusPtr, nullPtr)
import Foreign.Storable (peek, poke)
import Network.TLS hiding (Version)
import Network.TLS.Extra.Cipher

import Network.QUIC.Crypto.Types
import Network.QUIC.Imports
import Network.QUIC.Types

----------------------------------------------------------------

-- It would be nice to take [PlainText] and update AEAD context with
-- [PlainText]. But since each PlainText is not aligned to cipher block,
-- it's impossible.
cipherEncrypt :: Cipher -> Key -> Nonce -> PlainText -> AssDat -> Maybe (CipherText,CipherText)
cipherEncrypt :: Cipher
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
cipherEncrypt Cipher
cipher
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128GCM_SHA256        = Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes128gcmEncrypt
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128CCM_SHA256        = forall a. HasCallStack => [Char] -> a
error [Char]
"cipher_TLS13_AES128CCM_SHA256"
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES256GCM_SHA384        = Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes256gcmEncrypt
  | Bool
otherwise                                      = forall a. HasCallStack => [Char] -> a
error [Char]
"cipherEncrypt"

cipherDecrypt :: Cipher -> Key -> Nonce -> CipherText -> AssDat -> Maybe PlainText
cipherDecrypt :: Cipher -> Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
cipherDecrypt Cipher
cipher
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128GCM_SHA256        = Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
aes128gcmDecrypt
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128CCM_SHA256        = forall a. HasCallStack => [Char] -> a
error [Char]
"cipher_TLS13_AES128CCM_SHA256"
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES256GCM_SHA384        = Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
aes256gcmDecrypt
  | Bool
otherwise                                      = forall a. HasCallStack => [Char] -> a
error [Char]
"cipherDecrypt"

-- IMPORTANT: Using 'let' so that parameters can be memorized.
aes128gcmEncrypt :: Key -> (Nonce -> PlainText -> AssDat -> Maybe (CipherText,CipherText))
aes128gcmEncrypt :: Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes128gcmEncrypt (Key ByteString
key) = case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit ByteString
key of
  Maybe AES128
Nothing -> \Nonce
_ ByteString
_ AssDat
_  -> forall a. Maybe a
Nothing
  Just (AES128
aes :: AES128) -> \(Nonce ByteString
nonce) ByteString
plaintext (AssDat ByteString
ad) ->
    case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
aeadInit AEADMode
AEAD_GCM AES128
aes ByteString
nonce of
      Maybe (AEAD AES128)
Nothing -> forall a. Maybe a
Nothing
      Just AEAD AES128
aead ->
          let  (AuthTag Bytes
tag0, ByteString
ciphertext) = forall aad ba a.
(ByteArrayAccess aad, ByteArray ba) =>
AEAD a -> aad -> ba -> Int -> (AuthTag, ba)
aeadSimpleEncrypt AEAD AES128
aead ByteString
ad ByteString
plaintext Int
16
               tag :: ByteString
tag = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert Bytes
tag0
          in forall a. a -> Maybe a
Just (ByteString
ciphertext,ByteString
tag)

aes128gcmDecrypt :: Key -> (Nonce -> CipherText -> AssDat -> Maybe PlainText)
aes128gcmDecrypt :: Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
aes128gcmDecrypt (Key ByteString
key) = case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit ByteString
key of
  Maybe AES128
Nothing -> \Nonce
_ ByteString
_ AssDat
_  -> forall a. Maybe a
Nothing
  Just (AES128
aes :: AES128) -> \(Nonce ByteString
nonce) ByteString
ciphertag (AssDat ByteString
ad) ->
    case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
aeadInit AEADMode
AEAD_GCM AES128
aes ByteString
nonce of
      Maybe (AEAD AES128)
Nothing -> forall a. Maybe a
Nothing
      Just AEAD AES128
aead ->
          let (ByteString
ciphertext, ByteString
tag) = Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (ByteString -> Int
BS.length ByteString
ciphertag forall a. Num a => a -> a -> a
- Int
16) ByteString
ciphertag
              authtag :: AuthTag
authtag = Bytes -> AuthTag
AuthTag forall a b. (a -> b) -> a -> b
$ forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert ByteString
tag
           in forall aad ba a.
(ByteArrayAccess aad, ByteArray ba) =>
AEAD a -> aad -> ba -> AuthTag -> Maybe ba
aeadSimpleDecrypt AEAD AES128
aead ByteString
ad ByteString
ciphertext AuthTag
authtag

aes256gcmEncrypt :: Key -> (Nonce -> PlainText -> AssDat -> Maybe (CipherText,CipherText))
aes256gcmEncrypt :: Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes256gcmEncrypt (Key ByteString
key) = case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit ByteString
key of
  Maybe AES256
Nothing -> \Nonce
_ ByteString
_ AssDat
_  -> forall a. Maybe a
Nothing
  Just (AES256
aes :: AES256) -> \(Nonce ByteString
nonce) ByteString
plaintext (AssDat ByteString
ad) ->
    case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
aeadInit AEADMode
AEAD_GCM AES256
aes ByteString
nonce of
      Maybe (AEAD AES256)
Nothing -> forall a. Maybe a
Nothing
      Just AEAD AES256
aead ->
          let  (AuthTag Bytes
tag0, ByteString
ciphertext) = forall aad ba a.
(ByteArrayAccess aad, ByteArray ba) =>
AEAD a -> aad -> ba -> Int -> (AuthTag, ba)
aeadSimpleEncrypt AEAD AES256
aead ByteString
ad ByteString
plaintext Int
16
               tag :: ByteString
tag = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert Bytes
tag0
          in forall a. a -> Maybe a
Just (ByteString
ciphertext,ByteString
tag)

aes256gcmDecrypt :: Key -> (Nonce -> CipherText -> AssDat -> Maybe PlainText)
aes256gcmDecrypt :: Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
aes256gcmDecrypt (Key ByteString
key) = case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit ByteString
key of
  Maybe AES256
Nothing -> \Nonce
_ ByteString
_ AssDat
_  -> forall a. Maybe a
Nothing
  Just (AES256
aes :: AES256) -> \(Nonce ByteString
nonce) ByteString
ciphertag (AssDat ByteString
ad) ->
    case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
aeadInit AEADMode
AEAD_GCM AES256
aes ByteString
nonce of
      Maybe (AEAD AES256)
Nothing -> forall a. Maybe a
Nothing
      Just AEAD AES256
aead ->
          let (ByteString
ciphertext, ByteString
tag) = Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (ByteString -> Int
BS.length ByteString
ciphertag forall a. Num a => a -> a -> a
- Int
16) ByteString
ciphertag
              authtag :: AuthTag
authtag = Bytes -> AuthTag
AuthTag forall a b. (a -> b) -> a -> b
$ forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert ByteString
tag
           in forall aad ba a.
(ByteArrayAccess aad, ByteArray ba) =>
AEAD a -> aad -> ba -> AuthTag -> Maybe ba
aeadSimpleDecrypt AEAD AES256
aead ByteString
ad ByteString
ciphertext AuthTag
authtag

----------------------------------------------------------------

makeNonce :: IV -> ByteString -> Nonce
makeNonce :: IV -> ByteString -> Nonce
makeNonce (IV ByteString
iv) ByteString
pn = ByteString -> Nonce
Nonce ByteString
nonce
  where
    nonce :: ByteString
nonce = ByteString -> ByteString -> ByteString
bsXORpad ByteString
iv ByteString
pn

-- XORing IV and a packet numbr with left padded.
--             src0
-- IV          +IIIIIIIIIIIIIIIIII--------+
--                 diff          src1
-- PN          +000000000000000000+-------+
--             dst
-- Nonce       +IIIIIIIIIIIIIIIIII--------+
bsXORpad :: ByteString -> ByteString -> ByteString
bsXORpad :: ByteString -> ByteString -> ByteString
bsXORpad (PS ForeignPtr Word8
fp0 Int
off0 Int
len0) (PS ForeignPtr Word8
fp1 Int
off1 Int
len1)
  | Int
len0 forall a. Ord a => a -> a -> Bool
< Int
len1 = forall a. HasCallStack => [Char] -> a
error [Char]
"bsXORpad"
  | Bool
otherwise = Int -> (Ptr Word8 -> IO ()) -> ByteString
BS.unsafeCreate Int
len0 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
dst ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp0 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p0 ->
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp1 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p1 -> do
        let src0 :: Ptr b
src0 = Ptr Word8
p0 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off0
        let src1 :: Ptr b
src1 = Ptr Word8
p1 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off1
        let diff :: Int
diff = Int
len0 forall a. Num a => a -> a -> a
- Int
len1
        Ptr Word8 -> Ptr Word8 -> Int -> IO ()
BS.memcpy Ptr Word8
dst forall {b}. Ptr b
src0 Int
diff
        Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
loop (Ptr Word8
dst forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
diff) (forall {b}. Ptr b
src0 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
diff) forall {b}. Ptr b
src1 Int
len1
  where
    loop :: Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    loop :: Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
loop Ptr Word8
_ Ptr Word8
_ Ptr Word8
_ Int
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ()
    loop Ptr Word8
dst Ptr Word8
src0 Ptr Word8
src1 Int
len = do
        Word8
w1 <- forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
src0
        Word8
w2 <- forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
src1
        forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
dst (Word8
w1 forall a. Bits a => a -> a -> a
`xor` Word8
w2)
        Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
loop (Ptr Word8
dst forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Ptr Word8
src0 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Ptr Word8
src1 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Int
len forall a. Num a => a -> a -> a
- Int
1)

{-
bsXORpad' :: ByteString -> ByteString -> ByteString
bsXORpad' iv pn = BS.pack $ zipWith xor ivl pnl
  where
    ivl = BS.unpack iv
    diff = BS.length iv - BS.length pn
    pnl = replicate diff 0 ++ BS.unpack pn
-}

----------------------------------------------------------------

type NiteEncrypt = Buffer -> PlainText -> AssDat -> PacketNumber -> IO Int

makeNiteEncrypt :: Cipher -> Key -> IV -> NiteEncrypt
makeNiteEncrypt :: Cipher -> Key -> IV -> NiteEncrypt
makeNiteEncrypt Cipher
cipher Key
key IV
iv = (ByteString -> AssDat -> Int -> Maybe (ByteString, ByteString))
-> NiteEncrypt
niteEncryptWrapper (Cipher
-> Key
-> IV
-> ByteString
-> AssDat
-> Int
-> Maybe (ByteString, ByteString)
niteEncrypt Cipher
cipher Key
key IV
iv)

niteEncryptWrapper :: (PlainText -> AssDat -> PacketNumber -> Maybe (CipherText,CipherText)) -> NiteEncrypt
niteEncryptWrapper :: (ByteString -> AssDat -> Int -> Maybe (ByteString, ByteString))
-> NiteEncrypt
niteEncryptWrapper ByteString -> AssDat -> Int -> Maybe (ByteString, ByteString)
enc Ptr Word8
dst ByteString
plaintext AssDat
ad Int
pn = case ByteString -> AssDat -> Int -> Maybe (ByteString, ByteString)
enc ByteString
plaintext AssDat
ad Int
pn of
    Maybe (ByteString, ByteString)
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return (-Int
1)
    Just (ByteString
hdr,ByteString
bdy) -> do
        Int
len <- Ptr Word8 -> ByteString -> IO Int
copyBS Ptr Word8
dst ByteString
hdr
        let dst' :: Ptr b
dst' = Ptr Word8
dst forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len
        Int
len' <- Ptr Word8 -> ByteString -> IO Int
copyBS forall {b}. Ptr b
dst' ByteString
bdy
        forall (m :: * -> *) a. Monad m => a -> m a
return (Int
len forall a. Num a => a -> a -> a
+ Int
len')

niteEncrypt :: Cipher -> Key -> IV
             -> PlainText -> AssDat -> PacketNumber -> Maybe (CipherText,CipherText)
niteEncrypt :: Cipher
-> Key
-> IV
-> ByteString
-> AssDat
-> Int
-> Maybe (ByteString, ByteString)
niteEncrypt Cipher
cipher Key
key IV
iv =
    let enc :: Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
enc = Cipher
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
cipherEncrypt Cipher
cipher Key
key
        mk :: ByteString -> Nonce
mk  = IV -> ByteString -> Nonce
makeNonce IV
iv
    in \ByteString
plaintext AssDat
header Int
pn -> let bytePN :: ByteString
bytePN = Word64 -> ByteString
bytestring64 forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
pn
                                   nonce :: Nonce
nonce  = ByteString -> Nonce
mk ByteString
bytePN
                               in Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
enc Nonce
nonce ByteString
plaintext AssDat
header

niteEncrypt' :: Cipher -> Key -> Nonce -> PlainText -> AssDat -> Maybe (CipherText,CipherText)
niteEncrypt' :: Cipher
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
niteEncrypt' Cipher
cipher Key
key Nonce
nonce ByteString
plaintext AssDat
header =
    Cipher
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
cipherEncrypt Cipher
cipher Key
key Nonce
nonce ByteString
plaintext AssDat
header

----------------------------------------------------------------

type NiteDecrypt = Buffer -> CipherText -> AssDat -> PacketNumber -> IO Int

makeNiteDecrypt :: Cipher -> Key -> IV -> NiteDecrypt
makeNiteDecrypt :: Cipher -> Key -> IV -> NiteEncrypt
makeNiteDecrypt Cipher
cipher Key
key IV
iv = (ByteString -> AssDat -> Int -> Maybe ByteString) -> NiteEncrypt
niteDecryptWrapper (Cipher
-> Key -> IV -> ByteString -> AssDat -> Int -> Maybe ByteString
niteDecrypt Cipher
cipher Key
key IV
iv)

niteDecryptWrapper :: (CipherText -> AssDat -> PacketNumber -> Maybe PlainText) -> NiteDecrypt
niteDecryptWrapper :: (ByteString -> AssDat -> Int -> Maybe ByteString) -> NiteEncrypt
niteDecryptWrapper ByteString -> AssDat -> Int -> Maybe ByteString
dec Ptr Word8
dst ByteString
ciphertext AssDat
ad Int
pn = case ByteString -> AssDat -> Int -> Maybe ByteString
dec ByteString
ciphertext AssDat
ad Int
pn of
  Maybe ByteString
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return (-Int
1)
  Just ByteString
bs -> Ptr Word8 -> ByteString -> IO Int
copyBS Ptr Word8
dst ByteString
bs

niteDecrypt :: Cipher -> Key -> IV
            -> CipherText -> AssDat -> PacketNumber -> Maybe PlainText
niteDecrypt :: Cipher
-> Key -> IV -> ByteString -> AssDat -> Int -> Maybe ByteString
niteDecrypt Cipher
cipher Key
key IV
iv =
    let dec :: Nonce -> ByteString -> AssDat -> Maybe ByteString
dec = Cipher -> Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
cipherDecrypt Cipher
cipher Key
key
        mk :: ByteString -> Nonce
mk  = IV -> ByteString -> Nonce
makeNonce IV
iv
    in \ByteString
ciphertext AssDat
header Int
pn -> let bytePN :: ByteString
bytePN = Word64 -> ByteString
bytestring64 (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
pn)
                                    nonce :: Nonce
nonce = ByteString -> Nonce
mk ByteString
bytePN
                                in Nonce -> ByteString -> AssDat -> Maybe ByteString
dec Nonce
nonce ByteString
ciphertext AssDat
header

niteDecrypt' :: Cipher -> Key -> Nonce -> CipherText -> AssDat -> Maybe PlainText
niteDecrypt' :: Cipher -> Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
niteDecrypt' Cipher
cipher Key
key Nonce
nonce ByteString
ciphertext AssDat
header =
    Cipher -> Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
cipherDecrypt Cipher
cipher Key
key Nonce
nonce ByteString
ciphertext AssDat
header

----------------------------------------------------------------

protectionMask :: Cipher -> Key -> (Sample -> Mask)
protectionMask :: Cipher -> Key -> Sample -> Mask
protectionMask Cipher
cipher Key
key =
    let f :: Sample -> Mask
f = Cipher -> Key -> Sample -> Mask
cipherHeaderProtection Cipher
cipher Key
key
    in \Sample
sample -> Sample -> Mask
f Sample
sample

cipherHeaderProtection :: Cipher -> Key -> (Sample -> Mask)
cipherHeaderProtection :: Cipher -> Key -> Sample -> Mask
cipherHeaderProtection Cipher
cipher Key
key
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128GCM_SHA256        = Key -> Sample -> Mask
aes128ecbEncrypt Key
key
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128CCM_SHA256        = forall a. HasCallStack => [Char] -> a
error [Char]
"cipher_TLS13_AES128CCM_SHA256"
  | Cipher
cipher forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES256GCM_SHA384        = Key -> Sample -> Mask
aes256ecbEncrypt Key
key
  | Bool
otherwise                                      = forall a. HasCallStack => [Char] -> a
error [Char]
"cipherHeaderProtection"

aes128ecbEncrypt :: Key -> (Sample -> Mask)
aes128ecbEncrypt :: Key -> Sample -> Mask
aes128ecbEncrypt (Key ByteString
key) = case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit ByteString
key of
  Maybe AES128
Nothing -> \Sample
_ -> ByteString -> Mask
Mask ByteString
"0123456789012345"
  Just (AES128
aes :: AES128) ->
    let encrypt :: ByteString -> ByteString
encrypt = forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt AES128
aes
    in \(Sample ByteString
sample) -> let mask :: ByteString
mask = ByteString -> ByteString
encrypt ByteString
sample
                           in ByteString -> Mask
Mask ByteString
mask

aes256ecbEncrypt :: Key -> (Sample -> Mask)
aes256ecbEncrypt :: Key -> Sample -> Mask
aes256ecbEncrypt (Key ByteString
key) = case forall a. CryptoFailable a -> Maybe a
maybeCryptoError forall a b. (a -> b) -> a -> b
$ forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
cipherInit ByteString
key of
  Maybe AES256
Nothing -> \Sample
_ -> ByteString -> Mask
Mask ByteString
"0123456789012345"
  Just (AES256
aes :: AES256) ->
    let encrypt :: ByteString -> ByteString
encrypt = forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
ecbEncrypt AES256
aes
    in \(Sample ByteString
sample) -> let mask :: ByteString
mask = ByteString -> ByteString
encrypt ByteString
sample
                           in ByteString -> Mask
Mask ByteString
mask

----------------------------------------------------------------

makeNiteProtector :: Cipher -> Key -> IO (Buffer -> IO (), IO Buffer)
makeNiteProtector :: Cipher -> Key -> IO (Ptr Word8 -> IO (), IO (Ptr Word8))
makeNiteProtector Cipher
cipher Key
key = do
    IORef (Ptr Word8)
ref <- forall a. a -> IO (IORef a)
newIORef forall {b}. Ptr b
nullPtr
    Ptr Word8
dstbuf <- forall a. Int -> IO (Ptr a)
mallocBytes Int
32 -- fixme: free
    forall (m :: * -> *) a. Monad m => a -> m a
return (IORef (Ptr Word8) -> Ptr Word8 -> IO ()
niteSetSample IORef (Ptr Word8)
ref, IORef (Ptr Word8)
-> Int -> (Sample -> Mask) -> Ptr Word8 -> IO (Ptr Word8)
niteGetMask IORef (Ptr Word8)
ref Int
samplelen Sample -> Mask
mkMask Ptr Word8
dstbuf)
  where
    samplelen :: Int
samplelen = Int
16 -- sampleLength cipher -- fixme
    mkMask :: Sample -> Mask
mkMask = Cipher -> Key -> Sample -> Mask
protectionMask Cipher
cipher Key
key

niteSetSample :: IORef Buffer -> Buffer -> IO ()
niteSetSample :: IORef (Ptr Word8) -> Ptr Word8 -> IO ()
niteSetSample = forall a. IORef a -> a -> IO ()
writeIORef

niteGetMask :: IORef Buffer -> Int -> (Sample -> Mask) -> Buffer -> IO Buffer
niteGetMask :: IORef (Ptr Word8)
-> Int -> (Sample -> Mask) -> Ptr Word8 -> IO (Ptr Word8)
niteGetMask IORef (Ptr Word8)
ref Int
samplelen Sample -> Mask
mkMask Ptr Word8
dstbuf = do
    Ptr Word8
srcbuf <- forall a. IORef a -> IO a
readIORef IORef (Ptr Word8)
ref
    ByteString
sample <- do
        ForeignPtr Word8
fptr <- forall a. Ptr a -> IO (ForeignPtr a)
newForeignPtr_ Ptr Word8
srcbuf
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Int -> Int -> ByteString
PS ForeignPtr Word8
fptr Int
0 Int
samplelen
    let Mask ByteString
mask = Sample -> Mask
mkMask forall a b. (a -> b) -> a -> b
$ ByteString -> Sample
Sample ByteString
sample
    Int
_len <- Ptr Word8 -> ByteString -> IO Int
copyBS Ptr Word8
dstbuf ByteString
mask
    forall (m :: * -> *) a. Monad m => a -> m a
return Ptr Word8
dstbuf