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 +4/−0
- Network/TLS.hs +13/−4
- Network/TLS/Backend.hs +18/−1
- Network/TLS/Cipher.hs +1/−0
- Network/TLS/Context.hs +15/−8
- Network/TLS/Context/Internal.hs +3/−1
- Network/TLS/Core.hs +1/−1
- Network/TLS/Crypto.hs +2/−3
- Network/TLS/Crypto/ECDH.hs +3/−3
- Network/TLS/Extension.hs +1/−1
- Network/TLS/Extra/Cipher.hs +197/−28
- Network/TLS/Handshake/Client.hs +2/−2
- Network/TLS/Handshake/Key.hs +6/−6
- Network/TLS/Handshake/Server.hs +15/−9
- Network/TLS/Handshake/Signature.hs +4/−4
- Network/TLS/Handshake/State.hs +14/−4
- Network/TLS/MAC.hs +8/−0
- Network/TLS/Packet.hs +45/−23
- Network/TLS/Parameters.hs +8/−2
- Tests/Connection.hs +43/−8
- tls.cabal +11/−6
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