{-# LANGUAGE FlexibleContexts #-}
module Network.TLS.Record.Disengage
( disengageRecord
) where
import Control.Monad.State.Strict
import Crypto.Cipher.Types (AuthTag(..))
import Network.TLS.Struct
import Network.TLS.ErrT
import Network.TLS.Cap
import Network.TLS.Record.State
import Network.TLS.Record.Types
import Network.TLS.Cipher
import Network.TLS.Crypto
import Network.TLS.Compression
import Network.TLS.Util
import Network.TLS.Wire
import Network.TLS.Packet
import Network.TLS.Imports
import qualified Data.ByteString as B
import qualified Data.ByteArray as B (convert, xor)
disengageRecord :: Record Ciphertext -> RecordM (Record Plaintext)
disengageRecord :: Record Ciphertext -> RecordM (Record Plaintext)
disengageRecord = Record Ciphertext -> RecordM (Record Compressed)
decryptRecord (Record Ciphertext -> RecordM (Record Compressed))
-> (Record Compressed -> RecordM (Record Plaintext))
-> Record Ciphertext
-> RecordM (Record Plaintext)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Record Compressed -> RecordM (Record Plaintext)
uncompressRecord
uncompressRecord :: Record Compressed -> RecordM (Record Plaintext)
uncompressRecord :: Record Compressed -> RecordM (Record Plaintext)
uncompressRecord record :: Record Compressed
record = Record Compressed
-> (Fragment Compressed -> RecordM (Fragment Plaintext))
-> RecordM (Record Plaintext)
forall a b.
Record a
-> (Fragment a -> RecordM (Fragment b)) -> RecordM (Record b)
onRecordFragment Record Compressed
record ((Fragment Compressed -> RecordM (Fragment Plaintext))
-> RecordM (Record Plaintext))
-> (Fragment Compressed -> RecordM (Fragment Plaintext))
-> RecordM (Record Plaintext)
forall a b. (a -> b) -> a -> b
$ (ByteString -> RecordM ByteString)
-> Fragment Compressed -> RecordM (Fragment Plaintext)
fragmentUncompress ((ByteString -> RecordM ByteString)
-> Fragment Compressed -> RecordM (Fragment Plaintext))
-> (ByteString -> RecordM ByteString)
-> Fragment Compressed
-> RecordM (Fragment Plaintext)
forall a b. (a -> b) -> a -> b
$ \bytes :: ByteString
bytes ->
(Compression -> (Compression, ByteString)) -> RecordM ByteString
forall a. (Compression -> (Compression, a)) -> RecordM a
withCompression ((Compression -> (Compression, ByteString)) -> RecordM ByteString)
-> (Compression -> (Compression, ByteString)) -> RecordM ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> Compression -> (Compression, ByteString)
compressionInflate ByteString
bytes
decryptRecord :: Record Ciphertext -> RecordM (Record Compressed)
decryptRecord :: Record Ciphertext -> RecordM (Record Compressed)
decryptRecord record :: Record Ciphertext
record@(Record ct :: ProtocolType
ct ver :: Version
ver fragment :: Fragment Ciphertext
fragment) = do
RecordState
st <- RecordM RecordState
forall s (m :: * -> *). MonadState s m => m s
get
case RecordState -> Maybe Cipher
stCipher RecordState
st of
Nothing -> RecordM (Record Compressed)
noDecryption
_ -> do
RecordOptions
recOpts <- RecordM RecordOptions
getRecordOptions
let mver :: Version
mver = RecordOptions -> Version
recordVersion RecordOptions
recOpts
if RecordOptions -> Bool
recordTLS13 RecordOptions
recOpts
then Version -> ByteString -> RecordState -> RecordM (Record Compressed)
decryptData13 Version
mver (Fragment Ciphertext -> ByteString
forall a. Fragment a -> ByteString
fragmentGetBytes Fragment Ciphertext
fragment) RecordState
st
else Record Ciphertext
-> (Fragment Ciphertext -> RecordM (Fragment Compressed))
-> RecordM (Record Compressed)
forall a b.
Record a
-> (Fragment a -> RecordM (Fragment b)) -> RecordM (Record b)
onRecordFragment Record Ciphertext
record ((Fragment Ciphertext -> RecordM (Fragment Compressed))
-> RecordM (Record Compressed))
-> (Fragment Ciphertext -> RecordM (Fragment Compressed))
-> RecordM (Record Compressed)
forall a b. (a -> b) -> a -> b
$ (ByteString -> RecordM ByteString)
-> Fragment Ciphertext -> RecordM (Fragment Compressed)
fragmentUncipher ((ByteString -> RecordM ByteString)
-> Fragment Ciphertext -> RecordM (Fragment Compressed))
-> (ByteString -> RecordM ByteString)
-> Fragment Ciphertext
-> RecordM (Fragment Compressed)
forall a b. (a -> b) -> a -> b
$ \e :: ByteString
e ->
Version
-> Record Ciphertext
-> ByteString
-> RecordState
-> RecordM ByteString
decryptData Version
mver Record Ciphertext
record ByteString
e RecordState
st
where
noDecryption :: RecordM (Record Compressed)
noDecryption = Record Ciphertext
-> (Fragment Ciphertext -> RecordM (Fragment Compressed))
-> RecordM (Record Compressed)
forall a b.
Record a
-> (Fragment a -> RecordM (Fragment b)) -> RecordM (Record b)
onRecordFragment Record Ciphertext
record ((Fragment Ciphertext -> RecordM (Fragment Compressed))
-> RecordM (Record Compressed))
-> (Fragment Ciphertext -> RecordM (Fragment Compressed))
-> RecordM (Record Compressed)
forall a b. (a -> b) -> a -> b
$ (ByteString -> RecordM ByteString)
-> Fragment Ciphertext -> RecordM (Fragment Compressed)
fragmentUncipher ByteString -> RecordM ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return
decryptData13 :: Version -> ByteString -> RecordState -> RecordM (Record Compressed)
decryptData13 mver :: Version
mver e :: ByteString
e st :: RecordState
st
| ProtocolType
ct ProtocolType -> ProtocolType -> Bool
forall a. Eq a => a -> a -> Bool
== ProtocolType
ProtocolType_AppData = do
ByteString
inner <- Version
-> Record Ciphertext
-> ByteString
-> RecordState
-> RecordM ByteString
decryptData Version
mver Record Ciphertext
record ByteString
e RecordState
st
case ByteString -> Either String (ProtocolType, ByteString)
unInnerPlaintext ByteString
inner of
Left message :: String
message -> TLSError -> RecordM (Record Compressed)
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (TLSError -> RecordM (Record Compressed))
-> TLSError -> RecordM (Record Compressed)
forall a b. (a -> b) -> a -> b
$ (String, Bool, AlertDescription) -> TLSError
Error_Protocol (String
message, Bool
True, AlertDescription
UnexpectedMessage)
Right (ct' :: ProtocolType
ct', d :: ByteString
d) -> Record Compressed -> RecordM (Record Compressed)
forall (m :: * -> *) a. Monad m => a -> m a
return (Record Compressed -> RecordM (Record Compressed))
-> Record Compressed -> RecordM (Record Compressed)
forall a b. (a -> b) -> a -> b
$ ProtocolType -> Version -> Fragment Compressed -> Record Compressed
forall a. ProtocolType -> Version -> Fragment a -> Record a
Record ProtocolType
ct' Version
ver (ByteString -> Fragment Compressed
fragmentCompressed ByteString
d)
| Bool
otherwise = RecordM (Record Compressed)
noDecryption
unInnerPlaintext :: ByteString -> Either String (ProtocolType, ByteString)
unInnerPlaintext :: ByteString -> Either String (ProtocolType, ByteString)
unInnerPlaintext inner :: ByteString
inner =
case ByteString -> Maybe (ByteString, Word8)
B.unsnoc ByteString
dc of
Nothing -> String -> Either String (ProtocolType, ByteString)
forall a b. a -> Either a b
Left (String -> Either String (ProtocolType, ByteString))
-> String -> Either String (ProtocolType, ByteString)
forall a b. (a -> b) -> a -> b
$ Word8 -> String
forall a. Show a => a -> String
unknownContentType13 (0<