{-# 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 (newForeignPtr_, withForeignPtr)
import Foreign.Marshal.Alloc (mallocBytes)
import Foreign.Marshal.Utils (copyBytes)
import Foreign.Ptr (Ptr, nullPtr, plusPtr)
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
cipherEncrypt
:: Cipher -> Key -> Nonce -> PlainText -> AssDat -> Maybe (CipherText, CipherText)
cipherEncrypt :: Cipher
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
cipherEncrypt Cipher
cipher
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128GCM_SHA256 = Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes128gcmEncrypt
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128CCM_SHA256 =
[Char]
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
forall a. HasCallStack => [Char] -> a
error [Char]
"cipher_TLS13_AES128CCM_SHA256"
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES256GCM_SHA384 = Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes256gcmEncrypt
| Bool
otherwise = [Char]
-> Key
-> Nonce
-> ByteString
-> AssDat
-> Maybe (ByteString, ByteString)
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 Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128GCM_SHA256 = Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
aes128gcmDecrypt
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128CCM_SHA256 =
[Char] -> Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
forall a. HasCallStack => [Char] -> a
error [Char]
"cipher_TLS13_AES128CCM_SHA256"
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES256GCM_SHA384 = Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
aes256gcmDecrypt
| Bool
otherwise = [Char] -> Key -> Nonce -> ByteString -> AssDat -> Maybe ByteString
forall a. HasCallStack => [Char] -> a
error [Char]
"cipherDecrypt"
aes128gcmEncrypt
:: Key -> (Nonce -> PlainText -> AssDat -> Maybe (CipherText, CipherText))
aes128gcmEncrypt :: Key
-> Nonce -> ByteString -> AssDat -> Maybe (ByteString, ByteString)
aes128gcmEncrypt (Key ByteString
key) = case CryptoFailable AES128 -> Maybe AES128
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable AES128 -> Maybe AES128)
-> CryptoFailable AES128 -> Maybe AES128
forall a b. (a -> b) -> a -> b
$ ByteString -> CryptoFailable AES128
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES128
cipherInit ByteString
key of
Maybe AES128
Nothing -> \Nonce
_ ByteString
_ AssDat
_ -> Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
Just (AES128
aes :: AES128) -> \(Nonce ByteString
nonce) ByteString
plaintext (AssDat ByteString
ad) ->
case CryptoFailable (AEAD AES128) -> Maybe (AEAD AES128)
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable (AEAD AES128) -> Maybe (AEAD AES128))
-> CryptoFailable (AEAD AES128) -> Maybe (AEAD AES128)
forall a b. (a -> b) -> a -> b
$ AEADMode -> AES128 -> ByteString -> CryptoFailable (AEAD AES128)
forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
forall iv.
ByteArrayAccess iv =>
AEADMode -> AES128 -> iv -> CryptoFailable (AEAD AES128)
aeadInit AEADMode
AEAD_GCM AES128
aes ByteString
nonce of
Maybe (AEAD AES128)
Nothing -> Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
Just AEAD AES128
aead ->
let (AuthTag Bytes
tag0, ByteString
ciphertext) = AEAD AES128
-> ByteString -> ByteString -> Int -> (AuthTag, ByteString)
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 = Bytes -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert Bytes
tag0
in (ByteString, ByteString) -> Maybe (ByteString, ByteString)
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 CryptoFailable AES128 -> Maybe AES128
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable AES128 -> Maybe AES128)
-> CryptoFailable AES128 -> Maybe AES128
forall a b. (a -> b) -> a -> b
$ ByteString -> CryptoFailable AES128
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES128
cipherInit ByteString
key of
Maybe AES128
Nothing -> \Nonce
_ ByteString
_ AssDat
_ -> Maybe ByteString
forall a. Maybe a
Nothing
Just (AES128
aes :: AES128) -> \(Nonce ByteString
nonce) ByteString
ciphertag (AssDat ByteString
ad) ->
case CryptoFailable (AEAD AES128) -> Maybe (AEAD AES128)
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable (AEAD AES128) -> Maybe (AEAD AES128))
-> CryptoFailable (AEAD AES128) -> Maybe (AEAD AES128)
forall a b. (a -> b) -> a -> b
$ AEADMode -> AES128 -> ByteString -> CryptoFailable (AEAD AES128)
forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
forall iv.
ByteArrayAccess iv =>
AEADMode -> AES128 -> iv -> CryptoFailable (AEAD AES128)
aeadInit AEADMode
AEAD_GCM AES128
aes ByteString
nonce of
Maybe (AEAD AES128)
Nothing -> Maybe ByteString
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 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
16) ByteString
ciphertag
authtag :: AuthTag
authtag = Bytes -> AuthTag
AuthTag (Bytes -> AuthTag) -> Bytes -> AuthTag
forall a b. (a -> b) -> a -> b
$ ByteString -> Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert ByteString
tag
in AEAD AES128
-> ByteString -> ByteString -> AuthTag -> Maybe ByteString
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 CryptoFailable AES256 -> Maybe AES256
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable AES256 -> Maybe AES256)
-> CryptoFailable AES256 -> Maybe AES256
forall a b. (a -> b) -> a -> b
$ ByteString -> CryptoFailable AES256
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES256
cipherInit ByteString
key of
Maybe AES256
Nothing -> \Nonce
_ ByteString
_ AssDat
_ -> Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
Just (AES256
aes :: AES256) -> \(Nonce ByteString
nonce) ByteString
plaintext (AssDat ByteString
ad) ->
case CryptoFailable (AEAD AES256) -> Maybe (AEAD AES256)
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable (AEAD AES256) -> Maybe (AEAD AES256))
-> CryptoFailable (AEAD AES256) -> Maybe (AEAD AES256)
forall a b. (a -> b) -> a -> b
$ AEADMode -> AES256 -> ByteString -> CryptoFailable (AEAD AES256)
forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
forall iv.
ByteArrayAccess iv =>
AEADMode -> AES256 -> iv -> CryptoFailable (AEAD AES256)
aeadInit AEADMode
AEAD_GCM AES256
aes ByteString
nonce of
Maybe (AEAD AES256)
Nothing -> Maybe (ByteString, ByteString)
forall a. Maybe a
Nothing
Just AEAD AES256
aead ->
let (AuthTag Bytes
tag0, ByteString
ciphertext) = AEAD AES256
-> ByteString -> ByteString -> Int -> (AuthTag, ByteString)
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 = Bytes -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert Bytes
tag0
in (ByteString, ByteString) -> Maybe (ByteString, ByteString)
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 CryptoFailable AES256 -> Maybe AES256
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable AES256 -> Maybe AES256)
-> CryptoFailable AES256 -> Maybe AES256
forall a b. (a -> b) -> a -> b
$ ByteString -> CryptoFailable AES256
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES256
cipherInit ByteString
key of
Maybe AES256
Nothing -> \Nonce
_ ByteString
_ AssDat
_ -> Maybe ByteString
forall a. Maybe a
Nothing
Just (AES256
aes :: AES256) -> \(Nonce ByteString
nonce) ByteString
ciphertag (AssDat ByteString
ad) ->
case CryptoFailable (AEAD AES256) -> Maybe (AEAD AES256)
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable (AEAD AES256) -> Maybe (AEAD AES256))
-> CryptoFailable (AEAD AES256) -> Maybe (AEAD AES256)
forall a b. (a -> b) -> a -> b
$ AEADMode -> AES256 -> ByteString -> CryptoFailable (AEAD AES256)
forall cipher iv.
(BlockCipher cipher, ByteArrayAccess iv) =>
AEADMode -> cipher -> iv -> CryptoFailable (AEAD cipher)
forall iv.
ByteArrayAccess iv =>
AEADMode -> AES256 -> iv -> CryptoFailable (AEAD AES256)
aeadInit AEADMode
AEAD_GCM AES256
aes ByteString
nonce of
Maybe (AEAD AES256)
Nothing -> Maybe ByteString
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 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
16) ByteString
ciphertag
authtag :: AuthTag
authtag = Bytes -> AuthTag
AuthTag (Bytes -> AuthTag) -> Bytes -> AuthTag
forall a b. (a -> b) -> a -> b
$ ByteString -> Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
Byte.convert ByteString
tag
in AEAD AES256
-> ByteString -> ByteString -> AuthTag -> Maybe ByteString
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
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 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len1 = [Char] -> ByteString
forall a. HasCallStack => [Char] -> a
error [Char]
"bsXORpad"
| Bool
otherwise = Int -> (Ptr Word8 -> IO ()) -> ByteString
BS.unsafeCreate Int
len0 ((Ptr Word8 -> IO ()) -> ByteString)
-> (Ptr Word8 -> IO ()) -> ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
dst ->
ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp0 ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p0 ->
ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp1 ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p1 -> do
let src0 :: Ptr b
src0 = Ptr Word8
p0 Ptr Word8 -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off0
let src1 :: Ptr b
src1 = Ptr Word8
p1 Ptr Word8 -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off1
let diff :: Int
diff = Int
len0 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
len1
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
dst Ptr Word8
forall {b}. Ptr b
src0 Int
diff
Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
loop (Ptr Word8
dst Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
diff) (Ptr Any
forall {b}. Ptr b
src0 Ptr Any -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
diff) Ptr Word8
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 = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
loop Ptr Word8
dst Ptr Word8
src0 Ptr Word8
src1 Int
len = do
Word8
w1 <- Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
src0
Word8
w2 <- Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
src1
Ptr Word8 -> Word8 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr Word8
dst (Word8
w1 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
`xor` Word8
w2)
Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
loop (Ptr Word8
dst Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Ptr Word8
src0 Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Ptr Word8
src1 Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
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 -> Int -> IO Int
forall a. a -> IO a
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 Ptr Word8 -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len
Int
len' <- Ptr Word8 -> ByteString -> IO Int
copyBS Ptr Word8
forall {b}. Ptr b
dst' ByteString
bdy
Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
len Int -> Int -> Int
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 (Word64 -> ByteString) -> Word64 -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> Word64
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 -> Int -> IO Int
forall a. a -> IO a
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 (Int -> Word64
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)
Cipher
cipher Key
key
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128GCM_SHA256 = Key -> Sample -> Mask
aes128ecbEncrypt Key
key
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES128CCM_SHA256 =
[Char] -> Sample -> Mask
forall a. HasCallStack => [Char] -> a
error [Char]
"cipher_TLS13_AES128CCM_SHA256"
| Cipher
cipher Cipher -> Cipher -> Bool
forall a. Eq a => a -> a -> Bool
== Cipher
cipher_TLS13_AES256GCM_SHA384 = Key -> Sample -> Mask
aes256ecbEncrypt Key
key
| Bool
otherwise =
[Char] -> Sample -> Mask
forall a. HasCallStack => [Char] -> a
error [Char]
"cipherHeaderProtection"
aes128ecbEncrypt :: Key -> (Sample -> Mask)
aes128ecbEncrypt :: Key -> Sample -> Mask
aes128ecbEncrypt (Key ByteString
key) = case CryptoFailable AES128 -> Maybe AES128
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable AES128 -> Maybe AES128)
-> CryptoFailable AES128 -> Maybe AES128
forall a b. (a -> b) -> a -> b
$ ByteString -> CryptoFailable AES128
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES128
cipherInit ByteString
key of
Maybe AES128
Nothing -> \Sample
_ -> ByteString -> Mask
Mask ByteString
"0123456789012345"
Just (AES128
aes :: AES128) ->
let encrypt :: ByteString -> ByteString
encrypt = AES128 -> ByteString -> ByteString
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
forall ba. ByteArray ba => AES128 -> 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 CryptoFailable AES256 -> Maybe AES256
forall a. CryptoFailable a -> Maybe a
maybeCryptoError (CryptoFailable AES256 -> Maybe AES256)
-> CryptoFailable AES256 -> Maybe AES256
forall a b. (a -> b) -> a -> b
$ ByteString -> CryptoFailable AES256
forall cipher key.
(Cipher cipher, ByteArray key) =>
key -> CryptoFailable cipher
forall key. ByteArray key => key -> CryptoFailable AES256
cipherInit ByteString
key of
Maybe AES256
Nothing -> \Sample
_ -> ByteString -> Mask
Mask ByteString
"0123456789012345"
Just (AES256
aes :: AES256) ->
let encrypt :: ByteString -> ByteString
encrypt = AES256 -> ByteString -> ByteString
forall cipher ba.
(BlockCipher cipher, ByteArray ba) =>
cipher -> ba -> ba
forall ba. ByteArray ba => AES256 -> 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 <- Ptr Word8 -> IO (IORef (Ptr Word8))
forall a. a -> IO (IORef a)
newIORef Ptr Word8
forall {b}. Ptr b
nullPtr
Ptr Word8
dstbuf <- Int -> IO (Ptr Word8)
forall a. Int -> IO (Ptr a)
mallocBytes Int
32
(Ptr Word8 -> IO (), IO (Ptr Word8))
-> IO (Ptr Word8 -> IO (), IO (Ptr Word8))
forall a. a -> IO a
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
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 = IORef (Ptr Word8) -> Ptr Word8 -> IO ()
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 <- IORef (Ptr Word8) -> IO (Ptr Word8)
forall a. IORef a -> IO a
readIORef IORef (Ptr Word8)
ref
ByteString
sample <- do
ForeignPtr Word8
fptr <- Ptr Word8 -> IO (ForeignPtr Word8)
forall a. Ptr a -> IO (ForeignPtr a)
newForeignPtr_ Ptr Word8
srcbuf
ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
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 (Sample -> Mask) -> Sample -> Mask
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
Ptr Word8 -> IO (Ptr Word8)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Ptr Word8
dstbuf