packages feed

tls 1.3.8 → 1.3.9

raw patch · 21 files changed

+414/−114 lines, 21 filesdep ~cryptonitedep ~x509dep ~x509-validation

Dependency ranges changed: cryptonite, x509, x509-validation

Files

CHANGELOG.md view
@@ -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.
Network/TLS.hs view
@@ -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
Network/TLS/Backend.hs view
@@ -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))
Network/TLS/Cipher.hs view
@@ -125,6 +125,7 @@     , cipherBulk         :: Bulk     , cipherKeyExchange  :: CipherKeyExchangeType     , cipherMinVer       :: Maybe Version+    , cipherPRFHash      :: Maybe Hash     }  cipherKeyBlockSize :: Cipher -> Int
Network/TLS/Context.hs view
@@ -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
Network/TLS/Context/Internal.hs view
@@ -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.
Network/TLS/Core.hs view
@@ -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
Network/TLS/Crypto.hs view
@@ -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 
Network/TLS/Crypto/ECDH.hs view
@@ -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
Network/TLS/Extension.hs view
@@ -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
Network/TLS/Extra/Cipher.hs view
@@ -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]+ciphersuite_medium = [ cipher_RC4_128_SHA1+                     , cipher_AES128_SHA1+                     ] --- | the strongest ciphers supported.+-- | 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,11 +432,37 @@     , 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     { cipherID           = 0x66@@ -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,36 +570,73 @@     , 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+    }+ cipher_ECDHE_RSA_AES128GCM_SHA256 :: Cipher cipher_ECDHE_RSA_AES128GCM_SHA256 = Cipher     { cipherID           = 0xc02f     , 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}@@ -553,6 +715,13 @@ TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA  {0xC0,0x12} 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}
Network/TLS/Handshake/Client.hs view
@@ -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
Network/TLS/Handshake/Key.hs view
@@ -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 
Network/TLS/Handshake/Server.hs view
@@ -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)
Network/TLS/Handshake/Signature.hs view
@@ -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
Network/TLS/Handshake/State.hs view
@@ -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
Network/TLS/MAC.hs view
@@ -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
Network/TLS/Packet.hs view
@@ -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 ""
Network/TLS/Parameters.hs view
@@ -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)                                 ]
Tests/Connection.hs view
@@ -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
tls.cabal view
@@ -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