hs-tls/core/Network/TLS/State.hs

215 lines
7.7 KiB
Haskell
Raw Normal View History

{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2010-09-09 21:47:19 +00:00
-- |
-- Module : Network.TLS.State
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : unknown
--
-- the State module contains calls related to state initialization/manipulation
-- which is use by the Receiving module and the Sending module.
--
module Network.TLS.State
2013-07-12 06:27:28 +00:00
( TLSState(..)
, TLSSt
, runTLSState
, newTLSState
, withTLSRNG
, updateVerifiedData
, finishHandshakeTypeMaterial
, finishHandshakeMaterial
, certVerifyHandshakeTypeMaterial
, certVerifyHandshakeMaterial
, setVersion
, setVersionIfUnset
2013-07-13 07:03:25 +00:00
, getVersion
, getVersionWithDefault
2013-07-12 06:27:28 +00:00
, setSecureRenegotiation
, getSecureRenegotiation
, setExtensionNPN
, getExtensionNPN
, setNegotiatedProtocol
, getNegotiatedProtocol
, setServerNextProtocolSuggest
, getServerNextProtocolSuggest
, getClientCertificateChain
, setClientCertificateChain
, getVerifiedData
, setSession
, getSession
, isSessionResuming
, isClientContext
2013-07-28 06:32:44 +00:00
-- * random
, genRandom
, withRNG
2013-07-12 06:27:28 +00:00
) where
2010-09-09 21:47:19 +00:00
import Control.Applicative
2010-09-09 21:47:19 +00:00
import Network.TLS.Struct
2013-07-13 07:03:25 +00:00
import Network.TLS.RNG
import Network.TLS.Types (Role(..))
import qualified Data.ByteString as B
import Control.Monad.State
import Control.Monad.Error
2013-09-01 06:42:43 +00:00
import Crypto.Random
2013-05-19 07:05:46 +00:00
import Data.X509 (CertificateChain)
2010-09-09 21:47:19 +00:00
data TLSState = TLSState
2013-08-01 07:47:40 +00:00
{ stSession :: Session
2013-07-12 06:27:28 +00:00
, stSessionResuming :: Bool
, stSecureRenegotiation :: Bool -- RFC 5746
, stClientVerifiedData :: Bytes -- RFC 5746
, stServerVerifiedData :: Bytes -- RFC 5746
, stExtensionNPN :: Bool -- NPN draft extension
, stNegotiatedProtocol :: Maybe B.ByteString -- NPN protocol
, stServerNextProtocolSuggest :: Maybe [B.ByteString]
, stClientCertificateChain :: Maybe CertificateChain
, stRandomGen :: StateRNG
, stVersion :: Maybe Version
, stClientContext :: Role
2013-07-12 06:27:28 +00:00
} deriving (Show)
2010-09-09 21:47:19 +00:00
newtype TLSSt a = TLSSt { runTLSSt :: ErrorT TLSError (State TLSState) a }
deriving (Monad, MonadError TLSError, Functor, Applicative)
instance MonadState TLSState TLSSt where
2013-07-12 06:27:28 +00:00
put x = TLSSt (lift $ put x)
get = TLSSt (lift get)
#if MIN_VERSION_mtl(2,1,0)
2013-07-12 06:27:28 +00:00
state f = TLSSt (lift $ state f)
#endif
runTLSState :: TLSSt a -> TLSState -> (Either TLSError a, TLSState)
runTLSState f st = runState (runErrorT (runTLSSt f)) st
2010-09-09 21:47:19 +00:00
newTLSState :: CPRG g => g -> Role -> TLSState
newTLSState rng clientContext = TLSState
2013-08-01 07:47:40 +00:00
{ stSession = Session Nothing
2013-07-12 06:27:28 +00:00
, stSessionResuming = False
, stSecureRenegotiation = False
, stClientVerifiedData = B.empty
, stServerVerifiedData = B.empty
, stExtensionNPN = False
, stNegotiatedProtocol = Nothing
, stServerNextProtocolSuggest = Nothing
, stClientCertificateChain = Nothing
2013-07-24 16:35:57 +00:00
, stRandomGen = StateRNG rng
, stVersion = Nothing
, stClientContext = clientContext
2013-07-12 06:27:28 +00:00
}
2013-08-01 07:49:20 +00:00
updateVerifiedData :: Role -> Bytes -> TLSSt ()
updateVerifiedData sending bs = do
2013-07-12 06:27:28 +00:00
cc <- isClientContext
if cc /= sending
then modify (\st -> st { stServerVerifiedData = bs })
else modify (\st -> st { stClientVerifiedData = bs })
2010-09-09 21:47:19 +00:00
finishHandshakeTypeMaterial :: HandshakeType -> Bool
finishHandshakeTypeMaterial HandshakeType_ClientHello = True
finishHandshakeTypeMaterial HandshakeType_ServerHello = True
finishHandshakeTypeMaterial HandshakeType_Certificate = True
finishHandshakeTypeMaterial HandshakeType_HelloRequest = False
finishHandshakeTypeMaterial HandshakeType_ServerHelloDone = True
finishHandshakeTypeMaterial HandshakeType_ClientKeyXchg = True
finishHandshakeTypeMaterial HandshakeType_ServerKeyXchg = True
finishHandshakeTypeMaterial HandshakeType_CertRequest = True
finishHandshakeTypeMaterial HandshakeType_CertVerify = True
2010-09-09 21:47:19 +00:00
finishHandshakeTypeMaterial HandshakeType_Finished = True
2012-02-07 21:24:30 +00:00
finishHandshakeTypeMaterial HandshakeType_NPN = True
2010-09-09 21:47:19 +00:00
finishHandshakeMaterial :: Handshake -> Bool
finishHandshakeMaterial = finishHandshakeTypeMaterial . typeOfHandshake
certVerifyHandshakeTypeMaterial :: HandshakeType -> Bool
certVerifyHandshakeTypeMaterial HandshakeType_ClientHello = True
certVerifyHandshakeTypeMaterial HandshakeType_ServerHello = True
certVerifyHandshakeTypeMaterial HandshakeType_Certificate = True
certVerifyHandshakeTypeMaterial HandshakeType_HelloRequest = False
certVerifyHandshakeTypeMaterial HandshakeType_ServerHelloDone = True
certVerifyHandshakeTypeMaterial HandshakeType_ClientKeyXchg = True
certVerifyHandshakeTypeMaterial HandshakeType_ServerKeyXchg = True
certVerifyHandshakeTypeMaterial HandshakeType_CertRequest = True
certVerifyHandshakeTypeMaterial HandshakeType_CertVerify = False
certVerifyHandshakeTypeMaterial HandshakeType_Finished = False
certVerifyHandshakeTypeMaterial HandshakeType_NPN = False
certVerifyHandshakeMaterial :: Handshake -> Bool
certVerifyHandshakeMaterial = certVerifyHandshakeTypeMaterial . typeOfHandshake
2013-08-01 07:49:20 +00:00
setSession :: Session -> Bool -> TLSSt ()
2011-12-20 07:38:35 +00:00
setSession session resuming = modify (\st -> st { stSession = session, stSessionResuming = resuming })
2013-08-01 07:49:20 +00:00
getSession :: TLSSt Session
2011-12-20 07:38:35 +00:00
getSession = gets stSession
2013-08-01 07:49:20 +00:00
isSessionResuming :: TLSSt Bool
2011-12-20 07:38:35 +00:00
isSessionResuming = gets stSessionResuming
2013-08-01 07:49:20 +00:00
setVersion :: Version -> TLSSt ()
setVersion ver = modify (\st -> st { stVersion = Just ver })
setVersionIfUnset :: Version -> TLSSt ()
setVersionIfUnset ver = modify maybeSet
where maybeSet st = case stVersion st of
Nothing -> st { stVersion = Just ver }
Just _ -> st
2010-09-09 21:47:19 +00:00
2013-08-01 07:49:20 +00:00
getVersion :: TLSSt Version
getVersion = maybe (error $ "internal error: version hasn't been set yet") id <$> gets stVersion
getVersionWithDefault :: Version -> TLSSt Version
getVersionWithDefault defaultVer = maybe defaultVer id <$> gets stVersion
2013-07-13 07:03:25 +00:00
2013-08-01 07:49:20 +00:00
setSecureRenegotiation :: Bool -> TLSSt ()
setSecureRenegotiation b = modify (\st -> st { stSecureRenegotiation = b })
2013-08-01 07:49:20 +00:00
getSecureRenegotiation :: TLSSt Bool
getSecureRenegotiation = gets stSecureRenegotiation
2013-08-01 07:49:20 +00:00
setExtensionNPN :: Bool -> TLSSt ()
setExtensionNPN b = modify (\st -> st { stExtensionNPN = b })
2013-08-01 07:49:20 +00:00
getExtensionNPN :: TLSSt Bool
getExtensionNPN = gets stExtensionNPN
2013-08-01 07:49:20 +00:00
setNegotiatedProtocol :: B.ByteString -> TLSSt ()
setNegotiatedProtocol s = modify (\st -> st { stNegotiatedProtocol = Just s })
2013-08-01 07:49:20 +00:00
getNegotiatedProtocol :: TLSSt (Maybe B.ByteString)
getNegotiatedProtocol = gets stNegotiatedProtocol
2013-08-01 07:49:20 +00:00
setServerNextProtocolSuggest :: [B.ByteString] -> TLSSt ()
setServerNextProtocolSuggest ps = modify (\st -> st { stServerNextProtocolSuggest = Just ps})
2013-08-01 07:49:20 +00:00
getServerNextProtocolSuggest :: TLSSt (Maybe [B.ByteString])
getServerNextProtocolSuggest = gets stServerNextProtocolSuggest
2013-08-01 07:49:20 +00:00
setClientCertificateChain :: CertificateChain -> TLSSt ()
setClientCertificateChain s = modify (\st -> st { stClientCertificateChain = Just s })
2013-08-01 07:49:20 +00:00
getClientCertificateChain :: TLSSt (Maybe CertificateChain)
getClientCertificateChain = gets stClientCertificateChain
2013-08-01 07:49:20 +00:00
getVerifiedData :: Role -> TLSSt Bytes
2013-07-24 05:50:56 +00:00
getVerifiedData client = gets (if client == ClientRole then stClientVerifiedData else stServerVerifiedData)
2013-08-01 07:49:20 +00:00
isClientContext :: TLSSt Role
isClientContext = gets stClientContext
2010-09-09 21:47:19 +00:00
2013-07-13 07:03:25 +00:00
genRandom :: Int -> TLSSt Bytes
2013-07-24 16:35:57 +00:00
genRandom n = do
st <- get
2013-09-01 06:42:43 +00:00
case withTLSRNG (stRandomGen st) (cprgGenerate n) of
2013-07-24 16:35:57 +00:00
(bytes, rng') -> put (st { stRandomGen = rng' }) >> return bytes
2013-07-28 06:32:44 +00:00
withRNG :: (forall g . CPRG g => g -> (a, g)) -> TLSSt a
withRNG f = do
st <- get
let (a,rng') = withTLSRNG (stRandomGen st) f
put (st { stRandomGen = rng' })
return a