Skip to content

Commit

Permalink
Merge PR haskell-tls#317.
Browse files Browse the repository at this point in the history
  • Loading branch information
kazu-yamamoto committed Dec 12, 2018
2 parents 4922694 + 4eaca35 commit d2a6f95
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 67 deletions.
1 change: 1 addition & 0 deletions core/Network/TLS/Context.hs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ contextNew backend params = liftIO $ do
, ctxLockRead = lockRead
, ctxLockState = lockState
, ctxPendingActions = as
, ctxKeyLogger = debugKeyLogger debug
}

-- | create a new context on an handle.
Expand Down
1 change: 1 addition & 0 deletions core/Network/TLS/Context/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ data Context = Context
, ctxLockState :: MVar () -- ^ lock used during read/write when receiving and sending packet.
-- it is usually nested in a write or read lock.
, ctxPendingActions :: MVar [PendingAction]
, ctxKeyLogger :: String -> IO ()
}

data Established = NotEstablished
Expand Down
38 changes: 14 additions & 24 deletions core/Network/TLS/Handshake/Client.hs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,6 @@ handshakeClient cparams ctx = do
-- So, the ClientRandom in the first client hello is necessary.
handshakeClient' :: ClientParams -> Context -> [Group] -> Maybe ClientRandom -> IO ()
handshakeClient' cparams ctx groups mcrand = do
-- putStr $ "groups = " ++ show groups ++ ", keyshare = ["
-- case groups of
-- [] -> putStrLn "]"
-- g:_ -> putStrLn $ show g ++ "]"
updateMeasure ctx incrementNbHandshakes
sentExtensions <- sendClientHello mcrand
recvServerHello sentExtensions
Expand Down Expand Up @@ -264,9 +260,7 @@ handshakeClient' cparams ctx groups mcrand = do
let hCh = hash usedHash $ B.concat hmsgs -- fixme
EarlySecret earlySecret <- usingHState ctx getTLS13Secret -- fixme
let clientEarlyTrafficSecret = deriveSecret usedHash earlySecret "c e traffic" hCh
-- putStrLn $ "hCh: " ++ showBytesHex hCh
-- dumpKey ctx "CLIENT_EARLY_TRAFFIC_SECRET" clientEarlyTrafficSecret
-- putStrLn "---- setTxState ctx usedHash usedCipher clientEarlyTrafficSecret"
logKey ctx (ClientEarlyTrafficSecret clientEarlyTrafficSecret)
setTxState ctx usedHash usedCipher clientEarlyTrafficSecret
mapChunks_ 16384 (sendPacket13 ctx . AppData13) earlyData
usingHState ctx $ setTLS13RTT0Status RTT0Sent
Expand Down Expand Up @@ -460,7 +454,8 @@ sendClientData cparams ctx = sendCertificate >> sendClientKeyXchg >> sendCertifi
(xver, prerand) <- usingState_ ctx $ (,) <$> getVersion <*> genRandom 46

let premaster = encodePreMasterSecret clientVersion prerand
usingHState ctx $ setMasterSecretFromPre xver ClientRole premaster
masterSecret <- usingHState ctx $ setMasterSecretFromPre xver ClientRole premaster
logKey ctx (MasterSecret masterSecret)
encryptedPreMaster <- do
-- SSL3 implementation generally forget this length field since it's redundant,
-- however TLS10 make it clear that the length field need to be present.
Expand Down Expand Up @@ -504,8 +499,8 @@ sendClientData cparams ctx = sendCertificate >> sendClientKeyXchg >> sendCertifi
Nothing -> throwCore $ Error_Protocol ("invalid server public key", True, HandshakeFailure)
Just pair -> return pair

usingHState ctx $ setMasterSecretFromPre xver ClientRole premaster

masterSecret <- usingHState ctx $ setMasterSecretFromPre xver ClientRole premaster
logKey ctx (MasterSecret masterSecret)
return $ CKX_DH clientDHPub

getCKX_ECDHE = do
Expand All @@ -516,7 +511,8 @@ sendClientData cparams ctx = sendCertificate >> sendClientKeyXchg >> sendCertifi
Nothing -> throwCore $ Error_Protocol ("invalid server public key", True, HandshakeFailure)
Just (clipub, premaster) -> do
xver <- usingState_ ctx getVersion
usingHState ctx $ setMasterSecretFromPre xver ClientRole premaster
masterSecret <- usingHState ctx $ setMasterSecretFromPre xver ClientRole premaster
logKey ctx (MasterSecret masterSecret)
return $ CKX_ECDH $ encodeGroupPublic clipub

-- In order to send a proper certificate verify message,
Expand Down Expand Up @@ -625,7 +621,9 @@ onServerHello ctx cparams sentExts (ServerHello rver serverRan serverSession cip
case resumingSession of
Nothing -> return $ RecvStateHandshake (processCertificate cparams ctx)
Just sessionData -> do
usingHState ctx (setMasterSecret rver ClientRole $ sessionSecret sessionData)
let masterSecret = sessionSecret sessionData
usingHState ctx $ setMasterSecret rver ClientRole masterSecret
logKey ctx (MasterSecret masterSecret)
return $ RecvStateNext expectChangeCipher
onServerHello _ _ _ p = unexpected (show p) (Just "server hello")

Expand Down Expand Up @@ -773,7 +771,6 @@ handshakeClient13' cparams ctx usedCipher usedHash = do
return accepted
hChSf <- transcriptHash ctx
when rtt0accepted $ sendPacket13 ctx (Handshake13 [EndOfEarlyData13])
-- putStrLn "---- setTxState ctx usedHash usedCipher clientHandshakeTrafficSecret"
setTxState ctx usedHash usedCipher clientHandshakeTrafficSecret
chain <- clientChain cparams ctx
runPacketFlight ctx $ do
Expand Down Expand Up @@ -816,12 +813,8 @@ handshakeClient13' cparams ctx usedCipher usedHash = do
hChSh <- transcriptHash ctx
let clientHandshakeTrafficSecret = deriveSecret usedHash handshakeSecret "c hs traffic" hChSh
serverHandshakeTrafficSecret = deriveSecret usedHash handshakeSecret "s hs traffic" hChSh
-- putStrLn $ "earlySecret: " ++ showBytesHex earlySecret
-- putStrLn $ "handshakeSecret: " ++ showBytesHex handshakeSecret
-- putStrLn $ "hChSh: " ++ showBytesHex hChSh
-- usingHState ctx getHandshakeMessages >>= mapM_ (putStrLn . showBytesHex)
-- dumpKey ctx "SERVER_HANDSHAKE_TRAFFIC_SECRET" serverHandshakeTrafficSecret
-- dumpKey ctx "CLIENT_HANDSHAKE_TRAFFIC_SECRET" clientHandshakeTrafficSecret
logKey ctx (ServerHandshakeTrafficSecret serverHandshakeTrafficSecret)
logKey ctx (ClientHandshakeTrafficSecret clientHandshakeTrafficSecret)
setRxState ctx usedHash usedCipher serverHandshakeTrafficSecret
return (resuming, handshakeSecret, clientHandshakeTrafficSecret, serverHandshakeTrafficSecret)

Expand All @@ -831,11 +824,8 @@ handshakeClient13' cparams ctx usedCipher usedHash = do
serverApplicationTrafficSecret0 = deriveSecret usedHash masterSecret "s ap traffic" hChSf
exporterMasterSecret = deriveSecret usedHash masterSecret "exp master" hChSf
usingState_ ctx $ setExporterMasterSecret exporterMasterSecret
-- putStrLn $ "hChSf: " ++ showBytesHex hChSf
-- putStrLn $ "masterSecret: " ++ showBytesHex masterSecret
-- dumpKey ctx "SERVER_TRAFFIC_SECRET_0" serverApplicationTrafficSecret0
-- dumpKey ctx "CLIENT_TRAFFIC_SECRET_0" clientApplicationTrafficSecret0
-- putStrLn "---- setTxState ctx usedHash usedCipher clientApplicationTrafficSecret0"
logKey ctx (ServerTrafficSecret0 serverApplicationTrafficSecret0)
logKey ctx (ClientTrafficSecret0 clientApplicationTrafficSecret0)
setTxState ctx usedHash usedCipher clientApplicationTrafficSecret0
setRxState ctx usedHash usedCipher serverApplicationTrafficSecret0
return masterSecret
Expand Down
16 changes: 0 additions & 16 deletions core/Network/TLS/Handshake/Common13.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ module Network.TLS.Handshake.Common13
, getCurrentTimeFromBase
, getSessionData13
, safeNonNegative32
, dumpKey
, RecvHandshake13M
, runRecvHandshake13
, recvHandshake13
Expand Down Expand Up @@ -57,7 +56,6 @@ import Network.TLS.Struct13
import Network.TLS.Types
import Network.TLS.Wire
import Network.TLS.Util
import System.IO
import Time.System

import Control.Monad.State.Strict
Expand Down Expand Up @@ -261,20 +259,6 @@ safeNonNegative32 x
| x <= 0 = 0
| finiteBitSize x <= 32 = x
| otherwise = x `min` fromIntegral (maxBound :: Word32)

----------------------------------------------------------------

dumpKey :: Context -> String -> ByteString -> IO ()
dumpKey ctx label key = do
mhst <- getHState ctx
case mhst of
Nothing -> return ()
Just hst -> do
let cr = unClientRandom $ hstClientRandom hst
hPutStrLn stderr $ label ++ " " ++ dump cr ++ " " ++ dump key
where
dump = init . tail . showBytesHex

----------------------------------------------------------------

newtype RecvHandshake13M m a = RecvHandshake13M (StateT [Handshake13] m a)
Expand Down
40 changes: 40 additions & 0 deletions core/Network/TLS/Handshake/Key.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ module Network.TLS.Handshake.Key
, generateFFDHE
, generateFFDHEShared
, getLocalDigitalSignatureAlg
, logKey
, LogKey(..)
) where

import Control.Monad.State.Strict
Expand All @@ -30,6 +32,7 @@ import Network.TLS.Crypto
import Network.TLS.Types
import Network.TLS.Context.Internal
import Network.TLS.Imports
import Network.TLS.Struct

{- if the RSA encryption fails we just return an empty bytestring, and let the protocol
- fail by itself; however it would be probably better to just report it since it's an internal problem.
Expand Down Expand Up @@ -86,3 +89,40 @@ getLocalDigitalSignatureAlg ctx = do
case findDigitalSignatureAlg keys of
Just sigAlg -> return sigAlg
Nothing -> fail "selected credential does not support signing"

----------------------------------------------------------------

data LogKey = MasterSecret ByteString
| ClientEarlyTrafficSecret ByteString
| ServerHandshakeTrafficSecret ByteString
| ClientHandshakeTrafficSecret ByteString
| ServerTrafficSecret0 ByteString
| ClientTrafficSecret0 ByteString

labelAndKey :: LogKey -> (String, ByteString)
labelAndKey (MasterSecret key) =
("CLIENT_RANDOM", key)
labelAndKey (ClientEarlyTrafficSecret key) =
("CLIENT_EARLY_TRAFFIC_SECRET", key)
labelAndKey (ServerHandshakeTrafficSecret key) =
("SERVER_HANDSHAKE_TRAFFIC_SECRET", key)
labelAndKey (ClientHandshakeTrafficSecret key) =
("CLIENT_HANDSHAKE_TRAFFIC_SECRET", key)
labelAndKey (ServerTrafficSecret0 key) =
("SERVER_TRAFFIC_SECRET_0", key)
labelAndKey (ClientTrafficSecret0 key) =
("CLIENT_TRAFFIC_SECRET_0", key)

-- NSS Key Log Format
-- See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
logKey :: Context -> LogKey -> IO ()
logKey ctx logkey = do
mhst <- getHState ctx
case mhst of
Nothing -> return ()
Just hst -> do
let cr = unClientRandom $ hstClientRandom hst
(label,key) = labelAndKey logkey
ctxKeyLogger ctx $ label ++ " " ++ dump cr ++ " " ++ dump key
where
dump = init . tail . showBytesHex
10 changes: 7 additions & 3 deletions core/Network/TLS/Handshake/Process.hs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ processClientKeyXchg ctx (CKX_RSA encryptedPremaster) = do
(rver, role, random) <- usingState_ ctx $ do
(,,) <$> getVersion <*> isClientContext <*> genRandom 48
ePremaster <- decryptRSA ctx encryptedPremaster
usingHState ctx $ do
masterSecret <- usingHState ctx $ do
expectedVer <- gets hstClientVersion
case ePremaster of
Left _ -> setMasterSecretFromPre rver role random
Expand All @@ -103,6 +103,8 @@ processClientKeyXchg ctx (CKX_RSA encryptedPremaster) = do
Right (ver, _)
| ver /= expectedVer -> setMasterSecretFromPre rver role random
| otherwise -> setMasterSecretFromPre rver role premaster
liftIO $ logKey ctx (MasterSecret masterSecret)

processClientKeyXchg ctx (CKX_DH clientDHValue) = do
rver <- usingState_ ctx getVersion
role <- usingState_ ctx isClientContext
Expand All @@ -114,7 +116,8 @@ processClientKeyXchg ctx (CKX_DH clientDHValue) = do

dhpriv <- usingHState ctx getDHPrivate
let premaster = dhGetShared params dhpriv clientDHValue
usingHState ctx $ setMasterSecretFromPre rver role premaster
masterSecret <- usingHState ctx $ setMasterSecretFromPre rver role premaster
liftIO $ logKey ctx (MasterSecret masterSecret)

processClientKeyXchg ctx (CKX_ECDH bytes) = do
ServerECDHParams grp _ <- usingHState ctx getServerECDHParams
Expand All @@ -126,7 +129,8 @@ processClientKeyXchg ctx (CKX_ECDH bytes) = do
Just premaster -> do
rver <- usingState_ ctx getVersion
role <- usingState_ ctx isClientContext
usingHState ctx $ setMasterSecretFromPre rver role premaster
masterSecret <- usingHState ctx $ setMasterSecretFromPre rver role premaster
liftIO $ logKey ctx (MasterSecret masterSecret)
Nothing -> throwCore $ Error_Protocol ("cannote generate a shared secret on ECDH", True, HandshakeFailure)

processClientFinished :: Context -> FinishedData -> IO ()
Expand Down
31 changes: 8 additions & 23 deletions core/Network/TLS/Handshake/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,9 @@ doHandshake sparams mcred ctx chosenVersion usedCipher usedCompression clientSes
usingState_ ctx (setSession clientSession True)
serverhello <- makeServerHello clientSession
sendPacket ctx $ Handshake [serverhello]
usingHState ctx $ setMasterSecret chosenVersion ServerRole $ sessionSecret sessionData
let masterSecret = sessionSecret sessionData
usingHState ctx $ setMasterSecret chosenVersion ServerRole masterSecret
logKey ctx (MasterSecret masterSecret)
sendChangeCipherAndFinish ctx ServerRole
recvChangeCipherAndFinish ctx
handshakeTerminate ctx
Expand Down Expand Up @@ -686,9 +688,6 @@ handshakeServerWithTLS13 sparams ctx chosenVersion allCreds exts clientCiphers _
keyShares <- case extensionLookup extensionID_KeyShare exts >>= extensionDecode MsgTClientHello of
Just (KeyShareClientHello kses) -> return kses
_ -> throwCore $ Error_Protocol ("key exchange not implemented", True, HandshakeFailure)
-- putStrLn $ "keyshare = " ++ show (map keyShareEntryGroup keyShares)
-- putStrLn "Handshake messages:"
-- usingHState ctx getHandshakeMessages >>= mapM_ (putStrLn . showBytesHex)
case findKeyShare keyShares serverGroups of
Nothing -> helloRetryRequest sparams ctx chosenVersion usedCipher exts serverGroups clientSession
Just keyShare -> do
Expand Down Expand Up @@ -728,10 +727,7 @@ doHandshake13 sparams cred@(certChain, _) ctx chosenVersion usedCipher exts used
hCh <- transcriptHash ctx
let earlySecret = hkdfExtract usedHash zero psk
clientEarlyTrafficSecret = deriveSecret usedHash earlySecret "c e traffic" hCh
-- dumpKey ctx "CLIENT_EARLY_TRAFFIC_SECRET" clientEarlyTrafficSecret
-- putStrLn $ "hCh: " ++ showBytesHex hCh
-- putStrLn $ "earlySecret: " ++ showBytesHex earlySecret
-- putStrLn $ "clientEarlyTrafficSecret: " ++ showBytesHex clientEarlyTrafficSecret
logKey ctx (ClientEarlyTrafficSecret clientEarlyTrafficSecret)
extensions <- checkBinder earlySecret binderInfo
let authenticated = isJust binderInfo
rtt0OK = authenticated && rtt0 && rtt0accept && is0RTTvalid
Expand All @@ -757,18 +753,9 @@ doHandshake13 sparams cred@(certChain, _) ctx chosenVersion usedCipher exts used
hChSh <- transcriptHash ctx
let clientHandshakeTrafficSecret = deriveSecret usedHash handshakeSecret "c hs traffic" hChSh
serverHandshakeTrafficSecret = deriveSecret usedHash handshakeSecret "s hs traffic" hChSh
-- putStrLn $ "handshakeSecret: " ++ showBytesHex handshakeSecret
-- putStrLn $ "hChSh: " ++ showBytesHex hChSh
-- usingHState ctx getHandshakeMessages >>= mapM_ (putStrLn . showBytesHex)
-- dumpKey ctx "SERVER_HANDSHAKE_TRAFFIC_SECRET" serverHandshakeTrafficSecret
-- dumpKey ctx "CLIENT_HANDSHAKE_TRAFFIC_SECRET" clientHandshakeTrafficSecret
{-
if rtt0OK then
putStrLn "---- setRxState ctx usedHash usedCipher clientEarlyTrafficSecret"
else
putStrLn "---- setRxState ctx usedHash usedCipher clientHandshakeTrafficSecret"
-}
liftIO $ do
logKey ctx (ServerHandshakeTrafficSecret serverHandshakeTrafficSecret)
logKey ctx (ClientHandshakeTrafficSecret clientHandshakeTrafficSecret)
setRxState ctx usedHash usedCipher $ if rtt0OK then clientEarlyTrafficSecret else clientHandshakeTrafficSecret
setTxState ctx usedHash usedCipher serverHandshakeTrafficSecret
----------------------------------------------------------------
Expand All @@ -787,10 +774,8 @@ doHandshake13 sparams cred@(certChain, _) ctx chosenVersion usedCipher exts used
exporterMasterSecret = deriveSecret usedHash masterSecret "exp master" hChSf
usingState_ ctx $ setExporterMasterSecret exporterMasterSecret
----------------------------------------------------------------
-- putStrLn $ "hChSf: " ++ showBytesHex hChSf
-- putStrLn $ "masterSecret: " ++ showBytesHex masterSecret
-- dumpKey ctx "SERVER_TRAFFIC_SECRET_0" serverApplicationTrafficSecret0
-- dumpKey ctx "CLIENT_TRAFFIC_SECRET_0" clientApplicationTrafficSecret0
logKey ctx (ServerTrafficSecret0 serverApplicationTrafficSecret0)
logKey ctx (ClientTrafficSecret0 clientApplicationTrafficSecret0)
setTxState ctx usedHash usedCipher serverApplicationTrafficSecret0
----------------------------------------------------------------
let established
Expand Down
3 changes: 2 additions & 1 deletion core/Network/TLS/Handshake/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,11 @@ setMasterSecretFromPre :: ByteArrayAccess preMaster
=> Version -- ^ chosen transmission version
-> Role -- ^ the role (Client or Server) of the generating side
-> preMaster -- ^ the pre master secret
-> HandshakeM ()
-> HandshakeM ByteString
setMasterSecretFromPre ver role premasterSecret = do
secret <- genSecret <$> get
setMasterSecret ver role secret
return secret
where genSecret hst =
generateMasterSecret ver (fromJust "cipher" $ hstPendingCipher hst)
premasterSecret
Expand Down
3 changes: 3 additions & 0 deletions core/Network/TLS/Parameters.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ data DebugParams = DebugParams
, debugPrintSeed :: Seed -> IO ()
-- | Force to choose this version in the server side.
, debugVersionForced :: Maybe Version
-- | Printing master keys. The default is no printing.
, debugKeyLogger :: String -> IO ()
}

defaultDebugParams :: DebugParams
defaultDebugParams = DebugParams
{ debugSeed = Nothing
, debugPrintSeed = const (return ())
, debugVersionForced = Nothing
, debugKeyLogger = \_ -> return ()
}

instance Show DebugParams where
Expand Down

0 comments on commit d2a6f95

Please sign in to comment.