2013-07-18 06:19:05 +00:00
|
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
|
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
-- |
|
|
|
|
-- Module : Network.TLS.Handshake.State
|
|
|
|
-- License : BSD-style
|
|
|
|
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
|
|
|
|
-- Stability : experimental
|
|
|
|
-- Portability : unknown
|
|
|
|
--
|
|
|
|
module Network.TLS.Handshake.State
|
|
|
|
( HandshakeState(..)
|
|
|
|
, ClientCertRequestData
|
|
|
|
, HandshakeM
|
|
|
|
, newEmptyHandshake
|
2013-07-19 06:47:33 +00:00
|
|
|
, runHandshake
|
2013-07-20 06:18:16 +00:00
|
|
|
-- * key accessors
|
2013-07-19 06:47:54 +00:00
|
|
|
, setPublicKey
|
|
|
|
, setPrivateKey
|
|
|
|
, setClientPublicKey
|
|
|
|
, setClientPrivateKey
|
2013-07-20 06:18:16 +00:00
|
|
|
-- * cert accessors
|
|
|
|
, setClientCertSent
|
|
|
|
, getClientCertSent
|
|
|
|
, setCertReqSent
|
|
|
|
, getCertReqSent
|
|
|
|
, setClientCertChain
|
|
|
|
, getClientCertChain
|
|
|
|
, setClientCertRequest
|
|
|
|
, getClientCertRequest
|
2013-07-20 07:21:15 +00:00
|
|
|
-- * digest accessors
|
|
|
|
, addHandshakeMessage
|
|
|
|
, updateHandshakeDigest
|
|
|
|
, getHandshakeMessages
|
2013-07-18 06:19:05 +00:00
|
|
|
) where
|
|
|
|
|
|
|
|
import Network.TLS.Util
|
|
|
|
import Network.TLS.Struct
|
2013-07-22 07:35:53 +00:00
|
|
|
import Network.TLS.Record.State
|
2013-07-18 06:19:05 +00:00
|
|
|
import Network.TLS.Packet
|
|
|
|
import Network.TLS.Crypto
|
2013-07-22 07:35:53 +00:00
|
|
|
import Network.TLS.Cipher
|
|
|
|
import Network.TLS.Compression
|
2013-07-18 06:19:05 +00:00
|
|
|
import qualified Data.ByteString as B
|
|
|
|
import Control.Applicative ((<$>))
|
|
|
|
import Control.Monad
|
|
|
|
import Control.Monad.State
|
|
|
|
import Data.X509 (CertificateChain)
|
|
|
|
|
|
|
|
data HandshakeState = HandshakeState
|
2013-07-18 06:34:05 +00:00
|
|
|
{ hstClientVersion :: !(Version)
|
|
|
|
, hstClientRandom :: !ClientRandom
|
|
|
|
, hstServerRandom :: !(Maybe ServerRandom)
|
|
|
|
, hstMasterSecret :: !(Maybe Bytes)
|
|
|
|
, hstRSAPublicKey :: !(Maybe PubKey)
|
|
|
|
, hstRSAPrivateKey :: !(Maybe PrivKey)
|
|
|
|
, hstRSAClientPublicKey :: !(Maybe PubKey)
|
|
|
|
, hstRSAClientPrivateKey :: !(Maybe PrivKey)
|
|
|
|
, hstHandshakeDigest :: !HashCtx
|
|
|
|
, hstHandshakeMessages :: [Bytes]
|
|
|
|
, hstClientCertRequest :: !(Maybe ClientCertRequestData) -- ^ Set to Just-value when certificate request was received
|
|
|
|
, hstClientCertSent :: !Bool -- ^ Set to true when a client certificate chain was sent
|
|
|
|
, hstCertReqSent :: !Bool -- ^ Set to true when a certificate request was sent
|
|
|
|
, hstClientCertChain :: !(Maybe CertificateChain)
|
2013-07-22 07:35:53 +00:00
|
|
|
, hstPendingTxState :: Maybe TransmissionState
|
|
|
|
, hstPendingRxState :: Maybe TransmissionState
|
|
|
|
, hstPendingCipher :: Maybe Cipher
|
|
|
|
, hstPendingCompression :: Compression
|
2013-07-18 06:19:05 +00:00
|
|
|
} deriving (Show)
|
|
|
|
|
|
|
|
type ClientCertRequestData = ([CertificateType],
|
|
|
|
Maybe [(HashAlgorithm, SignatureAlgorithm)],
|
|
|
|
[DistinguishedName])
|
|
|
|
|
|
|
|
|
2013-07-19 06:46:09 +00:00
|
|
|
newtype HandshakeM a = HandshakeM { runHandshakeM :: State HandshakeState a }
|
|
|
|
deriving (Functor, Monad)
|
2013-07-18 06:19:05 +00:00
|
|
|
|
|
|
|
instance MonadState HandshakeState HandshakeM where
|
2013-07-19 06:46:09 +00:00
|
|
|
put x = HandshakeM (put x)
|
|
|
|
get = HandshakeM (get)
|
2013-07-18 06:19:05 +00:00
|
|
|
#if MIN_VERSION_mtl(2,1,0)
|
2013-07-19 06:46:09 +00:00
|
|
|
state f = HandshakeM (state f)
|
2013-07-18 06:19:05 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
-- create a new empty handshake state
|
|
|
|
newEmptyHandshake :: Version -> ClientRandom -> HashCtx -> HandshakeState
|
|
|
|
newEmptyHandshake ver crand digestInit = HandshakeState
|
2013-07-18 06:34:05 +00:00
|
|
|
{ hstClientVersion = ver
|
|
|
|
, hstClientRandom = crand
|
|
|
|
, hstServerRandom = Nothing
|
|
|
|
, hstMasterSecret = Nothing
|
|
|
|
, hstRSAPublicKey = Nothing
|
|
|
|
, hstRSAPrivateKey = Nothing
|
|
|
|
, hstRSAClientPublicKey = Nothing
|
|
|
|
, hstRSAClientPrivateKey = Nothing
|
|
|
|
, hstHandshakeDigest = digestInit
|
|
|
|
, hstHandshakeMessages = []
|
|
|
|
, hstClientCertRequest = Nothing
|
|
|
|
, hstClientCertSent = False
|
|
|
|
, hstCertReqSent = False
|
|
|
|
, hstClientCertChain = Nothing
|
2013-07-22 07:35:53 +00:00
|
|
|
, hstPendingTxState = Nothing
|
|
|
|
, hstPendingRxState = Nothing
|
|
|
|
, hstPendingCipher = Nothing
|
|
|
|
, hstPendingCompression = nullCompression
|
2013-07-18 06:19:05 +00:00
|
|
|
}
|
2013-07-19 06:47:33 +00:00
|
|
|
|
|
|
|
runHandshake :: HandshakeState -> HandshakeM a -> (a, HandshakeState)
|
|
|
|
runHandshake hst f = runState (runHandshakeM f) hst
|
2013-07-19 06:47:54 +00:00
|
|
|
|
|
|
|
setPublicKey :: PubKey -> HandshakeM ()
|
|
|
|
setPublicKey pk = modify (\hst -> hst { hstRSAPublicKey = Just pk })
|
|
|
|
|
|
|
|
setPrivateKey :: PrivKey -> HandshakeM ()
|
|
|
|
setPrivateKey pk = modify (\hst -> hst { hstRSAPrivateKey = Just pk })
|
|
|
|
|
|
|
|
setClientPublicKey :: PubKey -> HandshakeM ()
|
|
|
|
setClientPublicKey pk = modify (\hst -> hst { hstRSAClientPublicKey = Just pk })
|
|
|
|
|
|
|
|
setClientPrivateKey :: PrivKey -> HandshakeM ()
|
|
|
|
setClientPrivateKey pk = modify (\hst -> hst { hstRSAClientPrivateKey = Just pk })
|
2013-07-20 06:18:16 +00:00
|
|
|
|
|
|
|
setCertReqSent :: Bool -> HandshakeM ()
|
|
|
|
setCertReqSent b = modify (\hst -> hst { hstCertReqSent = b })
|
|
|
|
|
|
|
|
getCertReqSent :: HandshakeM Bool
|
|
|
|
getCertReqSent = gets hstCertReqSent
|
|
|
|
|
|
|
|
setClientCertSent :: Bool -> HandshakeM ()
|
|
|
|
setClientCertSent b = modify (\hst -> hst { hstClientCertSent = b })
|
|
|
|
|
|
|
|
getClientCertSent :: HandshakeM Bool
|
|
|
|
getClientCertSent = gets hstClientCertSent
|
|
|
|
|
|
|
|
setClientCertChain :: CertificateChain -> HandshakeM ()
|
|
|
|
setClientCertChain b = modify (\hst -> hst { hstClientCertChain = Just b })
|
|
|
|
|
|
|
|
getClientCertChain :: HandshakeM (Maybe CertificateChain)
|
|
|
|
getClientCertChain = gets hstClientCertChain
|
|
|
|
|
|
|
|
setClientCertRequest :: ClientCertRequestData -> HandshakeM ()
|
|
|
|
setClientCertRequest d = modify (\hst -> hst { hstClientCertRequest = Just d })
|
|
|
|
|
|
|
|
getClientCertRequest :: HandshakeM (Maybe ClientCertRequestData)
|
|
|
|
getClientCertRequest = gets hstClientCertRequest
|
|
|
|
|
2013-07-20 07:21:15 +00:00
|
|
|
addHandshakeMessage :: Bytes -> HandshakeM ()
|
|
|
|
addHandshakeMessage content = modify $ \hs -> hs { hstHandshakeMessages = content : hstHandshakeMessages hs}
|
|
|
|
|
|
|
|
getHandshakeMessages :: HandshakeM [Bytes]
|
|
|
|
getHandshakeMessages = gets (reverse . hstHandshakeMessages)
|
|
|
|
|
|
|
|
updateHandshakeDigest :: Bytes -> HandshakeM ()
|
|
|
|
updateHandshakeDigest content = modify $ \hs -> hs { hstHandshakeDigest = hashUpdate (hstHandshakeDigest hs) content }
|