{-# LANGUAGE OverloadedStrings #-}
module Network.TLS.Handshake.Client.ServerHello (
recvServerHello,
processServerHello13,
) where
import Network.TLS.Cipher
import Network.TLS.Compression
import Network.TLS.Context.Internal
import Network.TLS.ErrT
import Network.TLS.Extension
import Network.TLS.Handshake.Client.Common
import Network.TLS.Handshake.Common
import Network.TLS.Handshake.Key
import Network.TLS.Handshake.Process
import Network.TLS.Handshake.Random
import Network.TLS.Handshake.State
import Network.TLS.Handshake.State13
import Network.TLS.IO
import Network.TLS.Imports
import Network.TLS.Parameters
import Network.TLS.State
import Network.TLS.Struct
import Network.TLS.Struct13
import Network.TLS.Types
recvServerHello
:: ClientParams -> Context -> IO [Handshake]
recvServerHello :: ClientParams -> Context -> IO [Handshake]
recvServerHello ClientParams
cparams Context
ctx = do
(Handshake
sh, [Handshake]
hss) <- IO (Handshake, [Handshake])
recvSH
ClientParams -> Context -> Handshake -> IO ()
processServerHello ClientParams
cparams Context
ctx Handshake
sh
Context -> Handshake -> IO ()
processHandshake12 Context
ctx Handshake
sh
[Handshake] -> IO [Handshake]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [Handshake]
hss
where
recvSH :: IO (Handshake, [Handshake])
recvSH = do
Either TLSError Packet
epkt <- Context -> IO (Either TLSError Packet)
recvPacket12 Context
ctx
case Either TLSError Packet
epkt of
Left TLSError
e -> TLSError -> IO (Handshake, [Handshake])
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore TLSError
e
Right Packet
pkt -> case Packet
pkt of
Alert [(AlertLevel, AlertDescription)]
a -> [(AlertLevel, AlertDescription)] -> IO (Handshake, [Handshake])
forall {m :: * -> *} {a} {a}. (MonadIO m, Show a) => a -> m a
throwAlert [(AlertLevel, AlertDescription)]
a
Handshake (Handshake
h : [Handshake]
hs) -> (Handshake, [Handshake]) -> IO (Handshake, [Handshake])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Handshake
h, [Handshake]
hs)
Packet
_ -> [Char] -> Maybe [Char] -> IO (Handshake, [Handshake])
forall (m :: * -> *) a. MonadIO m => [Char] -> Maybe [Char] -> m a
unexpected (Packet -> [Char]
forall a. Show a => a -> [Char]
show Packet
pkt) ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"handshake")
throwAlert :: a -> m a
throwAlert a
a =
TLSError -> m a
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> m a) -> TLSError -> m a
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol
([Char]
"expecting server hello, got alert : " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ a -> [Char]
forall a. Show a => a -> [Char]
show a
a)
AlertDescription
HandshakeFailure
processServerHello13
:: ClientParams -> Context -> Handshake13 -> IO ()
processServerHello13 :: ClientParams -> Context -> Handshake13 -> IO ()
processServerHello13 ClientParams
cparams Context
ctx (ServerHello13 ServerRandom
serverRan Session
serverSession CipherID
cipher [ExtensionRaw]
exts) = do
let sh :: Handshake
sh = Version
-> ServerRandom
-> Session
-> CipherID
-> CompressionID
-> [ExtensionRaw]
-> Handshake
ServerHello Version
TLS12 ServerRandom
serverRan Session
serverSession CipherID
cipher CompressionID
0 [ExtensionRaw]
exts
ClientParams -> Context -> Handshake -> IO ()
processServerHello ClientParams
cparams Context
ctx Handshake
sh
processServerHello13 ClientParams
_ Context
_ Handshake13
h = [Char] -> Maybe [Char] -> IO ()
forall (m :: * -> *) a. MonadIO m => [Char] -> Maybe [Char] -> m a
unexpected (Handshake13 -> [Char]
forall a. Show a => a -> [Char]
show Handshake13
h) ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"server hello")
processServerHello
:: ClientParams -> Context -> Handshake -> IO ()
processServerHello :: ClientParams -> Context -> Handshake -> IO ()
processServerHello ClientParams
cparams Context
ctx (ServerHello Version
rver ServerRandom
serverRan Session
serverSession CipherID
cipher CompressionID
compression [ExtensionRaw]
exts) = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Version
rver Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
/= Version
TLS12) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol (Version -> [Char]
forall a. Show a => a -> [Char]
show Version
rver [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" is not supported") AlertDescription
IllegalParameter
Session
clientSession <- TLS13State -> Session
tls13stSession (TLS13State -> Session) -> IO TLS13State -> IO Session
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Context -> IO TLS13State
getTLS13State Context
ctx
[ExtensionID]
sentExts <- TLS13State -> [ExtensionID]
tls13stSentExtensions (TLS13State -> [ExtensionID]) -> IO TLS13State -> IO [ExtensionID]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Context -> IO TLS13State
getTLS13State Context
ctx
Cipher
cipherAlg <- case (Cipher -> Bool) -> [Cipher] -> Maybe Cipher
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (CipherID -> CipherID -> Bool
forall a. Eq a => a -> a -> Bool
(==) CipherID
cipher (CipherID -> Bool) -> (Cipher -> CipherID) -> Cipher -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cipher -> CipherID
cipherID) (Supported -> [Cipher]
supportedCiphers (Supported -> [Cipher]) -> Supported -> [Cipher]
forall a b. (a -> b) -> a -> b
$ Context -> Supported
ctxSupported Context
ctx) of
Maybe Cipher
Nothing -> TLSError -> IO Cipher
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO Cipher) -> TLSError -> IO Cipher
forall a b. (a -> b) -> a -> b
$ [Char] -> AlertDescription -> TLSError
Error_Protocol [Char]
"server choose unknown cipher" AlertDescription
IllegalParameter
Just Cipher
alg -> Cipher -> IO Cipher
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Cipher
alg
Compression
compressAlg <- case (Compression -> Bool) -> [Compression] -> Maybe Compression
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find
(CompressionID -> CompressionID -> Bool
forall a. Eq a => a -> a -> Bool
(==) CompressionID
compression (CompressionID -> Bool)
-> (Compression -> CompressionID) -> Compression -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Compression -> CompressionID
compressionID)
(Supported -> [Compression]
supportedCompressions (Supported -> [Compression]) -> Supported -> [Compression]
forall a b. (a -> b) -> a -> b
$ Context -> Supported
ctxSupported Context
ctx) of
Maybe Compression
Nothing ->
TLSError -> IO Compression
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO Compression) -> TLSError -> IO Compression
forall a b. (a -> b) -> a -> b
$ [Char] -> AlertDescription -> TLSError
Error_Protocol [Char]
"server choose unknown compression" AlertDescription
IllegalParameter
Just Compression
alg -> Compression -> IO Compression
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Compression
alg
CompressionID -> IO ()
forall (m :: * -> *). MonadIO m => CompressionID -> m ()
ensureNullCompression CompressionID
compression
let checkExt :: ExtensionRaw -> Bool
checkExt (ExtensionRaw ExtensionID
i ByteString
_)
| ExtensionID
i ExtensionID -> ExtensionID -> Bool
forall a. Eq a => a -> a -> Bool
== ExtensionID
EID_Cookie = Bool
False
| Bool
otherwise = ExtensionID
i ExtensionID -> [ExtensionID] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [ExtensionID]
sentExts
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((ExtensionRaw -> Bool) -> [ExtensionRaw] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ExtensionRaw -> Bool
checkExt [ExtensionRaw]
exts) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol [Char]
"spurious extensions received" AlertDescription
UnsupportedExtension
let isHRR :: Bool
isHRR = ServerRandom -> Bool
isHelloRetryRequest ServerRandom
serverRan
Context -> TLSSt () -> IO ()
forall a. Context -> TLSSt a -> IO a
usingState_ Context
ctx (TLSSt () -> IO ()) -> TLSSt () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Bool -> TLSSt ()
setTLS13HRR Bool
isHRR
Maybe Cookie -> TLSSt ()
setTLS13Cookie
( Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard Bool
isHRR
Maybe () -> Maybe ByteString -> Maybe ByteString
forall a b. Maybe a -> Maybe b -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ExtensionID -> [ExtensionRaw] -> Maybe ByteString
extensionLookup ExtensionID
EID_Cookie [ExtensionRaw]
exts
Maybe ByteString -> (ByteString -> Maybe Cookie) -> Maybe Cookie
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MessageType -> ByteString -> Maybe Cookie
forall a. Extension a => MessageType -> ByteString -> Maybe a
extensionDecode MessageType
MsgTServerHello
)
Version -> TLSSt ()
setVersion Version
rver
(ExtensionRaw -> TLSSt ()) -> [ExtensionRaw] -> TLSSt ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ExtensionRaw -> TLSSt ()
processServerExtension [ExtensionRaw]
exts
Context -> MessageType -> [ExtensionRaw] -> IO ()
setALPN Context
ctx MessageType
MsgTServerHello [ExtensionRaw]
exts
Version
ver <- Context -> TLSSt Version -> IO Version
forall a. Context -> TLSSt a -> IO a
usingState_ Context
ctx TLSSt Version
getVersion
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Version
ver Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
TLS12) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Context -> HandshakeM () -> IO ()
forall (m :: * -> *) a. MonadIO m => Context -> HandshakeM a -> m a
usingHState Context
ctx (HandshakeM () -> IO ()) -> HandshakeM () -> IO ()
forall a b. (a -> b) -> a -> b
$ Version -> ServerRandom -> Cipher -> Compression -> HandshakeM ()
setServerHelloParameters Version
rver ServerRandom
serverRan Cipher
cipherAlg Compression
compressAlg
let supportedVers :: [Version]
supportedVers = Supported -> [Version]
supportedVersions (Supported -> [Version]) -> Supported -> [Version]
forall a b. (a -> b) -> a -> b
$ ClientParams -> Supported
clientSupported ClientParams
cparams
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Version
ver Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
TLS13) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Session
clientSession Session -> Session -> Bool
forall a. Eq a => a -> a -> Bool
/= Session
serverSession) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol
[Char]
"session is not matched in compatibility mode"
AlertDescription
IllegalParameter
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Version
ver Version -> [Version] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Version]
supportedVers) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol
([Char]
"server version " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Version -> [Char]
forall a. Show a => a -> [Char]
show Version
ver [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" is not supported")
AlertDescription
ProtocolVersion
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Version -> [Version] -> ServerRandom -> Bool
isDowngraded Version
ver [Version]
supportedVers ServerRandom
serverRan) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol [Char]
"version downgrade detected" AlertDescription
IllegalParameter
if Version
ver Version -> Version -> Bool
forall a. Eq a => a -> a -> Bool
== Version
TLS13
then do
Context -> TLSSt () -> IO ()
forall a. Context -> TLSSt a -> IO a
usingState_ Context
ctx (TLSSt () -> IO ()) -> TLSSt () -> IO ()
forall a b. (a -> b) -> a -> b
$ Session -> TLSSt ()
setSession Session
serverSession
Context -> Cipher -> IO ()
updateContext13 Context
ctx Cipher
cipherAlg
else do
let resumingSession :: Maybe SessionData
resumingSession = case ClientParams -> [(ByteString, SessionData)]
clientSessions ClientParams
cparams of
(ByteString
_, SessionData
sessionData) : [(ByteString, SessionData)]
_ ->
if Session
serverSession Session -> Session -> Bool
forall a. Eq a => a -> a -> Bool
== Session
clientSession then SessionData -> Maybe SessionData
forall a. a -> Maybe a
Just SessionData
sessionData else Maybe SessionData
forall a. Maybe a
Nothing
[(ByteString, SessionData)]
_ -> Maybe SessionData
forall a. Maybe a
Nothing
Context -> TLSSt () -> IO ()
forall a. Context -> TLSSt a -> IO a
usingState_ Context
ctx (TLSSt () -> IO ()) -> TLSSt () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Session -> TLSSt ()
setSession Session
serverSession
Bool -> TLSSt ()
setTLS12SessionResuming (Bool -> TLSSt ()) -> Bool -> TLSSt ()
forall a b. (a -> b) -> a -> b
$ Maybe SessionData -> Bool
forall a. Maybe a -> Bool
isJust Maybe SessionData
resumingSession
Context -> [ExtensionRaw] -> Maybe SessionData -> IO ()
updateContext12 Context
ctx [ExtensionRaw]
exts Maybe SessionData
resumingSession
processServerHello ClientParams
_ Context
_ Handshake
p = [Char] -> Maybe [Char] -> IO ()
forall (m :: * -> *) a. MonadIO m => [Char] -> Maybe [Char] -> m a
unexpected (Handshake -> [Char]
forall a. Show a => a -> [Char]
show Handshake
p) ([Char] -> Maybe [Char]
forall a. a -> Maybe a
Just [Char]
"server hello")
processServerExtension :: ExtensionRaw -> TLSSt ()
processServerExtension :: ExtensionRaw -> TLSSt ()
processServerExtension (ExtensionRaw ExtensionID
extID ByteString
content)
| ExtensionID
extID ExtensionID -> ExtensionID -> Bool
forall a. Eq a => a -> a -> Bool
== ExtensionID
EID_SecureRenegotiation = do
ByteString
cvd <- Role -> TLSSt ByteString
getVerifyData Role
ClientRole
ByteString
svd <- Role -> TLSSt ByteString
getVerifyData Role
ServerRole
let bs :: ByteString
bs = SecureRenegotiation -> ByteString
forall a. Extension a => a -> ByteString
extensionEncode (SecureRenegotiation -> ByteString)
-> SecureRenegotiation -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> SecureRenegotiation
SecureRenegotiation ByteString
cvd ByteString
svd
Bool -> TLSSt () -> TLSSt ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString
bs ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
content) (TLSSt () -> TLSSt ()) -> TLSSt () -> TLSSt ()
forall a b. (a -> b) -> a -> b
$
TLSError -> TLSSt ()
forall a. TLSError -> TLSSt a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (TLSError -> TLSSt ()) -> TLSError -> TLSSt ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol [Char]
"server secure renegotiation data not matching" AlertDescription
HandshakeFailure
| ExtensionID
extID ExtensionID -> ExtensionID -> Bool
forall a. Eq a => a -> a -> Bool
== ExtensionID
EID_SupportedVersions = case MessageType -> ByteString -> Maybe SupportedVersions
forall a. Extension a => MessageType -> ByteString -> Maybe a
extensionDecode MessageType
MsgTServerHello ByteString
content of
Just (SupportedVersionsServerHello Version
ver) -> Version -> TLSSt ()
setVersion Version
ver
Maybe SupportedVersions
_ -> () -> TLSSt ()
forall a. a -> TLSSt a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| ExtensionID
extID ExtensionID -> ExtensionID -> Bool
forall a. Eq a => a -> a -> Bool
== ExtensionID
EID_KeyShare = do
Bool
hrr <- TLSSt Bool
getTLS13HRR
let msgt :: MessageType
msgt = if Bool
hrr then MessageType
MsgTHelloRetryRequest else MessageType
MsgTServerHello
Maybe KeyShare -> TLSSt ()
setTLS13KeyShare (Maybe KeyShare -> TLSSt ()) -> Maybe KeyShare -> TLSSt ()
forall a b. (a -> b) -> a -> b
$ MessageType -> ByteString -> Maybe KeyShare
forall a. Extension a => MessageType -> ByteString -> Maybe a
extensionDecode MessageType
msgt ByteString
content
| ExtensionID
extID ExtensionID -> ExtensionID -> Bool
forall a. Eq a => a -> a -> Bool
== ExtensionID
EID_PreSharedKey =
Maybe PreSharedKey -> TLSSt ()
setTLS13PreSharedKey (Maybe PreSharedKey -> TLSSt ()) -> Maybe PreSharedKey -> TLSSt ()
forall a b. (a -> b) -> a -> b
$ MessageType -> ByteString -> Maybe PreSharedKey
forall a. Extension a => MessageType -> ByteString -> Maybe a
extensionDecode MessageType
MsgTServerHello ByteString
content
| ExtensionID
extID ExtensionID -> ExtensionID -> Bool
forall a. Eq a => a -> a -> Bool
== ExtensionID
EID_SessionTicket = ByteString -> TLSSt ()
setTLS12SessionTicket ByteString
""
processServerExtension ExtensionRaw
_ = () -> TLSSt ()
forall a. a -> TLSSt a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
updateContext13 :: Context -> Cipher -> IO ()
updateContext13 :: Context -> Cipher -> IO ()
updateContext13 Context
ctx Cipher
cipherAlg = do
Established
established <- Context -> IO Established
ctxEstablished Context
ctx
Bool
eof <- Context -> IO Bool
ctxEOF Context
ctx
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Established
established Established -> Established -> Bool
forall a. Eq a => a -> a -> Bool
== Established
Established Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
eof) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$
[Char] -> AlertDescription -> TLSError
Error_Protocol
[Char]
"renegotiation to TLS 1.3 or later is not allowed"
AlertDescription
ProtocolVersion
IO (Either TLSError ()) -> IO ()
forall (m :: * -> *) a. MonadIO m => m (Either TLSError a) -> m a
failOnEitherError (IO (Either TLSError ()) -> IO ())
-> IO (Either TLSError ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ Context
-> HandshakeM (Either TLSError ()) -> IO (Either TLSError ())
forall (m :: * -> *) a. MonadIO m => Context -> HandshakeM a -> m a
usingHState Context
ctx (HandshakeM (Either TLSError ()) -> IO (Either TLSError ()))
-> HandshakeM (Either TLSError ()) -> IO (Either TLSError ())
forall a b. (a -> b) -> a -> b
$ Cipher -> HandshakeM (Either TLSError ())
setHelloParameters13 Cipher
cipherAlg
updateContext12 :: Context -> [ExtensionRaw] -> Maybe SessionData -> IO ()
updateContext12 :: Context -> [ExtensionRaw] -> Maybe SessionData -> IO ()
updateContext12 Context
ctx [ExtensionRaw]
exts Maybe SessionData
resumingSession = do
Bool
ems <- Context -> Version -> MessageType -> [ExtensionRaw] -> IO Bool
forall (m :: * -> *).
MonadIO m =>
Context -> Version -> MessageType -> [ExtensionRaw] -> m Bool
processExtendedMainSecret Context
ctx Version
TLS12 MessageType
MsgTServerHello [ExtensionRaw]
exts
case Maybe SessionData
resumingSession of
Maybe SessionData
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just SessionData
sessionData -> do
let emsSession :: Bool
emsSession = SessionFlag
SessionEMS SessionFlag -> [SessionFlag] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` SessionData -> [SessionFlag]
sessionFlags SessionData
sessionData
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
ems Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool
emsSession) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
let err :: [Char]
err = [Char]
"server resumes a session which is not EMS consistent"
in TLSError -> IO ()
forall (m :: * -> *) a. MonadIO m => TLSError -> m a
throwCore (TLSError -> IO ()) -> TLSError -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> AlertDescription -> TLSError
Error_Protocol [Char]
err AlertDescription
HandshakeFailure
let mainSecret :: ByteString
mainSecret = SessionData -> ByteString
sessionSecret SessionData
sessionData
Context -> HandshakeM () -> IO ()
forall (m :: * -> *) a. MonadIO m => Context -> HandshakeM a -> m a
usingHState Context
ctx (HandshakeM () -> IO ()) -> HandshakeM () -> IO ()
forall a b. (a -> b) -> a -> b
$ Version -> Role -> ByteString -> HandshakeM ()
setMainSecret Version
TLS12 Role
ClientRole ByteString
mainSecret
Context -> MainSecret -> IO ()
forall a. LogLabel a => Context -> a -> IO ()
logKey Context
ctx (ByteString -> MainSecret
MainSecret ByteString
mainSecret)