hs-tls/core/Tests/Connection.hs

155 lines
5.4 KiB
Haskell
Raw Normal View History

module Connection
2013-07-21 05:57:26 +00:00
( newPairContext
, arbitraryPairParams
, setPairParamsSessionManager
, setPairParamsSessionResuming
2013-07-21 06:37:58 +00:00
, establishDataPipe
2013-07-21 07:57:56 +00:00
, blockCipher
, streamCipher
2013-07-21 05:57:26 +00:00
) where
import Test.QuickCheck
import Certificate
import PubKey
import PipeChan
import Network.TLS
2013-05-19 07:05:46 +00:00
import Data.X509
2013-12-28 15:25:54 +00:00
import Control.Applicative
2013-07-21 06:37:58 +00:00
import Control.Concurrent.Chan
import Control.Concurrent
import qualified Control.Exception as E
import qualified Crypto.Random.AESCtr as RNG
import qualified Data.ByteString as B
debug = False
blockCipher :: Cipher
blockCipher = Cipher
2013-07-21 05:57:26 +00:00
{ cipherID = 0xff12
, cipherName = "rsa-id-const"
, cipherBulk = Bulk
{ bulkName = "id"
, bulkKeySize = 16
, bulkIVSize = 16
, bulkBlockSize = 16
, bulkF = BulkBlockF (\_ _ m -> m) (\_ _ m -> m)
2012-03-28 07:06:13 +00:00
}
2013-07-21 05:57:26 +00:00
, cipherHash = Hash
{ hashName = "const-hash"
, hashSize = 16
, hashF = (\_ -> B.replicate 16 1)
}
, cipherKeyExchange = CipherKeyExchange_RSA
, cipherMinVer = Nothing
}
2013-12-07 07:10:53 +00:00
blockCipherDHE_RSA :: Cipher
blockCipherDHE_RSA = blockCipher
{ cipherID = 0xff14
, cipherName = "dhe-rsa-id-const"
, cipherKeyExchange = CipherKeyExchange_DHE_RSA
}
2013-12-28 15:25:54 +00:00
blockCipherDHE_DSS :: Cipher
blockCipherDHE_DSS = blockCipher
{ cipherID = 0xff15
, cipherName = "dhe-dss-id-const"
, cipherKeyExchange = CipherKeyExchange_DHE_DSS
}
2013-12-07 07:10:53 +00:00
streamCipher :: Cipher
streamCipher = blockCipher
2013-07-21 05:57:26 +00:00
{ cipherID = 0xff13
, cipherBulk = Bulk
{ bulkName = "stream"
, bulkKeySize = 16
, bulkIVSize = 0
, bulkBlockSize = 0
, bulkF = BulkStreamF (\k -> k) (\i m -> (m,i)) (\i m -> (m,i))
2012-03-28 07:06:13 +00:00
}
2013-07-21 05:57:26 +00:00
}
supportedCiphers :: [Cipher]
2013-12-28 15:25:54 +00:00
supportedCiphers = [blockCipher,blockCipherDHE_RSA,blockCipherDHE_DSS,streamCipher]
supportedVersions :: [Version]
supportedVersions = [SSL3,TLS10,TLS11,TLS12]
arbitraryPairParams = do
2013-12-28 15:25:54 +00:00
(dsaPub, dsaPriv) <- (\(p,r) -> (PubKeyDSA p, PrivKeyDSA r)) <$> arbitraryDSAPair
let (pubKey, privKey) = (\(p, r) -> (PubKeyRSA p, PrivKeyRSA r)) $ getGlobalRSAPair
creds <- mapM (\(pub, priv) -> do
cert <- arbitraryX509WithKey (pub, priv)
return (CertificateChain [cert], priv)
) [ (pubKey, privKey), (dsaPub, dsaPriv) ]
connectVersion <- elements supportedVersions
let allowedVersions = [ v | v <- supportedVersions, v <= connectVersion ]
serAllowedVersions <- (:[]) `fmap` elements allowedVersions
serverCiphers <- arbitraryCiphers
clientCiphers <- oneof [arbitraryCiphers] `suchThat` (\cs -> or [x `elem` serverCiphers | x <- cs])
secNeg <- arbitrary
2012-03-28 07:06:13 +00:00
2013-12-28 15:25:54 +00:00
--let cred = (CertificateChain [servCert], PrivKeyRSA privKey)
2013-07-21 05:57:26 +00:00
let serverState = defaultParamsServer
{ pAllowedVersions = serAllowedVersions
2013-07-21 05:57:26 +00:00
, pCiphers = serverCiphers
2013-12-28 15:25:54 +00:00
, pCredentials = Credentials creds
2013-07-21 05:57:26 +00:00
, pUseSecureRenegotiation = secNeg
, pLogging = logging "server: "
2013-12-11 08:40:24 +00:00
, roleParams = roleParams $ updateServerParams (\sp -> sp { serverDHEParams = Just dhParams }) defaultParamsServer
2013-07-21 05:57:26 +00:00
}
let clientState = defaultParamsClient
{ pAllowedVersions = allowedVersions
2013-07-21 05:57:26 +00:00
, pCiphers = clientCiphers
, pUseSecureRenegotiation = secNeg
, pLogging = logging "client: "
}
return (clientState, serverState)
where
logging pre =
if debug
then defaultLogging { loggingPacketSent = putStrLn . ((pre ++ ">> ") ++)
, loggingPacketRecv = putStrLn . ((pre ++ "<< ") ++) }
else defaultLogging
arbitraryCiphers = resize (length supportedCiphers + 1) $ listOf1 (elements supportedCiphers)
setPairParamsSessionManager :: SessionManager -> (Params, Params) -> (Params, Params)
setPairParamsSessionManager manager (clientState, serverState) = (nc,ns)
2013-07-21 05:57:26 +00:00
where nc = setSessionManager manager clientState
ns = setSessionManager manager serverState
setPairParamsSessionResuming sessionStuff (clientState, serverState) = (nc,serverState)
2013-07-21 05:57:26 +00:00
where nc = updateClientParams (\cparams -> cparams { clientWantSessionResume = Just sessionStuff }) clientState
newPairContext pipe (cParams, sParams) = do
2013-07-21 05:57:26 +00:00
let noFlush = return ()
let noClose = return ()
2013-07-21 05:57:26 +00:00
cRNG <- RNG.makeSystem
sRNG <- RNG.makeSystem
2013-07-21 05:57:26 +00:00
let cBackend = Backend noFlush noClose (writePipeA pipe) (readPipeA pipe)
let sBackend = Backend noFlush noClose (writePipeB pipe) (readPipeB pipe)
cCtx' <- contextNew cBackend cParams cRNG
sCtx' <- contextNew sBackend sParams sRNG
2013-07-21 05:57:26 +00:00
return (cCtx', sCtx')
2013-07-21 06:37:58 +00:00
establishDataPipe params tlsServer tlsClient = do
-- initial setup
pipe <- newPipe
_ <- (runPipe pipe)
startQueue <- newChan
resultQueue <- newChan
(cCtx, sCtx) <- newPairContext pipe params
_ <- forkIO $ E.catch (tlsServer sCtx resultQueue) (printAndRaise "server")
_ <- forkIO $ E.catch (tlsClient startQueue cCtx) (printAndRaise "client")
return (startQueue, resultQueue)
where
printAndRaise :: String -> E.SomeException -> IO ()
printAndRaise s e = putStrLn (s ++ " exception: " ++ show e) >> E.throw e