tls-1.5.4: Benchmarks/Benchmarks.hs
{-# LANGUAGE BangPatterns #-}
module Main where
import Connection
import Certificate
import PubKey
import Gauge.Main
import Control.Concurrent.Chan
import Network.TLS
import Network.TLS.Extra.Cipher
import Data.X509
import Data.X509.Validation
import Data.Default.Class
import Data.IORef
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
blockCipher :: Cipher
blockCipher = Cipher
{ cipherID = 0xff12
, cipherName = "rsa-id-const"
, cipherBulk = Bulk
{ bulkName = "id"
, bulkKeySize = 16
, bulkIVSize = 16
, bulkExplicitIV= 0
, bulkAuthTagLen= 0
, bulkBlockSize = 16
, bulkF = BulkBlockF $ \ _ _ _ m -> (m, B.empty)
}
, cipherHash = MD5
, cipherPRFHash = Nothing
, cipherKeyExchange = CipherKeyExchange_RSA
, cipherMinVer = Nothing
}
getParams :: Version -> Cipher -> (ClientParams, ServerParams)
getParams connectVer cipher = (cParams, sParams)
where sParams = def { serverSupported = supported
, serverShared = def {
sharedCredentials = Credentials [ (CertificateChain [simpleX509 $ PubKeyRSA pubKey], PrivKeyRSA privKey) ]
}
}
cParams = (defaultParamsClient "" B.empty)
{ clientSupported = supported
, clientShared = def { sharedValidationCache = ValidationCache
{ cacheAdd = \_ _ _ -> return ()
, cacheQuery = \_ _ _ -> return ValidationCachePass
}
}
}
supported = def { supportedCiphers = [cipher]
, supportedVersions = [connectVer]
, supportedGroups = [X25519, FFDHE2048]
}
(pubKey, privKey) = getGlobalRSAPair
runTLSPipe :: (ClientParams, ServerParams)
-> (Context -> Chan b -> IO ())
-> (Chan a -> Context -> IO ())
-> a
-> IO b
runTLSPipe params tlsServer tlsClient d = do
withDataPipe params tlsServer tlsClient $ \(writeStart, readResult) -> do
writeStart d
readResult
runTLSPipeSimple :: (ClientParams, ServerParams) -> B.ByteString -> IO B.ByteString
runTLSPipeSimple params = runTLSPipe params tlsServer tlsClient
where tlsServer ctx queue = do
handshake ctx
d <- recvData ctx
writeChan queue d
bye ctx
tlsClient queue ctx = do
handshake ctx
d <- readChan queue
sendData ctx (L.fromChunks [d])
byeBye ctx
benchConnection :: (ClientParams, ServerParams) -> B.ByteString -> String -> Benchmark
benchConnection params !d name = bench name . nfIO $ runTLSPipeSimple params d
benchResumption :: (ClientParams, ServerParams) -> B.ByteString -> String -> Benchmark
benchResumption params !d name = env initializeSession runResumption
where
initializeSession = do
sessionRefs <- twoSessionRefs
let sessionManagers = twoSessionManagers sessionRefs
params1 = setPairParamsSessionManagers sessionManagers params
_ <- runTLSPipeSimple params1 d
Just sessionParams <- readClientSessionRef sessionRefs
let params2 = setPairParamsSessionResuming sessionParams params1
newIORef params2
runResumption paramsRef = bench name . nfIO $ do
params2 <- readIORef paramsRef
runTLSPipeSimple params2 d
benchResumption13 :: (ClientParams, ServerParams) -> B.ByteString -> String -> Benchmark
benchResumption13 params !d name = env initializeSession runResumption
where
initializeSession = do
sessionRefs <- twoSessionRefs
let sessionManagers = twoSessionManagers sessionRefs
params1 = setPairParamsSessionManagers sessionManagers params
_ <- runTLSPipeSimple params1 d
newIORef (params1, sessionRefs)
-- with TLS13 the sessionId is constantly changing so we must update
-- our parameters at each iteration unfortunately
runResumption paramsRef = bench name . nfIO $ do
(params1, sessionRefs) <- readIORef paramsRef
Just sessionParams <- readClientSessionRef sessionRefs
let params2 = setPairParamsSessionResuming sessionParams params1
runTLSPipeSimple params2 d
benchCiphers :: String -> Version -> B.ByteString -> [Cipher] -> Benchmark
benchCiphers name connectVer d = bgroup name . map doBench
where
doBench cipher =
benchResumption13 (getParams connectVer cipher) d (cipherName cipher)
main :: IO ()
main = defaultMain
[ bgroup "connection"
-- not sure the number actually make sense for anything. improve ..
[ benchConnection (getParams SSL3 blockCipher) small "SSL3-256 bytes"
, benchConnection (getParams TLS10 blockCipher) small "TLS10-256 bytes"
, benchConnection (getParams TLS11 blockCipher) small "TLS11-256 bytes"
, benchConnection (getParams TLS12 blockCipher) small "TLS12-256 bytes"
]
, bgroup "resumption"
[ benchResumption (getParams SSL3 blockCipher) small "SSL3-256 bytes"
, benchResumption (getParams TLS10 blockCipher) small "TLS10-256 bytes"
, benchResumption (getParams TLS11 blockCipher) small "TLS11-256 bytes"
, benchResumption (getParams TLS12 blockCipher) small "TLS12-256 bytes"
]
-- Here we try to measure TLS12 and TLS13 performance with AEAD ciphers.
-- Resumption and a larger message can be a demonstration of the symmetric
-- crypto but for TLS13 this does not work so well because of dhe_psk.
, benchCiphers "TLS12" TLS12 large
[ cipher_DHE_RSA_AES128GCM_SHA256
, cipher_DHE_RSA_AES256GCM_SHA384
, cipher_DHE_RSA_CHACHA20POLY1305_SHA256
, cipher_DHE_RSA_AES128CCM_SHA256
, cipher_DHE_RSA_AES128CCM8_SHA256
, cipher_ECDHE_RSA_AES128GCM_SHA256
, cipher_ECDHE_RSA_AES256GCM_SHA384
, cipher_ECDHE_RSA_CHACHA20POLY1305_SHA256
]
, benchCiphers "TLS13" TLS13 large
[ cipher_TLS13_AES128GCM_SHA256
, cipher_TLS13_AES256GCM_SHA384
, cipher_TLS13_CHACHA20POLY1305_SHA256
, cipher_TLS13_AES128CCM_SHA256
, cipher_TLS13_AES128CCM8_SHA256
]
]
where
small = B.replicate 256 0
large = B.replicate 102400 0