2011-04-11 18:54:21 +00:00
|
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleContexts, MultiParamTypeClasses, ExistentialQuantification, RankNTypes #-}
|
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
|
|
|
|
( TLSState(..)
|
2011-03-01 20:01:40 +00:00
|
|
|
, TLSSt
|
|
|
|
, runTLSState
|
2010-09-09 21:47:19 +00:00
|
|
|
, TLSHandshakeState(..)
|
|
|
|
, TLSCryptState(..)
|
|
|
|
, TLSMacState(..)
|
2010-10-02 09:32:29 +00:00
|
|
|
, TLSStatus(..)
|
|
|
|
, HandshakeStatus(..)
|
2010-09-09 21:47:19 +00:00
|
|
|
, newTLSState
|
2011-04-11 18:54:21 +00:00
|
|
|
, genTLSRandom
|
2010-10-03 10:01:22 +00:00
|
|
|
, withTLSRNG
|
2010-09-09 21:47:19 +00:00
|
|
|
, assert -- FIXME move somewhere else (Internal.hs ?)
|
2010-10-02 21:02:37 +00:00
|
|
|
, updateStatusHs
|
|
|
|
, updateStatusCC
|
2010-09-09 21:47:19 +00:00
|
|
|
, finishHandshakeTypeMaterial
|
|
|
|
, finishHandshakeMaterial
|
|
|
|
, makeDigest
|
|
|
|
, setMasterSecret
|
|
|
|
, setPublicKey
|
|
|
|
, setPrivateKey
|
|
|
|
, setKeyBlock
|
|
|
|
, setVersion
|
|
|
|
, setCipher
|
|
|
|
, setServerRandom
|
|
|
|
, switchTxEncryption
|
|
|
|
, switchRxEncryption
|
2011-05-12 07:28:55 +00:00
|
|
|
, getCipherKeyExchangeType
|
2010-09-09 21:47:19 +00:00
|
|
|
, isClientContext
|
|
|
|
, startHandshakeClient
|
|
|
|
, updateHandshakeDigest
|
2010-10-02 09:33:19 +00:00
|
|
|
, updateHandshakeDigestSplitted
|
2010-09-09 21:47:19 +00:00
|
|
|
, getHandshakeDigest
|
|
|
|
, endHandshake
|
|
|
|
) where
|
|
|
|
|
|
|
|
import Data.Word
|
2010-10-02 21:02:37 +00:00
|
|
|
import Data.List (find)
|
2011-02-20 08:37:19 +00:00
|
|
|
import Data.Maybe (isNothing)
|
2010-09-26 17:51:23 +00:00
|
|
|
import Network.TLS.Util
|
2010-09-09 21:47:19 +00:00
|
|
|
import Network.TLS.Struct
|
|
|
|
import Network.TLS.Wire
|
|
|
|
import Network.TLS.Packet
|
|
|
|
import Network.TLS.Crypto
|
|
|
|
import Network.TLS.Cipher
|
2010-10-06 08:07:48 +00:00
|
|
|
import Network.TLS.MAC
|
2010-09-26 09:34:47 +00:00
|
|
|
import qualified Data.ByteString as B
|
2010-09-09 21:47:19 +00:00
|
|
|
import Control.Monad
|
2011-03-01 20:01:40 +00:00
|
|
|
import Control.Monad.State
|
|
|
|
import Control.Monad.Error
|
2011-04-11 18:54:21 +00:00
|
|
|
import Crypto.Random
|
2010-09-09 21:47:19 +00:00
|
|
|
|
|
|
|
assert :: Monad m => String -> [(String,Bool)] -> m ()
|
|
|
|
assert fctname list = forM_ list $ \ (name, assumption) -> do
|
|
|
|
when assumption $ fail (fctname ++ ": assumption about " ++ name ++ " failed")
|
|
|
|
|
2010-10-02 09:32:29 +00:00
|
|
|
data HandshakeStatus =
|
|
|
|
HsStatusClientHello
|
|
|
|
| HsStatusServerHello
|
|
|
|
| HsStatusServerCertificate
|
|
|
|
| HsStatusServerKeyXchg
|
|
|
|
| HsStatusServerCertificateReq
|
|
|
|
| HsStatusServerHelloDone
|
|
|
|
| HsStatusClientCertificate
|
|
|
|
| HsStatusClientKeyXchg
|
|
|
|
| HsStatusClientCertificateVerify
|
|
|
|
| HsStatusClientChangeCipher
|
|
|
|
| HsStatusClientFinished
|
|
|
|
| HsStatusServerChangeCipher
|
|
|
|
deriving (Show,Eq)
|
|
|
|
|
|
|
|
data TLSStatus =
|
|
|
|
StatusInit
|
|
|
|
| StatusHandshakeReq
|
|
|
|
| StatusHandshake HandshakeStatus
|
|
|
|
| StatusOk
|
|
|
|
deriving (Show,Eq)
|
|
|
|
|
2010-09-09 21:47:19 +00:00
|
|
|
data TLSCryptState = TLSCryptState
|
2010-09-26 09:34:47 +00:00
|
|
|
{ cstKey :: !Bytes
|
|
|
|
, cstIV :: !Bytes
|
|
|
|
, cstMacSecret :: !Bytes
|
2010-09-09 21:47:19 +00:00
|
|
|
} deriving (Show)
|
|
|
|
|
|
|
|
data TLSMacState = TLSMacState
|
|
|
|
{ msSequence :: Word64
|
|
|
|
} deriving (Show)
|
|
|
|
|
|
|
|
data TLSHandshakeState = TLSHandshakeState
|
|
|
|
{ hstClientVersion :: !(Version)
|
|
|
|
, hstClientRandom :: !ClientRandom
|
|
|
|
, hstServerRandom :: !(Maybe ServerRandom)
|
2010-09-26 09:34:47 +00:00
|
|
|
, hstMasterSecret :: !(Maybe Bytes)
|
2010-09-09 21:47:19 +00:00
|
|
|
, hstRSAPublicKey :: !(Maybe PublicKey)
|
|
|
|
, hstRSAPrivateKey :: !(Maybe PrivateKey)
|
|
|
|
, hstHandshakeDigest :: Maybe (HashCtx, HashCtx) -- FIXME could be only 1 hash in tls12
|
|
|
|
} deriving (Show)
|
|
|
|
|
2011-04-11 18:54:21 +00:00
|
|
|
data StateRNG = forall g . CryptoRandomGen g => StateRNG g
|
|
|
|
|
|
|
|
instance Show StateRNG where
|
|
|
|
show _ = "rng[..]"
|
|
|
|
|
2010-09-09 21:47:19 +00:00
|
|
|
data TLSState = TLSState
|
|
|
|
{ stClientContext :: Bool
|
|
|
|
, stVersion :: !Version
|
2010-10-02 09:32:29 +00:00
|
|
|
, stStatus :: !TLSStatus
|
2010-09-09 21:47:19 +00:00
|
|
|
, stHandshake :: !(Maybe TLSHandshakeState)
|
|
|
|
, stTxEncrypted :: Bool
|
|
|
|
, stRxEncrypted :: Bool
|
|
|
|
, stTxCryptState :: !(Maybe TLSCryptState)
|
|
|
|
, stRxCryptState :: !(Maybe TLSCryptState)
|
|
|
|
, stTxMacState :: !(Maybe TLSMacState)
|
|
|
|
, stRxMacState :: !(Maybe TLSMacState)
|
|
|
|
, stCipher :: Maybe Cipher
|
2011-04-11 18:54:21 +00:00
|
|
|
, stRandomGen :: StateRNG
|
2010-09-09 21:47:19 +00:00
|
|
|
} deriving (Show)
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
newtype TLSSt a = TLSSt { runTLSSt :: ErrorT TLSError (State TLSState) a }
|
|
|
|
deriving (Monad, MonadError TLSError)
|
|
|
|
|
|
|
|
instance Functor TLSSt where
|
|
|
|
fmap f = TLSSt . fmap f . runTLSSt
|
|
|
|
|
|
|
|
instance MonadState TLSState TLSSt where
|
|
|
|
put x = TLSSt (lift $ put x)
|
|
|
|
get = TLSSt (lift get)
|
|
|
|
|
|
|
|
runTLSState :: TLSSt a -> TLSState -> (Either TLSError a, TLSState)
|
|
|
|
runTLSState f st = runState (runErrorT (runTLSSt f)) st
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-04-11 18:54:21 +00:00
|
|
|
newTLSState :: CryptoRandomGen g => g -> TLSState
|
2010-09-09 21:47:19 +00:00
|
|
|
newTLSState rng = TLSState
|
|
|
|
{ stClientContext = False
|
|
|
|
, stVersion = TLS10
|
2010-10-02 09:32:29 +00:00
|
|
|
, stStatus = StatusInit
|
2010-09-09 21:47:19 +00:00
|
|
|
, stHandshake = Nothing
|
|
|
|
, stTxEncrypted = False
|
|
|
|
, stRxEncrypted = False
|
|
|
|
, stTxCryptState = Nothing
|
|
|
|
, stRxCryptState = Nothing
|
|
|
|
, stTxMacState = Nothing
|
|
|
|
, stRxMacState = Nothing
|
|
|
|
, stCipher = Nothing
|
2011-04-11 18:54:21 +00:00
|
|
|
, stRandomGen = StateRNG rng
|
2010-09-09 21:47:19 +00:00
|
|
|
}
|
|
|
|
|
2011-04-11 18:54:21 +00:00
|
|
|
withTLSRNG :: StateRNG -> (forall g . CryptoRandomGen g => g -> Either e (a,g)) -> Either e (a, StateRNG)
|
|
|
|
withTLSRNG (StateRNG rng) f = case f rng of
|
|
|
|
Left err -> Left err
|
|
|
|
Right (a, rng') -> Right (a, StateRNG rng')
|
|
|
|
|
|
|
|
genTLSRandom :: (MonadState TLSState m, MonadError TLSError m) => Int -> m Bytes
|
|
|
|
genTLSRandom n = do
|
2011-03-01 20:01:40 +00:00
|
|
|
st <- get
|
2011-04-11 18:54:21 +00:00
|
|
|
case withTLSRNG (stRandomGen st) (genBytes n) of
|
|
|
|
Left err -> throwError $ Error_Random $ show err
|
|
|
|
Right (bytes, rng') -> put (st { stRandomGen = rng' }) >> return bytes
|
2010-10-03 10:01:22 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
makeDigest :: MonadState TLSState m => Bool -> Header -> Bytes -> m Bytes
|
2010-09-09 21:47:19 +00:00
|
|
|
makeDigest w hdr content = do
|
2011-03-01 20:01:40 +00:00
|
|
|
st <- get
|
2010-10-06 08:07:48 +00:00
|
|
|
let ver = stVersion st
|
2011-02-20 08:37:19 +00:00
|
|
|
let cst = fromJust "crypt state" $ if w then stTxCryptState st else stRxCryptState st
|
|
|
|
let ms = fromJust "mac state" $ if w then stTxMacState st else stRxMacState st
|
|
|
|
let cipher = fromJust "cipher" $ stCipher st
|
2010-10-06 08:07:48 +00:00
|
|
|
let machash = cipherMACHash cipher
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2010-10-06 08:07:48 +00:00
|
|
|
let (macF, msg) =
|
|
|
|
if ver < TLS10
|
|
|
|
then (macSSL machash, B.concat [ encodeWord64 $ msSequence ms, encodeHeaderNoVer hdr, content ])
|
|
|
|
else (hmac machash 64, B.concat [ encodeWord64 $ msSequence ms, encodeHeader hdr, content ])
|
|
|
|
let digest = macF (cstMacSecret cst) msg
|
2010-09-09 21:47:19 +00:00
|
|
|
|
|
|
|
let newms = ms { msSequence = (msSequence ms) + 1 }
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
modify (\_ -> if w then st { stTxMacState = Just newms } else st { stRxMacState = Just newms })
|
2010-09-09 21:47:19 +00:00
|
|
|
return digest
|
|
|
|
|
2010-10-02 21:02:37 +00:00
|
|
|
hsStatusTransitionTable :: [ (HandshakeType, TLSStatus, [ TLSStatus ]) ]
|
|
|
|
hsStatusTransitionTable =
|
|
|
|
[ (HandshakeType_HelloRequest, StatusHandshakeReq,
|
|
|
|
[ StatusOk ])
|
|
|
|
, (HandshakeType_ClientHello, StatusHandshake HsStatusClientHello,
|
|
|
|
[ StatusInit, StatusHandshakeReq ])
|
|
|
|
, (HandshakeType_ServerHello, StatusHandshake HsStatusServerHello,
|
|
|
|
[ StatusHandshake HsStatusClientHello ])
|
|
|
|
, (HandshakeType_Certificate, StatusHandshake HsStatusServerCertificate,
|
|
|
|
[ StatusHandshake HsStatusServerHello ])
|
|
|
|
, (HandshakeType_ServerKeyXchg, StatusHandshake HsStatusServerKeyXchg,
|
|
|
|
[ StatusHandshake HsStatusServerHello
|
|
|
|
, StatusHandshake HsStatusServerCertificate ])
|
|
|
|
, (HandshakeType_CertRequest, StatusHandshake HsStatusServerCertificateReq,
|
|
|
|
[ StatusHandshake HsStatusServerHello
|
|
|
|
, StatusHandshake HsStatusServerCertificate
|
|
|
|
, StatusHandshake HsStatusServerKeyXchg ])
|
|
|
|
, (HandshakeType_ServerHelloDone, StatusHandshake HsStatusServerHelloDone,
|
|
|
|
[ StatusHandshake HsStatusServerHello
|
|
|
|
, StatusHandshake HsStatusServerCertificate
|
|
|
|
, StatusHandshake HsStatusServerKeyXchg
|
|
|
|
, StatusHandshake HsStatusServerCertificateReq ])
|
|
|
|
, (HandshakeType_Certificate, StatusHandshake HsStatusClientCertificate,
|
|
|
|
[ StatusHandshake HsStatusServerHelloDone ])
|
|
|
|
, (HandshakeType_ClientKeyXchg, StatusHandshake HsStatusClientKeyXchg,
|
|
|
|
[ StatusHandshake HsStatusServerHelloDone
|
|
|
|
, StatusHandshake HsStatusClientCertificate ])
|
|
|
|
, (HandshakeType_CertVerify, StatusHandshake HsStatusClientCertificateVerify,
|
|
|
|
[ StatusHandshake HsStatusClientKeyXchg ])
|
|
|
|
, (HandshakeType_Finished, StatusHandshake HsStatusClientFinished,
|
|
|
|
[ StatusHandshake HsStatusClientChangeCipher ])
|
|
|
|
, (HandshakeType_Finished, StatusOk,
|
|
|
|
[ StatusHandshake HsStatusServerChangeCipher ])
|
|
|
|
]
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
updateStatus :: MonadState TLSState m => TLSStatus -> m ()
|
|
|
|
updateStatus x = modify (\st -> st { stStatus = x })
|
2010-10-02 21:02:37 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
updateStatusHs :: MonadState TLSState m => HandshakeType -> m (Maybe TLSError)
|
2010-10-02 21:02:37 +00:00
|
|
|
updateStatusHs ty = do
|
2011-03-01 20:01:40 +00:00
|
|
|
status <- return . stStatus =<< get
|
|
|
|
ns <- return . transition . stStatus =<< get
|
2010-10-02 21:02:37 +00:00
|
|
|
case ns of
|
|
|
|
Nothing -> return $ Just $ Error_Packet_unexpected (show status) ("handshake:" ++ show ty)
|
|
|
|
Just (_,x,_) -> updateStatus x >> return Nothing
|
|
|
|
where
|
|
|
|
edgeEq cur (ety, _, aprevs) = ty == ety && (maybe False (const True) $ find (== cur) aprevs)
|
|
|
|
transition currentStatus = find (edgeEq currentStatus) hsStatusTransitionTable
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
updateStatusCC :: MonadState TLSState m => Bool -> m (Maybe TLSError)
|
2010-10-02 21:02:37 +00:00
|
|
|
updateStatusCC sending = do
|
2011-03-01 20:01:40 +00:00
|
|
|
status <- return . stStatus =<< get
|
2010-10-02 21:02:37 +00:00
|
|
|
cc <- isClientContext
|
|
|
|
let x = case (cc /= sending, status) of
|
|
|
|
(False, StatusHandshake HsStatusClientKeyXchg) -> Just (StatusHandshake HsStatusClientChangeCipher)
|
|
|
|
(False, StatusHandshake HsStatusClientCertificateVerify) -> Just (StatusHandshake HsStatusClientChangeCipher)
|
|
|
|
(True, StatusHandshake HsStatusClientFinished) -> Just (StatusHandshake HsStatusServerChangeCipher)
|
|
|
|
_ -> Nothing
|
|
|
|
case x of
|
|
|
|
Just newstatus -> updateStatus newstatus >> return Nothing
|
|
|
|
Nothing -> return $ Just $ Error_Packet_unexpected (show status) ("Client Context: " ++ show cc)
|
|
|
|
|
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 = False
|
|
|
|
finishHandshakeTypeMaterial HandshakeType_Finished = True
|
|
|
|
|
|
|
|
finishHandshakeMaterial :: Handshake -> Bool
|
|
|
|
finishHandshakeMaterial = finishHandshakeTypeMaterial . typeOfHandshake
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
switchTxEncryption, switchRxEncryption :: MonadState TLSState m => m ()
|
|
|
|
switchTxEncryption = modify (\st -> st { stTxEncrypted = True })
|
|
|
|
switchRxEncryption = modify (\st -> st { stRxEncrypted = True })
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setServerRandom :: MonadState TLSState m => ServerRandom -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
setServerRandom ran = updateHandshake "srand" (\hst -> hst { hstServerRandom = Just ran })
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setMasterSecret :: MonadState TLSState m => Bytes -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
setMasterSecret premastersecret = do
|
2011-03-01 20:01:40 +00:00
|
|
|
st <- get
|
2010-09-09 21:47:19 +00:00
|
|
|
hasValidHandshake "master secret"
|
|
|
|
|
|
|
|
updateHandshake "master secret" (\hst ->
|
2011-02-20 08:37:19 +00:00
|
|
|
let ms = generateMasterSecret (stVersion st) premastersecret (hstClientRandom hst) (fromJust "server random" $ hstServerRandom hst) in
|
2010-09-26 09:34:47 +00:00
|
|
|
hst { hstMasterSecret = Just ms } )
|
2010-09-09 21:47:19 +00:00
|
|
|
return ()
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setPublicKey :: MonadState TLSState m => PublicKey -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
setPublicKey pk = updateHandshake "publickey" (\hst -> hst { hstRSAPublicKey = Just pk })
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setPrivateKey :: MonadState TLSState m => PrivateKey -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
setPrivateKey pk = updateHandshake "privatekey" (\hst -> hst { hstRSAPrivateKey = Just pk })
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setKeyBlock :: MonadState TLSState m => m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
setKeyBlock = do
|
2011-03-01 20:01:40 +00:00
|
|
|
st <- get
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-02-20 08:37:19 +00:00
|
|
|
let hst = fromJust "handshake" $ stHandshake st
|
2010-09-09 21:47:19 +00:00
|
|
|
|
|
|
|
let cc = stClientContext st
|
2011-02-20 08:37:19 +00:00
|
|
|
let cipher = fromJust "cipher" $ stCipher st
|
2010-09-09 21:47:19 +00:00
|
|
|
let keyblockSize = fromIntegral $ cipherKeyBlockSize cipher
|
2011-02-20 08:37:19 +00:00
|
|
|
let digestSize = fromIntegral $ cipherDigestSize cipher
|
|
|
|
let keySize = fromIntegral $ cipherKeySize cipher
|
|
|
|
let ivSize = fromIntegral $ cipherIVSize cipher
|
2010-10-05 17:45:10 +00:00
|
|
|
let kb = generateKeyBlock (stVersion st) (hstClientRandom hst)
|
2011-02-20 08:37:19 +00:00
|
|
|
(fromJust "server random" $ hstServerRandom hst)
|
|
|
|
(fromJust "master secret" $ hstMasterSecret hst) keyblockSize
|
2010-09-26 17:51:23 +00:00
|
|
|
|
|
|
|
let (cMACSecret, sMACSecret, cWriteKey, sWriteKey, cWriteIV, sWriteIV) =
|
2011-02-20 08:37:19 +00:00
|
|
|
fromJust "p6" $ partition6 kb (digestSize, digestSize, keySize, keySize, ivSize, ivSize)
|
2010-09-09 21:47:19 +00:00
|
|
|
|
|
|
|
let cstClient = TLSCryptState
|
2010-09-26 09:34:47 +00:00
|
|
|
{ cstKey = cWriteKey
|
|
|
|
, cstIV = cWriteIV
|
2010-09-09 21:47:19 +00:00
|
|
|
, cstMacSecret = cMACSecret }
|
|
|
|
let cstServer = TLSCryptState
|
2010-09-26 09:34:47 +00:00
|
|
|
{ cstKey = sWriteKey
|
|
|
|
, cstIV = sWriteIV
|
2010-09-09 21:47:19 +00:00
|
|
|
, cstMacSecret = sMACSecret }
|
|
|
|
let msClient = TLSMacState { msSequence = 0 }
|
|
|
|
let msServer = TLSMacState { msSequence = 0 }
|
2011-03-01 20:01:40 +00:00
|
|
|
put $ st
|
2010-09-09 21:47:19 +00:00
|
|
|
{ stTxCryptState = Just $ if cc then cstClient else cstServer
|
|
|
|
, stRxCryptState = Just $ if cc then cstServer else cstClient
|
|
|
|
, stTxMacState = Just $ if cc then msClient else msServer
|
|
|
|
, stRxMacState = Just $ if cc then msServer else msClient
|
|
|
|
}
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setCipher :: MonadState TLSState m => Cipher -> m ()
|
|
|
|
setCipher cipher = modify (\st -> st { stCipher = Just cipher })
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
setVersion :: MonadState TLSState m => Version -> m ()
|
|
|
|
setVersion ver = modify (\st -> st { stVersion = ver })
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-05-12 07:28:55 +00:00
|
|
|
getCipherKeyExchangeType :: MonadState TLSState m => m (Maybe CipherKeyExchangeType)
|
|
|
|
getCipherKeyExchangeType = get >>= return . (maybe Nothing (Just . cipherKeyExchange) . stCipher)
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
isClientContext :: MonadState TLSState m => m Bool
|
|
|
|
isClientContext = get >>= return . stClientContext
|
2010-09-09 21:47:19 +00:00
|
|
|
|
|
|
|
-- create a new empty handshake state
|
|
|
|
newEmptyHandshake :: Version -> ClientRandom -> TLSHandshakeState
|
|
|
|
newEmptyHandshake ver crand = TLSHandshakeState
|
|
|
|
{ hstClientVersion = ver
|
|
|
|
, hstClientRandom = crand
|
|
|
|
, hstServerRandom = Nothing
|
|
|
|
, hstMasterSecret = Nothing
|
|
|
|
, hstRSAPublicKey = Nothing
|
|
|
|
, hstRSAPrivateKey = Nothing
|
|
|
|
, hstHandshakeDigest = Nothing
|
|
|
|
}
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
startHandshakeClient :: MonadState TLSState m => Version -> ClientRandom -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
startHandshakeClient ver crand = do
|
|
|
|
-- FIXME check if handshake is already not null
|
2011-03-01 20:01:40 +00:00
|
|
|
chs <- get >>= return . stHandshake
|
2010-09-09 21:47:19 +00:00
|
|
|
when (isNothing chs) $
|
2011-03-01 20:01:40 +00:00
|
|
|
modify (\st -> st { stHandshake = Just $ newEmptyHandshake ver crand })
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
hasValidHandshake :: MonadState TLSState m => String -> m ()
|
|
|
|
hasValidHandshake name = get >>= \st -> assert name [ ("valid handshake", isNothing $ stHandshake st) ]
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
updateHandshake :: MonadState TLSState m => String -> (TLSHandshakeState -> TLSHandshakeState) -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
updateHandshake n f = do
|
|
|
|
hasValidHandshake n
|
2011-03-01 20:01:40 +00:00
|
|
|
modify (\st -> st { stHandshake = maybe Nothing (Just . f) (stHandshake st) })
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
updateHandshakeDigest :: MonadState TLSState m => Bytes -> m ()
|
2010-09-09 21:47:19 +00:00
|
|
|
updateHandshakeDigest content = updateHandshake "update digest" (\hs ->
|
2010-09-26 09:34:47 +00:00
|
|
|
let (c1, c2) = case hstHandshakeDigest hs of
|
2010-09-09 21:47:19 +00:00
|
|
|
Nothing -> (initHash HashTypeSHA1, initHash HashTypeMD5)
|
|
|
|
Just (sha1ctx, md5ctx) -> (sha1ctx, md5ctx) in
|
2010-09-26 09:34:47 +00:00
|
|
|
let nc1 = updateHash c1 content in
|
|
|
|
let nc2 = updateHash c2 content in
|
2010-09-09 21:47:19 +00:00
|
|
|
hs { hstHandshakeDigest = Just (nc1, nc2) }
|
|
|
|
)
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
updateHandshakeDigestSplitted :: MonadState TLSState m => HandshakeType -> Bytes -> m ()
|
2010-10-02 09:33:19 +00:00
|
|
|
updateHandshakeDigestSplitted ty bytes = updateHandshakeDigest $ B.concat [hdr, bytes]
|
|
|
|
where
|
|
|
|
hdr = runPut $ encodeHandshakeHeader ty (B.length bytes)
|
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
getHandshakeDigest :: MonadState TLSState m => Bool -> m Bytes
|
2010-09-09 21:47:19 +00:00
|
|
|
getHandshakeDigest client = do
|
2011-03-01 20:01:40 +00:00
|
|
|
st <- get
|
2011-02-20 08:37:19 +00:00
|
|
|
let hst = fromJust "handshake" $ stHandshake st
|
|
|
|
let (sha1ctx, md5ctx) = fromJust "handshake digest" $ hstHandshakeDigest hst
|
|
|
|
let msecret = fromJust "master secret" $ hstMasterSecret hst
|
2010-09-26 15:32:28 +00:00
|
|
|
return $ (if client then generateClientFinished else generateServerFinished) (stVersion st) msecret md5ctx sha1ctx
|
2010-09-09 21:47:19 +00:00
|
|
|
|
2011-03-01 20:01:40 +00:00
|
|
|
endHandshake :: MonadState TLSState m => m ()
|
|
|
|
endHandshake = modify (\st -> st { stHandshake = Nothing })
|