diff --git a/src/Common.hs b/src/Common.hs
--- a/src/Common.hs
+++ b/src/Common.hs
@@ -3,22 +3,31 @@
 module Common
     ( printCiphers
     , printDHParams
+    , printGroups
     , readNumber
     , readCiphers
     , readDHParams
+    , readGroups
     , printHandshakeInfo
+    , makeAddrInfo
+    , AddrInfo(..)
+    , getCertificateStore
     ) where
 
-import Control.Monad
-
 import Data.Char (isDigit)
-
+import Data.Maybe (fromJust)
 import Numeric (showHex)
+import Network.Socket
 
-import Network.TLS
+import Data.X509.CertificateStore
+import System.X509
+
+import Network.TLS hiding (HostName)
 import Network.TLS.Extra.Cipher
 import Network.TLS.Extra.FFDHE
 
+import Imports
+
 namedDHParams :: [(String, DHParams)]
 namedDHParams =
     [ ("ffdhe2048", ffdhe2048)
@@ -35,6 +44,20 @@
     , ("strong",    map cipherID ciphersuite_strong)
     ]
 
+namedGroups :: [(String, Group)]
+namedGroups =
+    [ ("ffdhe2048", FFDHE2048)
+    , ("ffdhe3072", FFDHE3072)
+    , ("ffdhe4096", FFDHE4096)
+    , ("ffdhe6144", FFDHE6144)
+    , ("ffdhe8192", FFDHE8192)
+    , ("p256", P256)
+    , ("p384", P384)
+    , ("p521", P521)
+    , ("x25519", X25519)
+    , ("x448", X448)
+    ]
+
 readNumber :: (Num a, Read a) => String -> Maybe a
 readNumber s
     | all isDigit s = Just $ read s
@@ -52,6 +75,9 @@
         Nothing -> (Just . read) `fmap` readFile s
         mparams -> return mparams
 
+readGroups :: String -> Maybe [Group]
+readGroups s = traverse (`lookup` namedGroups) (split ',' s)
+
 printCiphers :: IO ()
 printCiphers = do
     putStrLn "Supported ciphers"
@@ -74,6 +100,12 @@
     forM_ namedDHParams $ \(name, _) -> putStrLn name
     putStrLn "(or /path/to/dhparams)"
 
+printGroups :: IO ()
+printGroups = do
+    putStrLn "Groups"
+    putStrLn "====================================="
+    forM_ namedGroups $ \(name, _) -> putStrLn name
+
 printHandshakeInfo ctx = do
     info <- contextGetInformation ctx
     case info of
@@ -82,7 +114,37 @@
             putStrLn ("version: " ++ show (infoVersion i))
             putStrLn ("cipher: " ++ show (infoCipher i))
             putStrLn ("compression: " ++ show (infoCompression i))
+            putStrLn ("group: " ++ maybe "(none)" show (infoNegotiatedGroup i))
+            when (infoVersion i == TLS13) $ do
+                putStrLn ("handshake emode: " ++ show (fromJust (infoTLS13HandshakeMode i)))
+                putStrLn ("early data accepted: " ++ show (infoIsEarlyDataAccepted i))
     sni <- getClientSNI ctx
     case sni of
         Nothing -> return ()
         Just n  -> putStrLn ("server name indication: " ++ n)
+
+makeAddrInfo :: Maybe HostName -> PortNumber -> IO AddrInfo
+makeAddrInfo maddr port = do
+    let flgs = [AI_ADDRCONFIG, AI_NUMERICSERV, AI_PASSIVE]
+        hints = defaultHints {
+            addrFlags = flgs
+          , addrSocketType = Stream
+          }
+    head <$> getAddrInfo (Just hints) maddr (Just $ show port)
+
+split :: Char -> String -> [String]
+split _ "" = []
+split c s = case break (c==) s of
+    ("",r)  -> split c (tail r)
+    (s',"") -> [s']
+    (s',r)  -> s' : split c (tail r)
+
+getCertificateStore :: [FilePath] -> IO CertificateStore
+getCertificateStore []    = getSystemCertificateStore
+getCertificateStore paths = foldM readPathAppend mempty paths
+  where
+    readPathAppend acc path = do
+        mstore <- readCertificateStore path
+        case mstore of
+            Nothing -> error ("invalid certificate store: " ++ path)
+            Just st -> return $! mappend st acc
diff --git a/src/HexDump.hs b/src/HexDump.hs
--- a/src/HexDump.hs
+++ b/src/HexDump.hs
@@ -2,11 +2,11 @@
     ( hexdump
     ) where
 
-import Data.List
-import Data.Word
 import qualified Data.ByteString as B
 
-hexdump :: String -> B.ByteString -> [String]
+import Imports
+
+hexdump :: String -> ByteString -> [String]
 hexdump pre b = disptable (defaultConfig { configRowLeft = pre ++ "  | " } ) $ B.unpack b
 
 data BytedumpConfig = BytedumpConfig
diff --git a/src/Imports.hs b/src/Imports.hs
new file mode 100644
--- /dev/null
+++ b/src/Imports.hs
@@ -0,0 +1,17 @@
+module Imports (
+    ByteString
+  , module Control.Applicative
+  , module Control.Monad
+  , module Data.List
+  , module Data.Maybe
+  , module Data.Monoid
+  , module Data.Word
+  ) where
+
+import Control.Applicative
+import Control.Monad
+import Data.ByteString (ByteString)
+import Data.List
+import Data.Maybe
+import Data.Monoid
+import Data.Word
diff --git a/src/RetrieveCertificate.hs b/src/RetrieveCertificate.hs
--- a/src/RetrieveCertificate.hs
+++ b/src/RetrieveCertificate.hs
@@ -1,33 +1,25 @@
 {-# LANGUAGE DeriveDataTypeable, ViewPatterns #-}
 {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
 
-import Network.TLS
-import Network.TLS.Extra.Cipher
-
-import Network.BSD
-import Network.Socket
-
+import Control.Exception
+import qualified Data.ByteString.Char8 as B
 import Data.Default.Class
 import Data.IORef
+import Data.PEM
 import Data.X509 as X509
 import Data.X509.Validation
-import System.X509
-
-import Control.Applicative
-import Control.Monad
-import Control.Exception
-
-import Data.Char (isDigit)
-import Data.PEM
-
-import Text.Printf
-
+import Network.Socket
 import System.Console.GetOpt
 import System.Environment
 import System.Exit
+import System.X509
+import Text.Printf
 
-import qualified Data.ByteString.Char8 as B
+import Network.TLS
+import Network.TLS.Extra.Cipher
 
+import Imports
+
 openConnection s p = do
     ref <- newIORef Nothing
     let params = (defaultParamsClient s (B.pack p))
@@ -36,13 +28,11 @@
                     }
 
     --ctx <- connectionClient s p params rng
-    pn <- if and $ map isDigit $ p
-            then return $ fromIntegral $ (read p :: Int)
-            else servicePort <$> getServiceByName p "tcp"
-    he <- getHostByName s
+    let hints = defaultHints { addrSocketType = Stream }
+    addr:_ <- getAddrInfo (Just hints) (Just s) (Just p)
 
-    sock <- bracketOnError (socket AF_INET Stream defaultProtocol) close $ \sock -> do
-            connect sock (SockAddrInet pn (head $ hostAddresses he))
+    sock <- bracketOnError (socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)) close $ \sock -> do
+            connect sock $ addrAddress addr
             return sock
     ctx <- contextNew sock params
 
diff --git a/src/SimpleClient.hs b/src/SimpleClient.hs
--- a/src/SimpleClient.hs
+++ b/src/SimpleClient.hs
@@ -1,47 +1,38 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+
+import Control.Exception (SomeException(..))
+import qualified Control.Exception as E
 import Crypto.Random
-import Network.BSD
-import Network.Socket (socket, Family(..), SocketType(..), close, SockAddr(..), connect)
-import Network.TLS
-import Network.TLS.Extra.Cipher
-import System.Console.GetOpt
-import System.IO
-import System.Timeout
-import qualified Data.ByteString.Lazy.Char8 as LC
-import qualified Data.ByteString.Char8 as BC
 import qualified Data.ByteString as B
-import Control.Exception
-import qualified Control.Exception as E
-import Control.Monad
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy.Char8 as LC
+import Data.Default.Class
+import Data.IORef
+import Network.Socket (socket, close, connect)
+import System.Console.GetOpt
 import System.Environment
 import System.Exit
-import System.X509
+import System.IO
+import System.Timeout
 
-import Data.Default.Class
-import Data.IORef
-import Data.Monoid
-import Data.List (find)
-import Data.Maybe (isJust, mapMaybe)
+import Network.TLS
+import Network.TLS.Extra.Cipher
 
 import Common
 import HexDump
+import Imports
 
 defaultBenchAmount = 1024 * 1024
 defaultTimeout = 2000
 
 bogusCipher cid = cipher_AES128_SHA1 { cipherID = cid }
 
-runTLS debug ioDebug params hostname portNumber f = do
-    he   <- getHostByName hostname
-    sock <- socket AF_INET Stream defaultProtocol
-    let sockaddr = SockAddrInet portNumber (head $ hostAddresses he)
-    E.catch (connect sock sockaddr)
-          (\(SomeException e) -> close sock >> error ("cannot open socket " ++ show sockaddr ++ " " ++ show e))
-    ctx <- contextNew sock params
-    contextHookSetLogging ctx getLogging
-    () <- f ctx
-    close sock
+runTLS debug ioDebug params hostname portNumber f =
+    E.bracket setup teardown $ \sock -> do
+        ctx <- contextNew sock params
+        contextHookSetLogging ctx getLogging
+        f ctx
   where getLogging = ioLogging $ packetLogging $ def
         packetLogging logging
             | debug = logging { loggingPacketSent = putStrLn . ("debug: >> " ++)
@@ -55,29 +46,40 @@
                                     mapM_ putStrLn $ hexdump "<<" body
                                 }
             | otherwise = logging
+        setup = do
+            ai <- makeAddrInfo (Just hostname) portNumber
+            sock <- socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai)
+            let sockaddr = addrAddress ai
+            connect sock sockaddr
+            return sock
+        teardown sock = close sock
 
 sessionRef ref = SessionManager
-    { sessionEstablish  = \sid sdata -> writeIORef ref (sid,sdata)
-    , sessionResume     = \sid       -> readIORef ref >>= \(s,d) -> if s == sid then return (Just d) else return Nothing
-    , sessionInvalidate = \_         -> return ()
+    { sessionEstablish      = \sid sdata -> writeIORef ref (sid,sdata)
+    , sessionResume         = \sid       -> readIORef ref >>= \(s,d) -> if s == sid then return (Just d) else return Nothing
+    , sessionResumeOnlyOnce = \_         -> fail "sessionResumeOnlyOnce not implemented for simple client"
+    , sessionInvalidate     = \_         -> return ()
     }
 
-getDefaultParams flags host store sStorage certCredsRequest session =
+getDefaultParams flags host store sStorage certCredsRequest session earlyData =
     (defaultParamsClient serverName BC.empty)
-        { clientSupported = def { supportedVersions = supportedVers, supportedCiphers = myCiphers }
+        { clientSupported = def { supportedVersions = supportedVers
+                                , supportedCiphers = myCiphers
+                                , supportedGroups = getGroups flags
+                                }
         , clientWantSessionResume = session
-        , clientUseServerNameIndication = not (NoSNI `elem` flags)
+        , clientUseServerNameIndication = NoSNI `notElem` flags
         , clientShared = def { sharedSessionManager  = sessionRef sStorage
                              , sharedCAStore         = store
                              , sharedValidationCache = validateCache
-                             , sharedCredentials     = maybe mempty fst certCredsRequest
                              }
-        , clientHooks = def { onCertificateRequest = maybe (onCertificateRequest def) snd certCredsRequest }
+        , clientHooks = def { onCertificateRequest = fromMaybe (onCertificateRequest def) certCredsRequest }
         , clientDebug = def { debugSeed      = foldl getDebugSeed Nothing flags
                             , debugPrintSeed = if DebugPrintSeed `elem` flags
                                                     then (\seed -> putStrLn ("seed: " ++ show (seedToInteger seed)))
                                                     else (\_ -> return ())
                             }
+        , clientEarlyData = earlyData
         }
     where
             serverName = foldl f host flags
@@ -112,6 +114,7 @@
             getDebugSeed acc _                = acc
 
             tlsConnectVer
+                | Tls13 `elem` flags = TLS13
                 | Tls12 `elem` flags = TLS12
                 | Tls11 `elem` flags = TLS11
                 | Ssl3  `elem` flags = SSL3
@@ -120,28 +123,43 @@
             supportedVers
                 | NoVersionDowngrade `elem` flags = [tlsConnectVer]
                 | otherwise = filter (<= tlsConnectVer) allVers
-            allVers = [SSL3, TLS10, TLS11, TLS12]
+            allVers = [SSL3, TLS10, TLS11, TLS12, TLS13]
             validateCert = not (NoValidateCert `elem` flags)
 
+getGroups flags = case getGroup >>= readGroups of
+    Nothing     -> defaultGroups
+    Just []     -> defaultGroups
+    Just groups -> groups
+  where
+    defaultGroups = supportedGroups def
+    getGroup = foldl f Nothing flags
+      where f _   (Group g)  = Just g
+            f acc _          = acc
+
 data Flag = Verbose | Debug | IODebug | NoValidateCert | Session | Http11
-          | Ssl3 | Tls10 | Tls11 | Tls12
+          | Ssl3 | Tls10 | Tls11 | Tls12 | Tls13
           | SNI String
           | NoSNI
           | Uri String
           | NoVersionDowngrade
           | UserAgent String
+          | Input String
           | Output String
           | Timeout String
           | BogusCipher String
           | ClientCert String
+          | TrustAnchor String
           | BenchSend
           | BenchRecv
           | BenchData String
           | UseCipher String
           | ListCiphers
+          | ListGroups
           | DebugSeed String
           | DebugPrintSeed
+          | Group String
           | Help
+          | UpdateKey
           deriving (Show,Eq)
 
 options :: [OptDescr Flag]
@@ -150,10 +168,14 @@
     , Option ['d']  ["debug"]   (NoArg Debug) "TLS debug output on stdout"
     , Option []     ["io-debug"] (NoArg IODebug) "TLS IO debug output on stdout"
     , Option ['s']  ["session"] (NoArg Session) "try to resume a session"
+    , Option ['Z']  ["zerortt"]  (ReqArg Input "inpfile") "input for TLS 1.3 0RTT data"
     , Option ['O']  ["output"]  (ReqArg Output "stdout") "output "
+    , Option ['g']  ["group"]  (ReqArg Group "group") "group"
     , Option ['t']  ["timeout"] (ReqArg Timeout "timeout") "timeout in milliseconds (2s by default)"
+    , Option ['u']  ["update-key"]   (NoArg UpdateKey) "Updating keys after sending the first request then sending the same request again (TLS 1.3 only)"
     , Option []     ["no-validation"] (NoArg NoValidateCert) "disable certificate validation"
     , Option []     ["client-cert"] (ReqArg ClientCert "cert-file:key-file") "add a client certificate to use with the server"
+    , Option []     ["trust-anchor"] (ReqArg TrustAnchor "pem-or-dir") "use provided CAs instead of system certificate store"
     , Option []     ["http1.1"] (NoArg Http11) "use http1.1 instead of http1.0"
     , Option []     ["ssl3"]    (NoArg Ssl3) "use SSL 3.0"
     , Option []     ["sni"]     (ReqArg SNI "server-name") "use non-default server name indication"
@@ -162,6 +184,7 @@
     , Option []     ["tls10"]   (NoArg Tls10) "use TLS 1.0"
     , Option []     ["tls11"]   (NoArg Tls11) "use TLS 1.1"
     , Option []     ["tls12"]   (NoArg Tls12) "use TLS 1.2 (default)"
+    , Option []     ["tls13"]   (NoArg Tls13) "use TLS 1.3"
     , Option []     ["bogocipher"] (ReqArg BogusCipher "cipher-id") "add a bogus cipher id for testing"
     , Option ['x']  ["no-version-downgrade"] (NoArg NoVersionDowngrade) "do not allow version downgrade"
     , Option []     ["uri"]     (ReqArg Uri "URI") "optional URI requested by default /"
@@ -171,6 +194,7 @@
     , Option []     ["bench-data"] (ReqArg BenchData "amount") "amount of data to benchmark with"
     , Option []     ["use-cipher"] (ReqArg UseCipher "cipher-id") "use a specific cipher"
     , Option []     ["list-ciphers"] (NoArg ListCiphers) "list all ciphers supported and exit"
+    , Option []     ["list-groups"] (NoArg ListGroups) "list all groups supported and exit"
     , Option []     ["debug-seed"] (ReqArg DebugSeed "debug-seed") "debug: set a specific seed for randomness"
     , Option []     ["debug-print-seed"] (NoArg DebugPrintSeed) "debug: set a specific seed for randomness"
     ]
@@ -182,15 +206,19 @@
     | BenchRecv `elem` flags = runBench False
     | otherwise              = do
         certCredRequest <- getCredRequest
-        doTLS certCredRequest noSession
+        doTLS certCredRequest noSession Nothing `E.catch` \(SomeException e) -> print e
         when (Session `elem` flags) $ do
+            putStrLn "\nResuming the session..."
             session <- readIORef sStorage
-            doTLS certCredRequest (Just session)
+            earlyData <- case getInput of
+              Nothing -> return Nothing
+              Just i  -> Just <$> B.readFile i
+            doTLS certCredRequest (Just session) earlyData `E.catch` \(SomeException e) -> print e
   where
         runBench isSend =
             runTLS (Debug `elem` flags)
                    (IODebug `elem` flags)
-                   (getDefaultParams flags hostname certStore sStorage Nothing noSession) hostname port $ \ctx -> do
+                   (getDefaultParams flags hostname certStore sStorage Nothing noSession Nothing) hostname port $ \ctx -> do
                 handshake ctx
                 if isSend
                     then loopSendData getBenchAmount ctx
@@ -210,7 +238,7 @@
                     d <- recvData ctx
                     loopRecvData (bytes - B.length d) ctx
 
-        doTLS certCredRequest sess = do
+        doTLS certCredRequest sess earlyData = E.bracket setup teardown $ \out -> do
             let query = LC.pack (
                         "GET "
                         ++ findURI flags
@@ -218,17 +246,30 @@
                         ++ userAgent
                         ++ "\r\n\r\n")
             when (Verbose `elem` flags) (putStrLn "sending query:" >> LC.putStrLn query >> putStrLn "")
-            out <- maybe (return stdout) (flip openFile AppendMode) getOutput
             runTLS (Debug `elem` flags)
                    (IODebug `elem` flags)
-                   (getDefaultParams flags hostname certStore sStorage certCredRequest sess) hostname port $ \ctx -> do
+                   (getDefaultParams flags hostname certStore sStorage certCredRequest sess earlyData) hostname port $ \ctx -> do
                 handshake ctx
                 when (Verbose `elem` flags) $ printHandshakeInfo ctx
+                case earlyData of
+                    Just edata -> do
+                        minfo <- contextGetInformation ctx
+                        case minfo of
+                            Nothing -> return () -- what should we do?
+                            Just info -> unless (infoIsEarlyDataAccepted info) $ do
+                                putStrLn "Resending 0RTT data ..."
+                                sendData ctx $ LC.fromStrict edata
+                    _ -> return ()
                 sendData ctx $ query
                 loopRecv out ctx
-                bye ctx `catch` \(SomeException e) -> putStrLn $ "bye failed: " ++ show e
+                when (UpdateKey `elem` flags) $ do
+                    _tls13 <- updateKey ctx TwoWay
+                    sendData ctx $ query
+                    loopRecv out ctx
+                bye ctx `E.catch` \(SomeException e) -> putStrLn $ "bye failed: " ++ show e
                 return ()
-            when (isJust getOutput) $ hClose out
+        setup = maybe (return stdout) (flip openFile AppendMode) getOutput
+        teardown out = when (isJust getOutput) $ hClose out
         loopRecv out ctx = do
             d <- timeout (timeoutMs * 1000) (recvData ctx) -- 2s per recv
             case d of
@@ -239,7 +280,7 @@
         getCredRequest =
             case clientCert of
                 Nothing -> return Nothing
-                Just s  -> do
+                Just s  ->
                     case break (== ':') s of
                         (_   ,"")      -> error "wrong format for client-cert, expecting 'cert-file:key-file'"
                         (cert,':':key) -> do
@@ -248,7 +289,7 @@
                                 Left err   -> error ("cannot load client certificate: " ++ err)
                                 Right cred -> do
                                     let certRequest _ = return $ Just cred
-                                    return $ Just (Credentials [cred], certRequest)
+                                    return $ Just certRequest
                         (_   ,_)      -> error "wrong format for client-cert, expecting 'cert-file:key-file'"
 
         findURI []        = "/"
@@ -259,6 +300,9 @@
         mUserAgent = foldl f Nothing flags
           where f _   (UserAgent ua) = Just ua
                 f acc _              = acc
+        getInput = foldl f Nothing flags
+          where f _   (Input i)  = Just i
+                f acc _          = acc
         getOutput = foldl f Nothing flags
           where f _   (Output o) = Just o
                 f acc _          = acc
@@ -274,6 +318,10 @@
                                             Just i  -> i
                 f acc _              = acc
 
+getTrustAnchors flags = getCertificateStore (foldr getPaths [] flags)
+  where getPaths (TrustAnchor path) acc = path : acc
+        getPaths _                  acc = acc
+
 printUsage =
     putStrLn $ usageInfo "usage: simpleclient [opts] <hostname> [port]\n\n\t(port default to: 443)\noptions:\n" options
 
@@ -292,7 +340,11 @@
         printCiphers
         exitSuccess
 
-    certStore <- getSystemCertificateStore
+    when (ListGroups `elem` opts) $ do
+        printGroups
+        exitSuccess
+
+    certStore <- getTrustAnchors opts
     sStorage <- newIORef (error "storage ioref undefined")
     case other of
         [hostname]      -> runOn (sStorage, certStore) opts 443 hostname
diff --git a/src/SimpleServer.hs b/src/SimpleServer.hs
--- a/src/SimpleServer.hs
+++ b/src/SimpleServer.hs
@@ -1,32 +1,30 @@
 {-# LANGUAGE OverloadedStrings #-}
 -- Disable this warning so we can still test deprecated functionality.
 {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
+
+import Control.Concurrent
+import qualified Control.Exception as E
 import Crypto.Random
-import Network.BSD
-import Network.Socket (socket, Family(..), SocketType(..), close, SockAddr(..), bind, listen, accept, iNADDR_ANY)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Lazy.Char8 as LC
+import Data.Default.Class
+import Data.X509.CertificateStore
+import Network.Socket (socket, close, bind, listen, accept)
 import qualified Network.Socket as S
-import Network.TLS
-import Network.TLS.Extra.Cipher
+import Network.TLS.SessionManager
 import System.Console.GetOpt
-import System.IO
-import System.Timeout
-import qualified Data.ByteString.Lazy.Char8 as LC
-import qualified Data.ByteString.Char8 as BC
-import qualified Data.ByteString as B
-import Control.Monad
 import System.Environment
 import System.Exit
-import System.X509
-import Data.X509.CertificateStore
+import System.IO
+import System.Timeout
 
-import Data.Default.Class
-import Data.IORef
-import Data.Monoid
-import Data.List (find)
-import Data.Maybe (isJust, mapMaybe)
+import Network.TLS
+import Network.TLS.Extra.Cipher
 
 import Common
 import HexDump
+import Imports
 
 defaultBenchAmount = 1024 * 1024
 defaultTimeout = 2000
@@ -51,14 +49,8 @@
                                 }
             | otherwise = logging
 
-sessionRef ref = SessionManager
-    { sessionEstablish  = \sid sdata -> writeIORef ref (sid,sdata)
-    , sessionResume     = \sid       -> readIORef ref >>= \(s,d) -> if s == sid then return (Just d) else return Nothing
-    , sessionInvalidate = \_         -> return ()
-    }
-
-getDefaultParams :: [Flag] -> CertificateStore -> IORef (SessionID, SessionData) -> Credential -> IO ServerParams
-getDefaultParams flags store sStorage cred = do
+getDefaultParams :: [Flag] -> CertificateStore -> SessionManager -> Credential -> Bool -> IO ServerParams
+getDefaultParams flags store smgr cred rtt0accept = do
     dhParams <- case getDHParams flags of
         Nothing   -> return Nothing
         Just name -> readDHParams name
@@ -67,7 +59,7 @@
         { serverWantClientCert = False
         , serverCACertificates = []
         , serverDHEParams = dhParams
-        , serverShared = def { sharedSessionManager  = sessionRef sStorage
+        , serverShared = def { sharedSessionManager  = smgr
                              , sharedCAStore         = store
                              , sharedValidationCache = validateCache
                              , sharedCredentials     = Credentials [cred]
@@ -75,12 +67,15 @@
         , serverHooks = def
         , serverSupported = def { supportedVersions = supportedVers
                                 , supportedCiphers = myCiphers
-                                , supportedClientInitiatedRenegotiation = allowRenegotiation }
+                                , supportedGroups = getGroups flags
+                                , supportedClientInitiatedRenegotiation = allowRenegotiation
+                                }
         , serverDebug = def { debugSeed      = foldl getDebugSeed Nothing flags
                             , debugPrintSeed = if DebugPrintSeed `elem` flags
                                                     then (\seed -> putStrLn ("seed: " ++ show (seedToInteger seed)))
                                                     else (\_ -> return ())
                             }
+        , serverEarlyDataSize = if rtt0accept then 2048 else 0
         }
     where
             validateCache
@@ -116,6 +111,7 @@
             getDebugSeed acc _                = acc
 
             tlsConnectVer
+                | Tls13 `elem` flags = TLS13
                 | Tls12 `elem` flags = TLS12
                 | Tls11 `elem` flags = TLS11
                 | Ssl3  `elem` flags = SSL3
@@ -124,28 +120,42 @@
             supportedVers
                 | NoVersionDowngrade `elem` flags = [tlsConnectVer]
                 | otherwise = filter (<= tlsConnectVer) allVers
-            allVers = [SSL3, TLS10, TLS11, TLS12]
+            allVers = [SSL3, TLS10, TLS11, TLS12, TLS13]
             validateCert = not (NoValidateCert `elem` flags)
             allowRenegotiation = AllowRenegotiation `elem` flags
 
-data Flag = Verbose | Debug | IODebug | NoValidateCert | Session | Http11
-          | Ssl3 | Tls10 | Tls11 | Tls12
+getGroups flags = case getGroup >>= readGroups of
+    Nothing     -> defaultGroups
+    Just []     -> defaultGroups
+    Just groups -> groups
+  where
+    defaultGroups = supportedGroups def
+    getGroup = foldl f Nothing flags
+      where f _   (Group g)  = Just g
+            f acc _          = acc
+
+data Flag = Verbose | Debug | IODebug | NoValidateCert | Http11
+          | Ssl3 | Tls10 | Tls11 | Tls12 | Tls13
           | NoVersionDowngrade
           | AllowRenegotiation
           | Output String
           | Timeout String
           | BogusCipher String
+          | TrustAnchor String
           | BenchSend
           | BenchRecv
           | BenchData String
           | UseCipher String
           | ListCiphers
+          | ListGroups
           | ListDHParams
           | Certificate String
           | Key String
           | DHParams String
+          | Rtt0
           | DebugSeed String
           | DebugPrintSeed
+          | Group String
           | Help
           deriving (Show,Eq)
 
@@ -154,15 +164,18 @@
     [ Option ['v']  ["verbose"] (NoArg Verbose) "verbose output on stdout"
     , Option ['d']  ["debug"]   (NoArg Debug) "TLS debug output on stdout"
     , Option []     ["io-debug"] (NoArg IODebug) "TLS IO debug output on stdout"
-    , Option ['s']  ["session"] (NoArg Session) "try to resume a session"
+    , Option ['Z']  ["zerortt"] (NoArg Rtt0) "accept TLS 1.3 0RTT data"
     , Option ['O']  ["output"]  (ReqArg Output "stdout") "output "
+    , Option ['g']  ["group"]  (ReqArg Group "group") "group"
     , Option ['t']  ["timeout"] (ReqArg Timeout "timeout") "timeout in milliseconds (2s by default)"
     , Option []     ["no-validation"] (NoArg NoValidateCert) "disable certificate validation"
+    , Option []     ["trust-anchor"] (ReqArg TrustAnchor "pem-or-dir") "use provided CAs instead of system certificate store"
     , Option []     ["http1.1"] (NoArg Http11) "use http1.1 instead of http1.0"
     , Option []     ["ssl3"]    (NoArg Ssl3) "use SSL 3.0"
     , Option []     ["tls10"]   (NoArg Tls10) "use TLS 1.0"
     , Option []     ["tls11"]   (NoArg Tls11) "use TLS 1.1"
     , Option []     ["tls12"]   (NoArg Tls12) "use TLS 1.2 (default)"
+    , Option []     ["tls13"]   (NoArg Tls13) "use TLS 1.3"
     , Option []     ["bogocipher"] (ReqArg BogusCipher "cipher-id") "add a bogus cipher id for testing"
     , Option ['x']  ["no-version-downgrade"] (NoArg NoVersionDowngrade) "do not allow version downgrade"
     , Option []     ["allow-renegotiation"] (NoArg AllowRenegotiation) "allow client-initiated renegotiation"
@@ -172,6 +185,7 @@
     , Option []     ["bench-data"] (ReqArg BenchData "amount") "amount of data to benchmark with"
     , Option []     ["use-cipher"] (ReqArg UseCipher "cipher-id") "use a specific cipher"
     , Option []     ["list-ciphers"] (NoArg ListCiphers) "list all ciphers supported and exit"
+    , Option []     ["list-groups"] (NoArg ListGroups) "list all groups supported and exit"
     , Option []     ["list-dhparams"] (NoArg ListDHParams) "list all DH parameters supported and exit"
     , Option []     ["certificate"] (ReqArg Certificate "certificate") "certificate file"
     , Option []     ["debug-seed"] (ReqArg DebugSeed "debug-seed") "debug: set a specific seed for randomness"
@@ -191,9 +205,10 @@
     error "missing credential certificate"
 
 runOn (sStorage, certStore) flags port = do
-    sock <- socket AF_INET Stream defaultProtocol
+    ai <- makeAddrInfo Nothing port
+    sock <- socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai)
     S.setSocketOption sock S.ReuseAddr 1
-    let sockaddr = SockAddrInet port iNADDR_ANY
+    let sockaddr = addrAddress ai
     bind sock sockaddr
     listen sock 10
     runOn' sock
@@ -204,13 +219,14 @@
           | BenchRecv `elem` flags = runBench False sock
           | otherwise              = do
               --certCredRequest <- getCredRequest
-              doTLS sock
-              when (Session `elem` flags) $ doTLS sock
+              E.bracket (maybe (return stdout) (flip openFile AppendMode) getOutput)
+                        (\out -> when (isJust getOutput) $ hClose out)
+                        (doTLS sock)
         runBench isSend sock = do
             (cSock, cAddr) <- accept sock
             putStrLn ("connection from " ++ show cAddr)
             cred <- loadCred getKey getCertificate
-            params <- getDefaultParams flags certStore sStorage cred
+            params <- getDefaultParams flags certStore sStorage cred False
             runTLS False False params cSock $ \ctx -> do
                 handshake ctx
                 if isSend
@@ -232,25 +248,27 @@
                     d <- recvData ctx
                     loopRecvData (bytes - B.length d) ctx
 
-        doTLS sock = do
+        doTLS sock out = do
             (cSock, cAddr) <- accept sock
             putStrLn ("connection from " ++ show cAddr)
-            out <- maybe (return stdout) (flip openFile AppendMode) getOutput
 
             cred <- loadCred getKey getCertificate
-            params <- getDefaultParams flags certStore sStorage cred
+            let rtt0accept = Rtt0 `elem` flags
+            params <- getDefaultParams flags certStore sStorage cred rtt0accept
 
-            runTLS (Debug `elem` flags)
-                   (IODebug `elem` flags)
-                   params cSock $ \ctx -> do
-                handshake ctx
-                when (Verbose `elem` flags) $ printHandshakeInfo ctx
-                loopRecv out ctx
-                --sendData ctx $ query
-                bye ctx
-                return ()
-            close cSock
-            when (isJust getOutput) $ hClose out
+            void $ forkIO $ do
+                runTLS (Debug `elem` flags)
+                       (IODebug `elem` flags)
+                       params cSock $ \ctx -> do
+                    handshake ctx
+                    when (Verbose `elem` flags) $ printHandshakeInfo ctx
+                    loopRecv out ctx
+                    --sendData ctx $ query
+                    bye ctx
+                    return ()
+                close cSock
+            doTLS sock out
+
         loopRecv out ctx = do
             d <- timeout (timeoutMs * 1000) (recvData ctx) -- 2s per recv
             case d of
@@ -293,6 +311,10 @@
                                             Just i  -> i
                 f acc _              = acc
 
+getTrustAnchors flags = getCertificateStore (foldr getPaths [] flags)
+  where getPaths (TrustAnchor path) acc = path : acc
+        getPaths _                  acc = acc
+
 printUsage =
     putStrLn $ usageInfo "usage: simpleserver [opts] [port]\n\n\t(port default to: 443)\noptions:\n" options
 
@@ -315,8 +337,12 @@
         printDHParams
         exitSuccess
 
-    certStore <- getSystemCertificateStore
-    sStorage  <- newIORef (error "storage ioref undefined")
+    when (ListGroups `elem` opts) $ do
+        printGroups
+        exitSuccess
+
+    certStore <- getTrustAnchors opts
+    sStorage  <- newSessionManager defaultConfig
     case other of
         []     -> runOn (sStorage, certStore) opts 443
         [port] -> runOn (sStorage, certStore) opts (fromInteger $ read port)
diff --git a/src/Stunnel.hs b/src/Stunnel.hs
--- a/src/Stunnel.hs
+++ b/src/Stunnel.hs
@@ -1,34 +1,27 @@
-{-# LANGUAGE DeriveDataTypeable #-}
 -- Disable this warning so we can still test deprecated functionality.
 {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
-import Network.BSD
-import Network.Socket hiding (Debug)
-import System.IO
-import System.IO.Error (isEOFError)
-import System.Console.GetOpt
-import System.Environment (getArgs)
-import System.Exit
-import System.X509
-import Data.X509.Validation
 
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
-
 import Control.Concurrent (forkIO)
-import Control.Concurrent.MVar
 import Control.Exception (finally, throw, SomeException(..))
 import qualified Control.Exception as E
-import Control.Monad (when, forever)
-
-import Data.Char (isDigit)
+import qualified Crypto.PubKey.DH as DH ()
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
 import Data.Default.Class
+import Data.X509.Validation
+import Network.Socket hiding (Debug)
+import Network.TLS.SessionManager
+import System.Console.GetOpt
+import System.Environment (getArgs)
+import System.Exit
+import System.IO
+import System.IO.Error (isEOFError)
 
 import Network.TLS
 import Network.TLS.Extra.Cipher
 
-import qualified Crypto.PubKey.DH as DH ()
-
 import Common
+import Imports
 
 loopUntil :: Monad m => m Bool -> m ()
 loopUntil f = f >>= \v -> if v then return () else loopUntil f
@@ -74,15 +67,7 @@
         return False
     putStrLn "end"
 
-newtype MemSessionManager = MemSessionManager (MVar [(SessionID, SessionData)])
-
-memSessionManager (MemSessionManager mvar) = SessionManager
-    { sessionEstablish  = \sid sdata -> modifyMVar_ mvar (\l -> return $ (sid,sdata) : l)
-    , sessionResume     = \sid       -> withMVar mvar (return . lookup sid)
-    , sessionInvalidate = \_         -> return ()
-    }
-
-clientProcess dhParamsFile creds handle dsthandle dbg sessionStorage _ = do
+clientProcess dhParamsFile creds handle dsthandle dbg sessionManager _ = do
     let logging = if not dbg
             then def
             else def { loggingPacketSent = putStrLn . ("debug: send: " ++)
@@ -96,7 +81,7 @@
     let serverstate = def
             { serverSupported = def { supportedCiphers = ciphersuite_default }
             , serverShared    = def { sharedCredentials = creds
-                                    , sharedSessionManager = maybe noSessionManager (memSessionManager . MemSessionManager) sessionStorage
+                                    , sharedSessionManager = sessionManager
                                     }
             , serverDHEParams = dhParams
             }
@@ -117,13 +102,8 @@
 getAddressDescription (Address "tcp" desc) = do
     let (s, p) = break ((==) ':') desc
     when (p == "") (error $ "missing port: expecting [source]:port got " ++ show desc)
-    pn <- if and $ map isDigit $ drop 1 p
-        then return $ fromIntegral $ (read (drop 1 p) :: Int)
-        else do
-            service <- getServiceByName (drop 1 p) "tcp"
-            return $ servicePort service
-    he <- getHostByName s
-    return $ AddrSocket AF_INET (SockAddrInet pn (head $ hostAddresses he))
+    addr:_ <- getAddrInfo Nothing (Just s) (Just $ drop 1 p)
+    return $ AddrSocket (addrFamily addr) (addrAddress addr)
 
 getAddressDescription (Address "unix" desc) = do
     return $ AddrSocket AF_UNIX (SockAddrUnix desc)
@@ -163,7 +143,7 @@
                          , loggingPacketRecv = putStrLn . ("debug: recv: " ++)
                          }
 
-    store <- getSystemCertificateStore
+    store <- getTrustAnchors flags
     let validateCache
            | NoCertValidation `elem` flags =
                 ValidationCache (\_ _ _ -> return ValidationCachePass)
@@ -208,7 +188,10 @@
     dstaddr <- getAddressDescription destination
     let dhParamsFile = getDHParams flags
 
-    sessionStorage <- if NoSession `elem` flags then return Nothing else (Just `fmap` newMVar [])
+    sessionManager <-
+        if NoSession `elem` flags
+            then return noSessionManager
+            else newSessionManager defaultConfig
 
     case srcaddr of
         AddrSocket _ _ -> do
@@ -222,7 +205,7 @@
                     StunnelSocket dst -> socketToHandle dst ReadWriteMode
 
                 _ <- forkIO $ finally
-                    (clientProcess dhParamsFile creds srch dsth (Debug `elem` flags) sessionStorage addr >> return ())
+                    (clientProcess dhParamsFile creds srch dsth (Debug `elem` flags) sessionManager addr >> return ())
                     (hClose srch >> (when (dsth /= stdout) $ hClose dsth))
                 return ()
         AddrFD _ _ -> error "bad error fd. not implemented"
@@ -243,6 +226,7 @@
     | DHParams String
     | NoSession
     | NoCertValidation
+    | TrustAnchor String
     deriving (Show,Eq)
 
 options :: [OptDescr Flag]
@@ -259,6 +243,7 @@
     , Option []     ["dhparams"] (ReqArg DHParams "dhparams") "DH parameters (name or file)"
     , Option []     ["no-session"] (NoArg NoSession) "disable support for session"
     , Option []     ["no-cert-validation"] (NoArg NoCertValidation) "disable certificate validation"
+    , Option []     ["trust-anchor"] (ReqArg TrustAnchor "pem-or-dir") "use provided CAs instead of system certificate store"
     ]
 
 data Address = Address String String
@@ -288,6 +273,10 @@
 getKey opts = reverse $ onNull ["certificate.key"] $ foldl accf [] opts
   where accf acc (Key key) = key : acc
         accf acc _         = acc
+
+getTrustAnchors flags = getCertificateStore (foldr getPaths [] flags)
+  where getPaths (TrustAnchor path) acc = path : acc
+        getPaths _                  acc = acc
 
 getDHParams opts = foldl accf Nothing opts
   where accf _   (DHParams file) = Just file
diff --git a/tls-debug.cabal b/tls-debug.cabal
--- a/tls-debug.cabal
+++ b/tls-debug.cabal
@@ -1,5 +1,5 @@
 Name:                tls-debug
-Version:             0.4.5
+Version:             0.4.6
 Description:
    A set of program to test and debug various aspect of the TLS package.
    .
@@ -18,14 +18,18 @@
 Executable           tls-stunnel
   Main-is:           Stunnel.hs
   Other-modules:     Common
+                   , Imports
   Hs-Source-Dirs:    src
   Build-Depends:     base >= 4 && < 5
                    , network
                    , bytestring
+                   , x509-store
                    , x509-system >= 1.0
+                   , x509-validation >= 1.5
                    , data-default-class
                    , cryptonite >= 0.24
-                   , tls >= 1.3.0 && < 1.5
+                   , tls >= 1.5.0
+                   , tls-session-manager
   if os(windows)
     Buildable:       False
   else
@@ -40,23 +44,23 @@
 --                    , bytestring
 --                    , cprng-aes
 --                    , x509-system >= 1.0
---                    , tls >= 1.2 && < 1.3
+--                    , tls >= 1.2 && < 1.6
 --   Buildable:         True
 --   ghc-options:       -Wall -fno-warn-missing-signatures
 
 Executable           tls-retrievecertificate
   Main-is:           RetrieveCertificate.hs
+  Other-modules:     Imports
   Hs-Source-Dirs:    src
   Build-Depends:     base >= 4 && < 5
                    , network
                    , bytestring
-                   , time
                    , pem
-                   , cryptonite
                    , x509
                    , x509-system >= 1.4
-                   , x509-validation >= 1.5.0
-                   , tls >= 1.3 && < 1.5
+                   , x509-validation >= 1.5
+                   , data-default-class
+                   , tls >= 1.3 && < 1.6
   Buildable:         True
   ghc-options:       -Wall -fno-warn-missing-signatures
 
@@ -64,14 +68,16 @@
   Main-is:           SimpleClient.hs
   Other-modules:     Common
                    , HexDump
+                   , Imports
   Hs-Source-Dirs:    src
   Build-Depends:     base >= 4 && < 5
                    , network
                    , bytestring
                    , data-default-class
                    , cryptonite >= 0.14
+                   , x509-store
                    , x509-system >= 1.0
-                   , tls >= 1.3.6 && < 1.5
+                   , tls >= 1.5.0 && < 1.6
   Buildable:         True
   ghc-options:       -Wall -fno-warn-missing-signatures
 
@@ -79,6 +85,7 @@
   Main-is:           SimpleServer.hs
   Other-modules:     Common
                    , HexDump
+                   , Imports
   Hs-Source-Dirs:    src
   Build-Depends:     base >= 4 && < 5
                    , network
@@ -87,7 +94,8 @@
                    , cryptonite
                    , x509-store
                    , x509-system >= 1.0
-                   , tls >= 1.3 && < 1.5
+                   , tls >= 1.5.0 && < 1.6
+                   , tls-session-manager
   Buildable:         True
   ghc-options:       -Wall -fno-warn-missing-signatures
 
