Hello community,

here is the log from the commit of package ghc-tls for openSUSE:Factory checked 
in at 2017-02-01 09:52:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-tls (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-tls.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-tls"

Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-tls/ghc-tls.changes  2016-07-20 
09:20:15.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-tls.new/ghc-tls.changes     2017-02-03 
17:40:18.222598923 +0100
@@ -1,0 +2,5 @@
+Wed Jan 18 09:00:21 UTC 2017 - [email protected]
+
+- Update to version 1.3.9 with cabal2obs.
+
+-------------------------------------------------------------------

Old:
----
  tls-1.3.8.tar.gz

New:
----
  tls-1.3.9.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-tls.spec ++++++
--- /var/tmp/diff_new_pack.PIEHad/_old  2017-02-03 17:40:18.602545145 +0100
+++ /var/tmp/diff_new_pack.PIEHad/_new  2017-02-03 17:40:18.606544579 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package ghc-tls
 #
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,15 +19,14 @@
 %global pkg_name tls
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        1.3.8
+Version:        1.3.9
 Release:        0
 Summary:        TLS/SSL protocol native implementation (Server and Client)
 License:        BSD-3-Clause
-Group:          System/Libraries
+Group:          Development/Languages/Other
 Url:            https://hackage.haskell.org/package/%{pkg_name}
 Source0:        
https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz
 BuildRequires:  ghc-Cabal-devel
-# Begin cabal-rpm deps:
 BuildRequires:  ghc-asn1-encoding-devel
 BuildRequires:  ghc-asn1-types-devel
 BuildRequires:  ghc-async-devel
@@ -50,7 +49,6 @@
 BuildRequires:  ghc-tasty-devel
 BuildRequires:  ghc-tasty-quickcheck-devel
 %endif
-# End cabal-rpm deps
 
 %description
 Native Haskell TLS and SSL protocol implementation for server and client.
@@ -80,20 +78,14 @@
 %prep
 %setup -q -n %{pkg_name}-%{version}
 
-
 %build
 %ghc_lib_build
 
-
 %install
 %ghc_lib_install
 
-
 %check
-%if %{with tests}
-%{cabal} test
-%endif
-
+%cabal_test
 
 %post devel
 %ghc_pkg_recache

++++++ tls-1.3.8.tar.gz -> tls-1.3.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/CHANGELOG.md new/tls-1.3.9/CHANGELOG.md
--- old/tls-1.3.8/CHANGELOG.md  2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/CHANGELOG.md  2016-05-14 18:46:17.000000000 +0200
@@ -1,3 +1,7 @@
+## Version 1.3.8
+
+- Fix older GHC builds
+
 ## Version 1.3.7
 
 - Disable SHA384 based cipher, as they don't work properly yet.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Backend.hs 
new/tls-1.3.9/Network/TLS/Backend.hs
--- old/tls-1.3.8/Network/TLS/Backend.hs        2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Backend.hs        2016-07-30 12:11:49.000000000 
+0200
@@ -52,6 +52,23 @@
     initializeBackend _ = return ()
     getBackend = id
 
+#if defined(__GLASGOW_HASKELL__) && WINDOWS
+-- Socket recv and accept calls on Windows platform cannot be interrupted when 
compiled with -threaded.
+-- See https://ghc.haskell.org/trac/ghc/ticket/5797 for details.
+-- The following enables simple workaround
+#define SOCKET_ACCEPT_RECV_WORKAROUND
+#endif
+
+safeRecv :: Network.Socket -> Int -> IO ByteString
+#ifndef SOCKET_ACCEPT_RECV_WORKAROUND
+safeRecv = Network.recv
+#else
+safeRecv s buf = do
+    var <- newEmptyMVar
+    forkIO $ Network.recv s buf `E.catch` (\(_::IOException) -> return 
S8.empty) >>= putMVar var
+    takeMVar var
+#endif
+
 #ifdef INCLUDE_NETWORK
 instance HasBackend Network.Socket where
     initializeBackend _ = return ()
@@ -59,7 +76,7 @@
       where recvAll n = B.concat `fmap` loop n
               where loop 0    = return []
                     loop left = do
-                        r <- Network.recv sock left
+                        r <- safeRecv sock left
                         if B.null r
                             then return []
                             else liftM (r:) (loop (left - B.length r))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Cipher.hs 
new/tls-1.3.9/Network/TLS/Cipher.hs
--- old/tls-1.3.8/Network/TLS/Cipher.hs 2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Cipher.hs 2016-12-17 12:09:25.000000000 +0100
@@ -125,6 +125,7 @@
     , cipherBulk         :: Bulk
     , cipherKeyExchange  :: CipherKeyExchangeType
     , cipherMinVer       :: Maybe Version
+    , cipherPRFHash      :: Maybe Hash
     }
 
 cipherKeyBlockSize :: Cipher -> Int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Context/Internal.hs 
new/tls-1.3.9/Network/TLS/Context/Internal.hs
--- old/tls-1.3.8/Network/TLS/Context/Internal.hs       2016-05-12 
08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Context/Internal.hs       2016-07-30 
12:11:49.000000000 +0200
@@ -57,6 +57,7 @@
 import Network.TLS.Backend
 import Network.TLS.Extension
 import Network.TLS.Cipher
+import Network.TLS.Credentials (Credentials)
 import Network.TLS.Struct
 import Network.TLS.Compression (Compression)
 import Network.TLS.State
@@ -89,7 +90,8 @@
     { ctxConnection       :: Backend   -- ^ return the backend object 
associated with this context
     , ctxSupported        :: Supported
     , ctxShared           :: Shared
-    , ctxCiphers          :: [Cipher]  -- ^ prepared list of allowed ciphers 
according to parameters
+    , ctxCiphers          :: Credentials -> [Cipher]  -- ^ list of allowed 
ciphers according to parameters
+                                                      -- and additional 
credentials
     , ctxState            :: MVar TLSState
     , ctxMeasurement      :: IORef Measurement
     , ctxEOF_             :: IORef Bool    -- ^ has the handle EOFed or not.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Context.hs 
new/tls-1.3.9/Network/TLS/Context.hs
--- old/tls-1.3.8/Network/TLS/Context.hs        2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Context.hs        2016-12-17 12:09:25.000000000 
+0100
@@ -81,6 +81,7 @@
 import Control.Concurrent.MVar
 import Control.Monad.State
 import Data.IORef
+import Data.Monoid (mappend)
 
 -- deprecated imports
 #ifdef INCLUDE_NETWORK
@@ -91,7 +92,7 @@
 class TLSParams a where
     getTLSCommonParams :: a -> CommonParams
     getTLSRole         :: a -> Role
-    getCiphers         :: a -> [Cipher]
+    getCiphers         :: a -> Credentials -> [Cipher]
     doHandshake        :: a -> Context -> IO ()
     doHandshakeWith    :: a -> Context -> Handshake -> IO ()
 
@@ -101,7 +102,7 @@
                                  , clientDebug cparams
                                  )
     getTLSRole _ = ClientRole
-    getCiphers cparams = supportedCiphers $ clientSupported cparams
+    getCiphers cparams _ = supportedCiphers $ clientSupported cparams
     doHandshake = handshakeClient
     doHandshakeWith = handshakeClientWith
 
@@ -113,7 +114,7 @@
     getTLSRole _ = ServerRole
     -- on the server we filter our allowed ciphers here according
     -- to the credentials and DHE parameters loaded
-    getCiphers sparams = filter authorizedCKE (supportedCiphers $ 
serverSupported sparams)
+    getCiphers sparams extraCreds = filter authorizedCKE (supportedCiphers $ 
serverSupported sparams)
           where authorizedCKE cipher =
                     case cipherKeyExchange cipher of
                         CipherKeyExchange_RSA         -> canEncryptRSA
@@ -121,20 +122,24 @@
                         CipherKeyExchange_DHE_RSA     -> canSignRSA && canDHE
                         CipherKeyExchange_DHE_DSS     -> canSignDSS && canDHE
                         CipherKeyExchange_ECDHE_RSA   -> canSignRSA
-                        -- unimplemented: non ephemeral DH
+                        -- unimplemented: EC
+                        CipherKeyExchange_ECDHE_ECDSA -> False
+                        -- unimplemented: non ephemeral DH & ECDH.
+                        -- Note, these *should not* be implemented, and have
+                        -- (for example) been removed in OpenSSL 1.1.0
+                        --
                         CipherKeyExchange_DH_DSS      -> False
                         CipherKeyExchange_DH_RSA      -> False
-                        -- unimplemented: EC
                         CipherKeyExchange_ECDH_ECDSA  -> False
                         CipherKeyExchange_ECDH_RSA    -> False
-                        CipherKeyExchange_ECDHE_ECDSA -> False
 
                 canDHE        = isJust $ serverDHEParams sparams
                 canSignDSS    = SignatureDSS `elem` signingAlgs
                 canSignRSA    = SignatureRSA `elem` signingAlgs
                 canEncryptRSA = isJust $ credentialsFindForDecrypting creds
                 signingAlgs   = credentialsListSigningAlgorithms creds
-                creds         = sharedCredentials $ serverShared sparams
+                serverCreds   = sharedCredentials $ serverShared sparams
+                creds         = extraCreds `mappend` serverCreds
     doHandshake = handshakeServer
     doHandshakeWith = handshakeServerWith
 
@@ -159,7 +164,9 @@
         st   = newTLSState rng role
         ciphers = getCiphers params
 
-    when (null ciphers) $ error "no ciphers available with those parameters"
+--  we still might get some ciphers from SNI callback
+--  If we could bail only on protocols which require the main cert??
+--    when (null (ciphers mempty)) $ error "no ciphers available with those 
parameters"
 
     stvar <- newMVar st
     eof   <- newIORef False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Core.hs 
new/tls-1.3.9/Network/TLS/Core.hs
--- old/tls-1.3.8/Network/TLS/Core.hs   2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Core.hs   2016-12-04 07:54:32.000000000 +0100
@@ -54,7 +54,7 @@
 bye :: MonadIO m => Context -> m ()
 bye ctx = sendPacket ctx $ Alert [(AlertLevel_Warning, CloseNotify)]
 
--- | If the Next Protocol Negotiation extension has been used, this will
+-- | If the Next Protocol Negotiation or ALPN extensions have been used, this 
will
 -- return get the protocol agreed upon.
 getNegotiatedProtocol :: MonadIO m => Context -> m (Maybe B.ByteString)
 getNegotiatedProtocol ctx = liftIO $ usingState_ ctx S.getNegotiatedProtocol
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Crypto/ECDH.hs 
new/tls-1.3.9/Network/TLS/Crypto/ECDH.hs
--- old/tls-1.3.8/Network/TLS/Crypto/ECDH.hs    2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Crypto/ECDH.hs    2016-12-04 07:54:32.000000000 
+0100
@@ -15,7 +15,6 @@
     , ecdhUnwrapPublic
     ) where
 
-import Network.TLS.Util.Serialization (lengthBytes)
 import Network.TLS.Extension.EC
 import qualified Crypto.PubKey.ECC.DH as ECDH
 import qualified Crypto.PubKey.ECC.Types as ECDH
@@ -72,5 +71,6 @@
 ecdhUnwrapPublic _                                 = error "ecdhUnwrapPublic"
 
 pointSize :: ECDH.Curve -> Int
-pointSize (ECDH.CurveFP curve) = lengthBytes $ ECDH.ecc_p curve
-pointSize _ = error "pointSize" -- FIXME
+pointSize = toBytes . ECDH.curveSizeBits
+  where
+    toBytes bits = (bits + 7) `div` 8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Crypto.hs 
new/tls-1.3.9/Network/TLS/Crypto.hs
--- old/tls-1.3.8/Network/TLS/Crypto.hs 2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Crypto.hs 2016-12-04 07:54:32.000000000 +0100
@@ -42,7 +42,6 @@
 import qualified Crypto.PubKey.RSA as RSA
 import qualified Crypto.PubKey.RSA.PKCS15 as RSA
 import Crypto.Number.Serialize (os2ip)
-import Crypto.Number.Basic (numBits)
 
 import Data.X509 (PrivKey(..), PubKey(..), PubKeyEC(..), SerializedPoint(..))
 import Network.TLS.Crypto.DH
@@ -215,7 +214,7 @@
                 Nothing                -> Nothing
                 Just (ptFormat, input) ->
                     case ptFormat of
-                        4 -> if B.length bs == 2 * bytes
+                        4 -> if B.length input /= 2 * bytes
                                 then Nothing
                                 else
                                     let (x, y) = B.splitAt bytes input
@@ -225,7 +224,7 @@
                                             else Nothing
                         -- 2 and 3 for compressed format.
                         _ -> Nothing
-          where bits  = numBits . ECC.ecc_n . ECC.common_curve $ curve
+          where bits  = ECC.curveSizeBits curve
                 bytes = (bits + 7) `div` 8
 kxVerify _              _         _   _    = False
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Extension.hs 
new/tls-1.3.9/Network/TLS/Extension.hs
--- old/tls-1.3.8/Network/TLS/Extension.hs      2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Extension.hs      2016-12-17 12:09:25.000000000 
+0100
@@ -270,7 +270,7 @@
     deriving (Show,Eq)
 
 availableEllipticCurves :: [NamedCurve]
-availableEllipticCurves = [SEC SEC_p256r1, SEC SEC_p521r1]
+availableEllipticCurves = [SEC SEC_p256r1, SEC SEC_p384r1, SEC SEC_p521r1]
 
 instance EnumSafe16 NamedCurve where
     fromEnumSafe16 NamedCurve_arbitrary_explicit_prime_curves = 0xFF01
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Extra/Cipher.hs 
new/tls-1.3.9/Network/TLS/Extra/Cipher.hs
--- old/tls-1.3.8/Network/TLS/Extra/Cipher.hs   2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Extra/Cipher.hs   2016-12-17 12:09:25.000000000 
+0100
@@ -10,7 +10,8 @@
 module Network.TLS.Extra.Cipher
     (
     -- * cipher suite
-      ciphersuite_all
+      ciphersuite_default
+    , ciphersuite_all
     , ciphersuite_medium
     , ciphersuite_strong
     , ciphersuite_unencrypted
@@ -18,29 +19,38 @@
     , ciphersuite_dhe_dss
     -- * individual ciphers
     , cipher_null_SHA1
-    , cipher_null_MD5
-    , cipher_RC4_128_MD5
-    , cipher_RC4_128_SHA1
     , cipher_AES128_SHA1
     , cipher_AES256_SHA1
     , cipher_AES128_SHA256
     , cipher_AES256_SHA256
-    , cipher_RSA_3DES_EDE_CBC_SHA1
+    , cipher_AES128GCM_SHA256
+    , cipher_AES256GCM_SHA384
     , cipher_DHE_RSA_AES128_SHA1
     , cipher_DHE_RSA_AES256_SHA1
     , cipher_DHE_RSA_AES128_SHA256
     , cipher_DHE_RSA_AES256_SHA256
     , cipher_DHE_DSS_AES128_SHA1
     , cipher_DHE_DSS_AES256_SHA1
-    , cipher_DHE_DSS_RC4_SHA1
     , cipher_DHE_RSA_AES128GCM_SHA256
+    , cipher_DHE_RSA_AES256GCM_SHA384
     , cipher_ECDHE_RSA_AES128GCM_SHA256
     , cipher_ECDHE_RSA_AES256GCM_SHA384
     , cipher_ECDHE_RSA_AES128CBC_SHA256
     , cipher_ECDHE_RSA_AES128CBC_SHA
     , cipher_ECDHE_RSA_AES256CBC_SHA
     , cipher_ECDHE_RSA_AES256CBC_SHA384
+    , cipher_ECDHE_ECDSA_AES128CBC_SHA
+    , cipher_ECDHE_ECDSA_AES256CBC_SHA
+    , cipher_ECDHE_ECDSA_AES128CBC_SHA256
+    , cipher_ECDHE_ECDSA_AES256CBC_SHA384
     , cipher_ECDHE_ECDSA_AES128GCM_SHA256
+    , cipher_ECDHE_ECDSA_AES256GCM_SHA384
+    -- * obsolete and non-standard ciphers
+    , cipher_RSA_3DES_EDE_CBC_SHA1
+    , cipher_RC4_128_MD5
+    , cipher_RC4_128_SHA1
+    , cipher_null_MD5
+    , cipher_DHE_DSS_RC4_SHA1
     ) where
 
 import qualified Data.ByteString as B
@@ -134,44 +144,82 @@
         let (ctx', output) = RC4.combine ctx input
          in (output, BulkStream (combineRC4 ctx'))
 
+-- | All AES ciphers supported ordered from strong to weak.  This choice
+-- of ciphersuites should satisfy most normal needs.  For otherwise strong
+-- ciphers we make little distinction between AES128 and AES256, and list
+-- each but the weakest of the AES128 ciphers ahead of the corresponding AES256
+-- ciphers.
+ciphersuite_default :: [Cipher]
+ciphersuite_default =
+    [        -- First the PFS + GCM + SHA2 ciphers
+      cipher_ECDHE_ECDSA_AES128GCM_SHA256, cipher_ECDHE_ECDSA_AES256GCM_SHA384
+    , cipher_ECDHE_RSA_AES128GCM_SHA256, cipher_ECDHE_RSA_AES256GCM_SHA384
+    , cipher_DHE_RSA_AES128GCM_SHA256, cipher_DHE_RSA_AES256GCM_SHA384
+             -- Next the PFS + CBC + SHA2 ciphers
+    , cipher_ECDHE_ECDSA_AES128CBC_SHA256, cipher_ECDHE_ECDSA_AES256CBC_SHA384
+    , cipher_ECDHE_RSA_AES128CBC_SHA256, cipher_ECDHE_RSA_AES256CBC_SHA384
+    , cipher_DHE_RSA_AES128_SHA256, cipher_DHE_RSA_AES256_SHA256
+             -- Next the PFS + CBC + SHA1 ciphers
+    , cipher_ECDHE_ECDSA_AES128CBC_SHA, cipher_ECDHE_ECDSA_AES256CBC_SHA
+    , cipher_ECDHE_RSA_AES128CBC_SHA, cipher_ECDHE_RSA_AES256CBC_SHA
+    , cipher_DHE_RSA_AES128_SHA1, cipher_DHE_RSA_AES256_SHA1
+             -- Next the non-PFS + GCM + SHA2 ciphers
+    , cipher_AES128GCM_SHA256, cipher_AES256GCM_SHA384
+             -- Next the non-PFS + CBC + SHA2 ciphers
+    , cipher_AES256_SHA256, cipher_AES128_SHA256
+             -- Next the non-PFS + CBC + SHA1 ciphers
+    , cipher_AES256_SHA1, cipher_AES128_SHA1
+             -- Nobody uses or should use DSS, RC4,  3DES or MD5
+    -- , cipher_DHE_DSS_AES256_SHA1, cipher_DHE_DSS_AES128_SHA1
+    -- , cipher_DHE_DSS_RC4_SHA1, cipher_RC4_128_SHA1, cipher_RC4_128_MD5
+    -- , cipher_RSA_3DES_EDE_CBC_SHA1
+    ]
 
--- | all encrypted ciphers supported ordered from strong to weak.
--- this choice of ciphersuite should satisfy most normal need
+-- | The default ciphersuites + some not recommended last resort ciphers.
 ciphersuite_all :: [Cipher]
-ciphersuite_all =
-    [ cipher_ECDHE_RSA_AES128GCM_SHA256
-    , cipher_ECDHE_RSA_AES256CBC_SHA
-    , cipher_ECDHE_ECDSA_AES128GCM_SHA256
-    , cipher_DHE_RSA_AES256_SHA256, cipher_DHE_RSA_AES128_SHA256
-    , cipher_DHE_RSA_AES256_SHA1, cipher_DHE_RSA_AES128_SHA1
-    , cipher_DHE_DSS_AES256_SHA1, cipher_DHE_DSS_AES128_SHA1
-    , cipher_AES128_SHA256, cipher_AES256_SHA256
-    , cipher_AES128_SHA1,   cipher_AES256_SHA1
-    , cipher_DHE_DSS_RC4_SHA1, cipher_RC4_128_SHA1,  cipher_RC4_128_MD5
+ciphersuite_all = ciphersuite_default ++
+    [ cipher_DHE_DSS_AES256_SHA1, cipher_DHE_DSS_AES128_SHA1
     , cipher_RSA_3DES_EDE_CBC_SHA1
-    , cipher_DHE_RSA_AES128GCM_SHA256
+    , cipher_RC4_128_SHA1
     ]
 
 -- | list of medium ciphers.
 ciphersuite_medium :: [Cipher]
-ciphersuite_medium = [cipher_RC4_128_MD5, cipher_RC4_128_SHA1, 
cipher_AES128_SHA1, cipher_AES256_SHA1]
-
--- | the strongest ciphers supported.
+ciphersuite_medium = [ cipher_RC4_128_SHA1
+                     , cipher_AES128_SHA1
+                     ]
+
+-- | The strongest ciphers supported ciphers supported.  For ciphers with PFS,
+-- AEAD and SHA2, we list each AES128 variant right after the corresponding
+-- AES256 variant.  For weaker constructs, we use just the AES256 form.
 ciphersuite_strong :: [Cipher]
 ciphersuite_strong =
-    [ cipher_ECDHE_RSA_AES128GCM_SHA256
-    , cipher_ECDHE_RSA_AES256CBC_SHA
-    , cipher_ECDHE_ECDSA_AES128GCM_SHA256
+    [        -- If we have PFS + AEAD + SHA2, then allow AES128, else just 256
+      cipher_ECDHE_ECDSA_AES256GCM_SHA384, cipher_ECDHE_ECDSA_AES128GCM_SHA256
+    , cipher_ECDHE_RSA_AES256GCM_SHA384, cipher_ECDHE_RSA_AES128GCM_SHA256
+    , cipher_DHE_RSA_AES256GCM_SHA384, cipher_DHE_RSA_AES128GCM_SHA256
+             -- No AEAD
+    , cipher_ECDHE_ECDSA_AES256CBC_SHA384
+    , cipher_ECDHE_RSA_AES256CBC_SHA384
     , cipher_DHE_RSA_AES256_SHA256
+             -- No SHA2
+    , cipher_ECDHE_ECDSA_AES256CBC_SHA
+    , cipher_ECDHE_RSA_AES256CBC_SHA
+    , cipher_DHE_RSA_AES256_SHA1
+             -- No PFS
+    , cipher_AES256GCM_SHA384
+             -- Neither PFS nor AEAD, just SHA2
     , cipher_AES256_SHA256
+             -- Last resort no PFS, AEAD or SHA2
     , cipher_AES256_SHA1
     ]
 
 -- | DHE-RSA cipher suite
 ciphersuite_dhe_rsa :: [Cipher]
-ciphersuite_dhe_rsa = [cipher_DHE_RSA_AES256_SHA256, 
cipher_DHE_RSA_AES128_SHA256
+ciphersuite_dhe_rsa = [ cipher_DHE_RSA_AES256GCM_SHA384, 
cipher_DHE_RSA_AES128GCM_SHA256
+                      , cipher_DHE_RSA_AES256_SHA256, 
cipher_DHE_RSA_AES128_SHA256
                       , cipher_DHE_RSA_AES256_SHA1, cipher_DHE_RSA_AES128_SHA1
-                      , cipher_DHE_RSA_AES128GCM_SHA256]
+                      ]
 
 ciphersuite_dhe_dss :: [Cipher]
 ciphersuite_dhe_dss = [cipher_DHE_DSS_AES256_SHA1, cipher_DHE_DSS_AES128_SHA1, 
cipher_DHE_DSS_RC4_SHA1]
@@ -260,6 +308,7 @@
     , cipherName         = "RSA-null-MD5"
     , cipherBulk         = bulk_null
     , cipherHash         = MD5
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Nothing
     }
@@ -271,6 +320,7 @@
     , cipherName         = "RSA-null-SHA1"
     , cipherBulk         = bulk_null
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Nothing
     }
@@ -282,6 +332,7 @@
     , cipherName         = "RSA-rc4-128-md5"
     , cipherBulk         = bulk_rc4
     , cipherHash         = MD5
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Nothing
     }
@@ -293,6 +344,7 @@
     , cipherName         = "RSA-rc4-128-sha1"
     , cipherBulk         = bulk_rc4
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Nothing
     }
@@ -304,6 +356,7 @@
     , cipherName         = "RSA-AES128-SHA1"
     , cipherBulk         = bulk_aes128
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Just SSL3
     }
@@ -315,6 +368,7 @@
     , cipherName         = "DHE-DSA-AES128-SHA1"
     , cipherBulk         = bulk_aes128
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_DHE_DSS
     , cipherMinVer       = Nothing
     }
@@ -326,6 +380,7 @@
     , cipherName         = "DHE-RSA-AES128-SHA1"
     , cipherBulk         = bulk_aes128
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_DHE_RSA
     , cipherMinVer       = Nothing
     }
@@ -337,6 +392,7 @@
     , cipherName         = "RSA-AES256-SHA1"
     , cipherBulk         = bulk_aes256
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Just SSL3
     }
@@ -364,6 +420,7 @@
     , cipherName         = "RSA-AES128-SHA256"
     , cipherBulk         = bulk_aes128
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Just TLS12
     }
@@ -375,10 +432,36 @@
     , cipherName         = "RSA-AES256-SHA256"
     , cipherBulk         = bulk_aes256
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
+    , cipherKeyExchange  = CipherKeyExchange_RSA
+    , cipherMinVer       = Just TLS12
+    }
+
+-- | AESGCM cipher (128 bit key), RSA key exchange.
+-- The SHA256 digest is used as a PRF, not as a MAC.
+cipher_AES128GCM_SHA256 :: Cipher
+cipher_AES128GCM_SHA256 = Cipher
+    { cipherID           = 0x9c
+    , cipherName         = "RSA-AES128GCM-SHA256"
+    , cipherBulk         = bulk_aes128gcm
+    , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Just TLS12
     }
 
+-- | AESGCM cipher (256 bit key), RSA key exchange.
+-- The SHA384 digest is used as a PRF, not as a MAC.
+cipher_AES256GCM_SHA384 :: Cipher
+cipher_AES256GCM_SHA384 = Cipher
+    { cipherID           = 0x9d
+    , cipherName         = "RSA-AES256GCM-SHA384"
+    , cipherBulk         = bulk_aes256gcm
+    , cipherHash         = SHA384
+    , cipherPRFHash      = Just SHA384
+    , cipherKeyExchange  = CipherKeyExchange_RSA
+    , cipherMinVer       = Just TLS12
+    }
 
 cipher_DHE_DSS_RC4_SHA1 :: Cipher
 cipher_DHE_DSS_RC4_SHA1 = cipher_DHE_DSS_AES128_SHA1
@@ -392,6 +475,7 @@
     { cipherID           = 0x67
     , cipherName         = "DHE-RSA-AES128-SHA256"
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
     , cipherMinVer       = Just TLS12
     }
 
@@ -409,6 +493,7 @@
     , cipherName         = "RSA-3DES-EDE-CBC-SHA1"
     , cipherBulk         = bulk_tripledes_ede
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_RSA
     , cipherMinVer       = Nothing
     }
@@ -419,16 +504,51 @@
     , cipherName         = "DHE-RSA-AES128GCM-SHA256"
     , cipherBulk         = bulk_aes128gcm
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
     , cipherKeyExchange  = CipherKeyExchange_DHE_RSA
     , cipherMinVer       = Just TLS12 -- RFC 5288 Sec 4
     }
 
+cipher_DHE_RSA_AES256GCM_SHA384 :: Cipher
+cipher_DHE_RSA_AES256GCM_SHA384 = Cipher
+    { cipherID           = 0x9f
+    , cipherName         = "DHE-RSA-AES256GCM-SHA384"
+    , cipherBulk         = bulk_aes256gcm
+    , cipherHash         = SHA384
+    , cipherPRFHash      = Just SHA384
+    , cipherKeyExchange  = CipherKeyExchange_DHE_RSA
+    , cipherMinVer       = Just TLS12
+    }
+
+cipher_ECDHE_ECDSA_AES128CBC_SHA :: Cipher
+cipher_ECDHE_ECDSA_AES128CBC_SHA = Cipher
+    { cipherID           = 0xc009
+    , cipherName         = "ECDHE-ECDSA-AES128CBC-SHA"
+    , cipherBulk         = bulk_aes128
+    , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
+    , cipherMinVer       = Just TLS10
+    }
+
+cipher_ECDHE_ECDSA_AES256CBC_SHA :: Cipher
+cipher_ECDHE_ECDSA_AES256CBC_SHA = Cipher
+    { cipherID           = 0xc00A
+    , cipherName         = "ECDHE-ECDSA-AES256CBC-SHA"
+    , cipherBulk         = bulk_aes256
+    , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
+    , cipherMinVer       = Just TLS10
+    }
+
 cipher_ECDHE_RSA_AES128CBC_SHA :: Cipher
 cipher_ECDHE_RSA_AES128CBC_SHA = Cipher
     { cipherID           = 0xc013
     , cipherName         = "ECDHE-RSA-AES128CBC-SHA"
     , cipherBulk         = bulk_aes128
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
     , cipherMinVer       = Just TLS10
     }
@@ -439,6 +559,7 @@
     , cipherName         = "ECDHE-RSA-AES256CBC-SHA"
     , cipherBulk         = bulk_aes256
     , cipherHash         = SHA1
+    , cipherPRFHash      = Nothing
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
     , cipherMinVer       = Just TLS10
     }
@@ -449,26 +570,62 @@
     , cipherName         = "ECDHE-RSA-AES128CBC-SHA256"
     , cipherBulk         = bulk_aes128
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
     , cipherMinVer       = Just TLS12 -- RFC 5288 Sec 4
     }
 
 cipher_ECDHE_RSA_AES256CBC_SHA384 :: Cipher
 cipher_ECDHE_RSA_AES256CBC_SHA384 = Cipher
-    { cipherID           = 0xc027
+    { cipherID           = 0xc028
     , cipherName         = "ECDHE-RSA-AES256CBC-SHA384"
     , cipherBulk         = bulk_aes256
     , cipherHash         = SHA384
+    , cipherPRFHash      = Just SHA384
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
     , cipherMinVer       = Just TLS12 -- RFC 5288 Sec 4
     }
 
+cipher_ECDHE_ECDSA_AES128CBC_SHA256 :: Cipher
+cipher_ECDHE_ECDSA_AES128CBC_SHA256 = Cipher
+    { cipherID           = 0xc023
+    , cipherName         = "ECDHE-ECDSA-AES128CBC-SHA256"
+    , cipherBulk         = bulk_aes128
+    , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_ECDSA
+    , cipherMinVer       = Just TLS12 -- RFC 5289
+    }
+
+cipher_ECDHE_ECDSA_AES256CBC_SHA384 :: Cipher
+cipher_ECDHE_ECDSA_AES256CBC_SHA384 = Cipher
+    { cipherID           = 0xc024
+    , cipherName         = "ECDHE-ECDSA-AES256CBC-SHA384"
+    , cipherBulk         = bulk_aes256
+    , cipherHash         = SHA384
+    , cipherPRFHash      = Just SHA384
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_ECDSA
+    , cipherMinVer       = Just TLS12 -- RFC 5289
+    }
+
 cipher_ECDHE_ECDSA_AES128GCM_SHA256 :: Cipher
 cipher_ECDHE_ECDSA_AES128GCM_SHA256 = Cipher
     { cipherID           = 0xc02b
     , cipherName         = "ECDHE-ECDSA-AES128GCM-SHA256"
     , cipherBulk         = bulk_aes128gcm
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_ECDSA
+    , cipherMinVer       = Just TLS12 -- RFC 5289
+    }
+
+cipher_ECDHE_ECDSA_AES256GCM_SHA384 :: Cipher
+cipher_ECDHE_ECDSA_AES256GCM_SHA384 = Cipher
+    { cipherID           = 0xc02c
+    , cipherName         = "ECDHE-ECDSA-AES256GCM-SHA384"
+    , cipherBulk         = bulk_aes256gcm
+    , cipherHash         = SHA384
+    , cipherPRFHash      = Just SHA384
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_ECDSA
     , cipherMinVer       = Just TLS12 -- RFC 5289
     }
@@ -479,6 +636,7 @@
     , cipherName         = "ECDHE-RSA-AES128GCM-SHA256"
     , cipherBulk         = bulk_aes128gcm
     , cipherHash         = SHA256
+    , cipherPRFHash      = Just SHA256
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
     , cipherMinVer       = Just TLS12 -- RFC 5288 Sec 4
     }
@@ -486,9 +644,10 @@
 cipher_ECDHE_RSA_AES256GCM_SHA384 :: Cipher
 cipher_ECDHE_RSA_AES256GCM_SHA384 = Cipher
     { cipherID           = 0xc030
-    , cipherName         = "ECDHE-RSA-AES256GCM-SHA256"
+    , cipherName         = "ECDHE-RSA-AES256GCM-SHA384"
     , cipherBulk         = bulk_aes256gcm
     , cipherHash         = SHA384
+    , cipherPRFHash      = Just SHA384
     , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
     , cipherMinVer       = Just TLS12 -- RFC 5289
     }
@@ -525,6 +684,9 @@
 CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA          = { 0x00,0x1A };
 CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA     = { 0x00,0x1B };
 
+TLS-RSA-WITH-AES-128-GCM-SHA256    {0x00,0x9C}
+TLS-RSA-WITH-AES-256-GCM-SHA384    {0x00,0x9D}
+
 TLS-DHE-RSA-WITH-AES-128-CBC-SHA     {0x00,0x33}
 TLS-DHE-RSA-WITH-AES-256-CBC-SHA     {0x00,0x39}
 TLS-DHE-RSA-WITH-AES-128-CBC-SHA256   {0x00,0x67}
@@ -554,6 +716,13 @@
 TLS-ECDHE-RSA-WITH-RC4-128-SHA    {0xC0,0x11}
 TLS-ECDHE-RSA-WITH-NULL-SHA  {0xC0,0x10}
 
+TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA    {0xC0,0x09}
+TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA    {0xC0,0x0A}
+TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 {0xC0,0x23}
+TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 {0xC0,0x24}
+TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 {0xC0,0x2B}
+TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 {0xC0,0x2C}
+
 TLS-PSK-WITH-RC4-128-SHA    {0x00,0x8A}
 TLS-PSK-WITH-3DES-EDE-CBC-SHA      {0x00,0x8B}
 TLS-PSK-WITH-AES-128-CBC-SHA     {0x00,0x8C}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Handshake/Client.hs 
new/tls-1.3.9/Network/TLS/Handshake/Client.hs
--- old/tls-1.3.8/Network/TLS/Handshake/Client.hs       2016-05-12 
08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Handshake/Client.hs       2016-07-30 
12:11:49.000000000 +0200
@@ -111,7 +111,7 @@
             startHandshake ctx highestVer crand
             usingState_ ctx $ setVersionIfUnset highestVer
             sendPacket ctx $ Handshake
-                [ ClientHello highestVer crand clientSession (map cipherID 
ciphers)
+                [ ClientHello highestVer crand clientSession (map cipherID 
(ciphers mempty))
                               (map compressionID compressions) extensions 
Nothing
                 ]
             return $ map (\(ExtensionRaw i _) -> i) extensions
@@ -291,7 +291,7 @@
         Nothing -> throwCore $ Error_Protocol ("server version " ++ show rver 
++ " is not supported", True, ProtocolVersion)
         Just _  -> return ()
     -- find the compression and cipher methods that the server want to use.
-    cipherAlg <- case find ((==) cipher . cipherID) (ctxCiphers ctx) of
+    cipherAlg <- case find ((==) cipher . cipherID) (ctxCiphers ctx mempty) of
                      Nothing  -> throwCore $ Error_Protocol ("server choose 
unknown cipher", True, HandshakeFailure)
                      Just alg -> return alg
     compressAlg <- case find ((==) compression . compressionID) 
(supportedCompressions $ ctxSupported ctx) of
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Handshake/Key.hs 
new/tls-1.3.9/Network/TLS/Handshake/Key.hs
--- old/tls-1.3.8/Network/TLS/Handshake/Key.hs  2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Handshake/Key.hs  2016-12-17 12:09:25.000000000 
+0100
@@ -9,9 +9,9 @@
 --
 module Network.TLS.Handshake.Key
     ( encryptRSA
-    , signRSA
+    , signPrivate
     , decryptRSA
-    , verifyRSA
+    , verifyPublic
     , generateDHE
     , generateECDHE
     ) where
@@ -37,8 +37,8 @@
             Left err       -> fail ("rsa encrypt failed: " ++ show err)
             Right econtent -> return econtent
 
-signRSA :: Context -> Role -> Hash -> ByteString -> IO ByteString
-signRSA ctx _ hsh content = do
+signPrivate :: Context -> Role -> Hash -> ByteString -> IO ByteString
+signPrivate ctx _ hsh content = do
     privateKey <- usingHState ctx getLocalPrivateKey
     usingState_ ctx $ do
         r <- withRNG $ kxSign privateKey hsh content
@@ -54,8 +54,8 @@
         let cipher = if ver < TLS10 then econtent else B.drop 2 econtent
         withRNG $ kxDecrypt privateKey cipher
 
-verifyRSA :: Context -> Role -> Hash -> ByteString -> ByteString -> IO Bool
-verifyRSA ctx _ hsh econtent sign = do
+verifyPublic :: Context -> Role -> Hash -> ByteString -> ByteString -> IO Bool
+verifyPublic ctx _ hsh econtent sign = do
     publicKey <- usingHState ctx getRemotePublicKey
     return $ kxVerify publicKey hsh econtent sign
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Handshake/Server.hs 
new/tls-1.3.9/Network/TLS/Handshake/Server.hs
--- old/tls-1.3.8/Network/TLS/Handshake/Server.hs       2016-05-12 
08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Handshake/Server.hs       2016-12-17 
12:09:25.000000000 +0100
@@ -106,8 +106,6 @@
                         Nothing -> throwCore $ Error_Protocol ("client version 
" ++ show clientVersion ++ " is not supported", True, ProtocolVersion)
                         Just v  -> return v
 
-    when (commonCipherIDs == []) $ throwCore $
-        Error_Protocol ("no cipher in common with the client", True, 
HandshakeFailure)
     when (null commonCompressions) $ throwCore $
         Error_Protocol ("no compression in common with the client", True, 
HandshakeFailure)
 
@@ -117,10 +115,18 @@
                       toHostName (ServerNameOther _)           = Nothing
             _                           -> Nothing
 
-    let ciphersFilteredVersion = filter (cipherAllowedForVersion 
chosenVersion) commonCiphers
-        usedCipher = (onCipherChoosing $ serverHooks sparams) chosenVersion 
ciphersFilteredVersion
     extraCreds <- (onServerNameIndication $ serverHooks sparams) serverName
-    let creds = extraCreds `mappend` (sharedCredentials $ ctxShared ctx)
+
+    -- The shared cipherlist can become empty after filtering for compatible
+    -- creds, check now before calling onCipherChoosing, which does not handle
+    -- empty lists.
+    let ciphersFilteredVersion = filter (cipherAllowedForVersion 
chosenVersion) (commonCiphers extraCreds)
+    when (null ciphersFilteredVersion) $ throwCore $
+        Error_Protocol ("no cipher in common with the client", True, 
HandshakeFailure)
+
+    let usedCipher = (onCipherChoosing $ serverHooks sparams) chosenVersion 
ciphersFilteredVersion
+        creds = extraCreds `mappend` (sharedCredentials $ ctxShared ctx)
+
     cred <- case cipherKeyExchange usedCipher of
                 CipherKeyExchange_RSA     -> return $ 
credentialsFindForDecrypting creds
                 CipherKeyExchange_DH_Anon -> return $ Nothing
@@ -152,10 +158,10 @@
     doHandshake sparams cred ctx chosenVersion usedCipher usedCompression 
clientSession resumeSessionData exts
 
   where
-        commonCipherIDs    = intersect ciphers (map cipherID $ ctxCiphers ctx)
-        commonCiphers      = filter (flip elem commonCipherIDs . cipherID) 
(ctxCiphers ctx)
-        commonCompressions = compressionIntersectID (supportedCompressions $ 
ctxSupported ctx) compressions
-        usedCompression    = head commonCompressions
+        commonCipherIDs extra = intersect ciphers (map cipherID $ (ctxCiphers 
ctx extra))
+        commonCiphers   extra = filter (flip elem (commonCipherIDs extra) . 
cipherID) (ctxCiphers ctx extra)
+        commonCompressions    = compressionIntersectID (supportedCompressions 
$ ctxSupported ctx) compressions
+        usedCompression       = head commonCompressions
 
 
 handshakeServerWith _ _ _ = throwCore $ Error_Protocol ("unexpected handshake 
message received in handshakeServerWith", True, HandshakeFailure)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Handshake/Signature.hs 
new/tls-1.3.9/Network/TLS/Handshake/Signature.hs
--- old/tls-1.3.8/Network/TLS/Handshake/Signature.hs    2016-05-12 
08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Handshake/Signature.hs    2016-12-17 
12:09:25.000000000 +0100
@@ -107,7 +107,7 @@
             case (malg, hashAlg) of
                 (Nothing, SHA1_MD5) -> hashFinal $ hashUpdate (hashInit 
SHA1_MD5) toSign
                 _                   -> toSign
-    DigitallySigned malg <$> signRSA ctx cc hashAlg signData
+    DigitallySigned malg <$> signPrivate ctx cc hashAlg signData
 
 signatureVerify :: Context -> DigitallySigned -> SignatureAlgorithm -> Bytes 
-> IO Bool
 signatureVerify ctx digSig@(DigitallySigned hashSigAlg _) sigAlgExpected 
toVerifyData = do
@@ -133,9 +133,9 @@
 signatureVerifyWithHashDescr ctx sigAlgExpected (DigitallySigned _ bs) 
(hashDescr, toVerify) = do
     cc <- usingState_ ctx $ isClientContext
     case sigAlgExpected of
-        SignatureRSA   -> verifyRSA ctx cc hashDescr toVerify bs
-        SignatureDSS   -> verifyRSA ctx cc hashDescr toVerify bs
-        SignatureECDSA -> verifyRSA ctx cc hashDescr toVerify bs
+        SignatureRSA   -> verifyPublic ctx cc hashDescr toVerify bs
+        SignatureDSS   -> verifyPublic ctx cc hashDescr toVerify bs
+        SignatureECDSA -> verifyPublic ctx cc hashDescr toVerify bs
         _              -> error "signature verification not implemented yet"
 
 digitallySignParams :: Context -> Bytes -> SignatureAlgorithm -> IO 
DigitallySigned
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Handshake/State.hs 
new/tls-1.3.9/Network/TLS/Handshake/State.hs
--- old/tls-1.3.8/Network/TLS/Handshake/State.hs        2016-05-12 
08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Handshake/State.hs        2016-12-17 
12:09:25.000000000 +0100
@@ -188,7 +188,8 @@
   where gen hst = case hstHandshakeDigest hst of
                       Right hashCtx ->
                          let msecret = fromJust "master secret" $ 
hstMasterSecret hst
-                          in generateFinish ver msecret hashCtx
+                             cipher  = fromJust "cipher" $ hstPendingCipher hst
+                          in generateFinish ver cipher msecret hashCtx
                       Left _        ->
                          error "un-initialized handshake digest"
         generateFinish | role == ClientRole = generateClientFinished
@@ -203,7 +204,8 @@
 setMasterSecretFromPre ver role premasterSecret = do
     secret <- genSecret <$> get
     setMasterSecret ver role secret
-  where genSecret hst = generateMasterSecret ver
+  where genSecret hst =
+            generateMasterSecret ver (fromJust "cipher" $ hstPendingCipher hst)
                                  premasterSecret
                                  (hstClientRandom hst)
                                  (fromJust "server random" $ hstServerRandom 
hst)
@@ -227,7 +229,7 @@
                                               else 0
         keySize      = bulkKeySize bulk
         ivSize       = bulkIVSize bulk
-        kb           = generateKeyBlock ver (hstClientRandom hst)
+        kb           = generateKeyBlock ver cipher (hstClientRandom hst)
                                         (fromJust "server random" $ 
hstServerRandom hst)
                                         masterSecret keyblockSize
 
@@ -271,6 +273,14 @@
                 , hstPendingCompression = compression
                 , hstHandshakeDigest    = updateDigest $ hstHandshakeDigest hst
                 }
-  where hashAlg = if ver < TLS12 then SHA1_MD5 else SHA256
+  where hashAlg = getHash ver cipher
         updateDigest (Left bytes) = Right $ foldl hashUpdate (hashInit 
hashAlg) $ reverse bytes
         updateDigest (Right _)    = error "cannot initialize digest with 
another digest"
+
+-- The TLS12 Hash is cipher specific, and some TLS12 algorithms use SHA384
+-- instead of the default SHA256.
+getHash :: Version -> Cipher -> Hash
+getHash ver ciph
+    | ver < TLS12                              = SHA1_MD5
+    | maybe True (< TLS12) (cipherMinVer ciph) = SHA256
+    | otherwise                                = cipherHash ciph
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/MAC.hs 
new/tls-1.3.9/Network/TLS/MAC.hs
--- old/tls-1.3.8/Network/TLS/MAC.hs    2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/MAC.hs    2016-12-17 12:09:25.000000000 +0100
@@ -11,10 +11,12 @@
     , prf_MD5
     , prf_SHA1
     , prf_SHA256
+    , prf_TLS
     , prf_MD5SHA1
     ) where
 
 import Network.TLS.Crypto
+import Network.TLS.Types
 import qualified Data.ByteString as B
 import Data.ByteString (ByteString)
 import Data.Bits (xor)
@@ -71,3 +73,9 @@
 
 prf_SHA256 :: ByteString -> ByteString -> Int -> ByteString
 prf_SHA256 secret seed len = B.concat $ hmacIter (hmac SHA256) secret seed 
seed len
+
+-- | For now we ignore the version, but perhaps some day the PRF will depend
+-- not only on the cipher PRF algorithm, but also on the protocol version.
+prf_TLS :: Version -> Hash -> ByteString -> ByteString -> Int -> ByteString
+prf_TLS _ halg secret seed len =
+    B.concat $ hmacIter (hmac halg) secret seed seed len
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Packet.hs 
new/tls-1.3.9/Network/TLS/Packet.hs
--- old/tls-1.3.8/Network/TLS/Packet.hs 2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS/Packet.hs 2016-12-17 12:09:25.000000000 +0100
@@ -71,7 +71,7 @@
 import Data.X509 (CertificateChainRaw(..), encodeCertificateChain, 
decodeCertificateChain)
 import Network.TLS.Crypto
 import Network.TLS.MAC
-import Network.TLS.Cipher (CipherKeyExchangeType(..))
+import Network.TLS.Cipher (CipherKeyExchangeType(..), Cipher(..))
 import Network.TLS.Util.Serialization (os2ip,i2ospOf_)
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
@@ -380,9 +380,9 @@
     putExtensions exts
     return ()
 
-encodeHandshakeContent (ServerHello version random session cipherID 
compressionID exts) =
+encodeHandshakeContent (ServerHello version random session cipherid 
compressionID exts) =
     putVersion version >> putServerRandom32 random >> putSession session
-                       >> putWord16 cipherID >> putWord8 compressionID
+                       >> putWord16 cipherid >> putWord8 compressionID
                        >> putExtensions exts >> return ()
 
 encodeHandshakeContent (Certificates cc) = putOpaque24 (runPut $ mapM_ 
putOpaque24 certs)
@@ -581,6 +581,14 @@
  -}
 type PRF = Bytes -> Bytes -> Int -> Bytes
 
+-- | The TLS12 PRF is cipher specific, and some TLS12 algorithms use SHA384
+-- instead of the default SHA256.
+getPRF :: Version -> Cipher -> PRF
+getPRF ver ciph
+    | ver < TLS12 = prf_MD5SHA1
+    | maybe True (< TLS12) (cipherMinVer ciph) = prf_SHA256
+    | otherwise = prf_TLS ver $ maybe SHA256 id $ cipherPRFHash ciph
+
 generateMasterSecret_SSL :: ByteArrayAccess preMaster => preMaster -> 
ClientRandom -> ServerRandom -> Bytes
 generateMasterSecret_SSL premasterSecret (ClientRandom c) (ServerRandom s) =
     B.concat $ map (computeMD5) ["A","BB","CCC"]
@@ -592,12 +600,16 @@
     prf (B.convert premasterSecret) seed 48
   where seed = B.concat [ "master secret", c, s ]
 
-generateMasterSecret :: ByteArrayAccess preMaster => Version -> preMaster -> 
ClientRandom -> ServerRandom -> Bytes
-generateMasterSecret SSL2  = generateMasterSecret_SSL
-generateMasterSecret SSL3  = generateMasterSecret_SSL
-generateMasterSecret TLS10 = generateMasterSecret_TLS prf_MD5SHA1
-generateMasterSecret TLS11 = generateMasterSecret_TLS prf_MD5SHA1
-generateMasterSecret TLS12 = generateMasterSecret_TLS prf_SHA256
+generateMasterSecret :: ByteArrayAccess preMaster
+                     => Version
+                     -> Cipher
+                     -> preMaster
+                     -> ClientRandom
+                     -> ServerRandom
+                     -> Bytes
+generateMasterSecret SSL2 _ = generateMasterSecret_SSL
+generateMasterSecret SSL3 _ = generateMasterSecret_SSL
+generateMasterSecret v    c = generateMasterSecret_TLS $ getPRF v c
 
 generateKeyBlock_TLS :: PRF -> ClientRandom -> ServerRandom -> Bytes -> Int -> 
Bytes
 generateKeyBlock_TLS prf (ClientRandom c) (ServerRandom s) mastersecret kbsize 
=
@@ -610,12 +622,16 @@
         computeMD5  label = hash MD5 $ B.concat [ mastersecret, computeSHA1 
label ]
         computeSHA1 label = hash SHA1 $ B.concat [ label, mastersecret, s, c ]
 
-generateKeyBlock :: Version -> ClientRandom -> ServerRandom -> Bytes -> Int -> 
Bytes
-generateKeyBlock SSL2  = generateKeyBlock_SSL
-generateKeyBlock SSL3  = generateKeyBlock_SSL
-generateKeyBlock TLS10 = generateKeyBlock_TLS prf_MD5SHA1
-generateKeyBlock TLS11 = generateKeyBlock_TLS prf_MD5SHA1
-generateKeyBlock TLS12 = generateKeyBlock_TLS prf_SHA256
+generateKeyBlock :: Version
+                 -> Cipher
+                 -> ClientRandom
+                 -> ServerRandom
+                 -> Bytes
+                 -> Int
+                 -> Bytes
+generateKeyBlock SSL2 _ = generateKeyBlock_SSL
+generateKeyBlock SSL3 _ = generateKeyBlock_SSL
+generateKeyBlock v    c = generateKeyBlock_TLS $ getPRF v c
 
 generateFinished_TLS :: PRF -> Bytes -> Bytes -> HashCtx -> Bytes
 generateFinished_TLS prf label mastersecret hashctx = prf mastersecret seed 12
@@ -632,17 +648,23 @@
         pad2     = B.replicate 48 0x5c
         pad1     = B.replicate 48 0x36
 
-generateClientFinished :: Version -> Bytes -> HashCtx -> Bytes
-generateClientFinished ver
+generateClientFinished :: Version
+                       -> Cipher
+                       -> Bytes
+                       -> HashCtx
+                       -> Bytes
+generateClientFinished ver ciph
     | ver < TLS10 = generateFinished_SSL "CLNT"
-    | ver < TLS12 = generateFinished_TLS prf_MD5SHA1 "client finished"
-    | otherwise   = generateFinished_TLS prf_SHA256 "client finished"
+    | otherwise   = generateFinished_TLS (getPRF ver ciph) "client finished"
 
-generateServerFinished :: Version -> Bytes -> HashCtx -> Bytes
-generateServerFinished ver
+generateServerFinished :: Version
+                       -> Cipher
+                       -> Bytes
+                       -> HashCtx
+                       -> Bytes
+generateServerFinished ver ciph
     | ver < TLS10 = generateFinished_SSL "SRVR"
-    | ver < TLS12 = generateFinished_TLS prf_MD5SHA1 "server finished"
-    | otherwise   = generateFinished_TLS prf_SHA256 "server finished"
+    | otherwise   = generateFinished_TLS (getPRF ver ciph) "server finished"
 
 generateCertificateVerify_SSL :: Bytes -> HashCtx -> Bytes
 generateCertificateVerify_SSL = generateFinished_SSL ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS/Parameters.hs 
new/tls-1.3.9/Network/TLS/Parameters.hs
--- old/tls-1.3.8/Network/TLS/Parameters.hs     2016-05-12 08:01:28.000000000 
+0200
+++ new/tls-1.3.9/Network/TLS/Parameters.hs     2016-12-17 12:09:25.000000000 
+0100
@@ -88,6 +88,8 @@
     , clientWantSessionResume         :: Maybe (SessionID, SessionData)
     , clientShared                    :: Shared
     , clientHooks                     :: ClientHooks
+      -- | In this element, you'll  need to override the default empty value of
+      -- of 'supportedCiphers' with a suitable cipherlist.
     , clientSupported                 :: Supported
     , clientDebug                     :: DebugParams
     } deriving (Show)
@@ -144,7 +146,9 @@
       -- On the client side, the highest version will be used to establish the 
connection.
       -- On the server side, the highest version that is less or equal than 
the client version will be chosed.
       supportedVersions       :: [Version]
-      -- | Supported cipher methods
+      -- | Supported cipher methods.  The default is empty, specify a suitable
+      -- cipher list.  'Network.TLS.Extra.Cipher.ciphersuite_default' is often
+      -- a good choice.
     , supportedCiphers        :: [Cipher]
       -- | supported compressions methods
     , supportedCompressions   :: [Compression]
@@ -182,9 +186,11 @@
     , supportedCiphers        = []
     , supportedCompressions   = [nullCompression]
     , supportedHashSignatures = [ (Struct.HashSHA512, SignatureRSA)
+                                , (Struct.HashSHA512, SignatureECDSA)
                                 , (Struct.HashSHA384, SignatureRSA)
+                                , (Struct.HashSHA384, SignatureECDSA)
                                 , (Struct.HashSHA256, SignatureRSA)
-                                , (Struct.HashSHA224, SignatureRSA)
+                                , (Struct.HashSHA256, SignatureECDSA)
                                 , (Struct.HashSHA1,   SignatureRSA)
                                 , (Struct.HashSHA1,   SignatureDSS)
                                 ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Network/TLS.hs new/tls-1.3.9/Network/TLS.hs
--- old/tls-1.3.8/Network/TLS.hs        2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Network/TLS.hs        2016-09-16 08:04:43.000000000 +0200
@@ -10,13 +10,17 @@
     (
     -- * Context configuration
       ClientParams(..)
+    , HostName
+    , Bytes
     , ServerParams(..)
     , DebugParams(..)
+    , DHParams
     , ClientHooks(..)
     , ServerHooks(..)
     , Supported(..)
     , Shared(..)
     , Hooks(..)
+    , Handshake
     , Logging(..)
     , Measurement(..)
     , CertificateUsage(..)
@@ -45,7 +49,7 @@
     , Context
     , ctxConnection
     , TLSParams
-    , HasBackend
+    , HasBackend(..)
 
     -- * Creating a context
     , contextNew
@@ -62,6 +66,9 @@
 
     -- * Information gathering
     , Information(..)
+    , ClientRandom
+    , ServerRandom
+
     , unClientRandom
     , unServerRandom
     , contextGetInformation
@@ -120,13 +127,15 @@
     , exceptionValidationCache
     ) where
 
-import Network.TLS.Backend (Backend(..), HasBackend)
+import Network.TLS.Backend (Backend(..), HasBackend(..))
 import Network.TLS.Struct ( TLSError(..), TLSException(..)
                           , HashAndSignatureAlgorithm, HashAlgorithm(..), 
SignatureAlgorithm(..)
                           , Header(..), ProtocolType(..), CertificateType(..)
                           , AlertDescription(..)
-                          , ClientRandom(..), ServerRandom(..))
-import Network.TLS.Crypto (KxError(..))
+                          , ClientRandom(..), ServerRandom(..)
+                          , Bytes
+                          , Handshake)
+import Network.TLS.Crypto (KxError(..), DHParams)
 import Network.TLS.Cipher
 import Network.TLS.Hooks
 import Network.TLS.Measurement
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/Tests/Connection.hs 
new/tls-1.3.9/Tests/Connection.hs
--- old/tls-1.3.8/Tests/Connection.hs   2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/Tests/Connection.hs   2016-12-17 12:09:25.000000000 +0100
@@ -38,6 +38,7 @@
         , bulkF         = BulkBlockF $ \_ _ _ -> (\m -> (m, B.empty))
         }
     , cipherHash        = MD5
+    , cipherPRFHash     = Nothing
     , cipherKeyExchange = CipherKeyExchange_RSA
     , cipherMinVer      = Nothing
     }
@@ -56,6 +57,23 @@
     , cipherKeyExchange = CipherKeyExchange_DHE_DSS
     }
 
+blockCipherECDHE_RSA :: Cipher
+blockCipherECDHE_RSA = blockCipher
+    { cipherID   = 0xff16
+    , cipherName = "ecdhe-rsa-id-const"
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
+    }
+
+blockCipherECDHE_RSA_SHA384 :: Cipher
+blockCipherECDHE_RSA_SHA384 = blockCipher
+    { cipherID   = 0xff17
+    , cipherName = "ecdhe-rsa-id-const-sha384"
+    , cipherKeyExchange  = CipherKeyExchange_ECDHE_RSA
+    , cipherHash        = SHA384
+    , cipherPRFHash     = Just SHA384
+    , cipherMinVer      = Just TLS12
+    }
+
 streamCipher :: Cipher
 streamCipher = blockCipher
     { cipherID   = 0xff13
@@ -73,7 +91,13 @@
     passThrough _ _ = BulkStream go where go inp = (inp, BulkStream go)
 
 knownCiphers :: [Cipher]
-knownCiphers = [blockCipher,blockCipherDHE_RSA,blockCipherDHE_DSS,streamCipher]
+knownCiphers = [ blockCipher
+               , blockCipherDHE_RSA
+               , blockCipherDHE_DSS
+               , blockCipherECDHE_RSA
+               , blockCipherECDHE_RSA_SHA384
+               , streamCipher
+               ]
 
 knownVersions :: [Version]
 knownVersions = [SSL3,TLS10,TLS11,TLS12]
@@ -86,10 +110,16 @@
                                     return (CertificateChain [cert], priv)
                                ) [ (pubKey, privKey), (dsaPub, dsaPriv) ]
     connectVersion     <- elements knownVersions
-    let allowedVersions = [ v | v <- knownVersions, v <= connectVersion ]
+    serverCiphers      <- arbitraryCiphers `suchThat`
+                                (\cs -> or [maybe True (<= connectVersion) 
(cipherMinVer x) | x <- cs])
+    clientCiphers      <- oneof [arbitraryCiphers] `suchThat`
+                                (\cs -> or [x `elem` serverCiphers &&
+                                            maybe True (<= connectVersion) 
(cipherMinVer x) | x <- cs])
+    -- The shared ciphers may set a floor on the compatible protocol versions
+    let allowedVersions = [ v | v <- knownVersions,
+                                or [ x `elem` serverCiphers &&
+                                     maybe True (<= v) (cipherMinVer x) | x <- 
clientCiphers ]]
     serAllowedVersions <- (:[]) `fmap` elements allowedVersions
-    serverCiphers      <- arbitraryCiphers
-    clientCiphers      <- oneof [arbitraryCiphers] `suchThat` (\cs -> or [x 
`elem` serverCiphers | x <- cs])
     secNeg             <- arbitrary
 
 
@@ -155,10 +185,15 @@
 
     (cCtx, sCtx) <- newPairContext pipe params
 
-    _ <- forkIO $ E.catch (tlsServer sCtx resultQueue) (printAndRaise "server")
-    _ <- forkIO $ E.catch (tlsClient startQueue cCtx) (printAndRaise "client")
+    _ <- forkIO $ E.catch (tlsServer sCtx resultQueue)
+                          (printAndRaise "server" (serverSupported $ snd 
params))
+    _ <- forkIO $ E.catch (tlsClient startQueue cCtx)
+                          (printAndRaise "client" (clientSupported $ fst 
params))
 
     return (startQueue, resultQueue)
   where
-        printAndRaise :: String -> E.SomeException -> IO ()
-        printAndRaise s e = putStrLn (s ++ " exception: " ++ show e) >> 
E.throw e
+        printAndRaise :: String -> Supported -> E.SomeException -> IO ()
+        printAndRaise s supported e = do
+            putStrLn $ s ++ " exception: " ++ show e ++
+                           ", supported: " ++ show supported
+            E.throw e
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tls-1.3.8/tls.cabal new/tls-1.3.9/tls.cabal
--- old/tls-1.3.8/tls.cabal     2016-05-12 08:01:28.000000000 +0200
+++ new/tls-1.3.9/tls.cabal     2016-12-17 12:54:03.000000000 +0100
@@ -1,5 +1,5 @@
 Name:                tls
-Version:             1.3.8
+Version:             1.3.9
 Description:
    Native Haskell TLS and SSL protocol implementation for server and client.
    .
@@ -23,7 +23,6 @@
 Category:            Network
 stability:           experimental
 Cabal-Version:       >=1.8
-Tested-With:         GHC == 7.0.4, GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, 
GHC == 7.10.3, GHC == 8.0.1
 Homepage:            http://github.com/vincenthz/hs-tls
 extra-source-files:  Tests/*.hs
                      CHANGELOG.md
@@ -49,13 +48,13 @@
                    , data-default-class
                    -- crypto related
                    , memory
-                   , cryptonite >= 0.15
+                   , cryptonite >= 0.21
                    -- certificate related
                    , asn1-types >= 0.2.0
                    , asn1-encoding
-                   , x509 >= 1.6.2 && < 1.7.0
+                   , x509 >= 1.6.5 && < 1.7.0
                    , x509-store >= 1.6
-                   , x509-validation >= 1.6.3 && < 1.7.0
+                   , x509-validation >= 1.6.5 && < 1.7.0
                    , async
   if flag(network)
     Build-Depends:   network
@@ -122,6 +121,12 @@
   type:              exitcode-stdio-1.0
   hs-source-dirs:    Tests
   Main-is:           Tests.hs
+  other-modules:     Certificate
+                     Ciphers
+                     Connection
+                     Marshalling
+                     PipeChan
+                     PubKey
   Build-Depends:     base >= 3 && < 5
                    , mtl
                    , cereal >= 0.3
@@ -157,5 +162,5 @@
 
 source-repository head
   type: git
-  location: git://github.com/vincenthz/hs-tls
+  location: https://github.com/vincenthz/hs-tls
   subdir: core


Reply via email to