packages feed

quic 0.2.22 → 0.2.23

raw patch · 8 files changed

+176/−68 lines, 8 filesdep ~crypton

Dependency ranges changed: crypton

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # ChangeLog +## 0.2.23++* Supporting ChaCha20Poly1305 for crypton (not for Fusion)+  [#89](https://github.com/kazu-yamamoto/quic/pull/89)+ ## 0.2.22  * Using tls v2.2 and crypton-x509* v1.8.
Network/QUIC/Config.hs view
@@ -16,6 +16,7 @@     defaultSupported,  ) import Network.TLS.QUIC+import Network.TLS.Extra.Cipher  import Network.QUIC.Imports import Network.QUIC.Parameters@@ -53,6 +54,19 @@         , onConnectionEstablished = \_ -> return ()         } +defaultCiphers :: [Cipher]+defaultCiphers =+#ifdef USE_FUSION+  [ cipher13_AES_256_GCM_SHA384+  , cipher13_AES_128_GCM_SHA256+  ]+#else+  [ cipher13_CHACHA20_POLY1305_SHA256+  , cipher13_AES_256_GCM_SHA384+  , cipher13_AES_128_GCM_SHA256+  ]+#endif+ ----------------------------------------------------------------  -- | Client configuration.@@ -122,7 +136,7 @@     ClientConfig         { ccVersion = Version1         , ccVersions = [Version2, Version1]-        , ccCiphers = supportedCiphers defaultSupported+        , ccCiphers = defaultCiphers         , ccGroups = supportedGroups defaultSupported         , ccParameters = defaultParameters #if MIN_VERSION_tls(2,1,10)@@ -189,7 +203,7 @@ defaultServerConfig =     ServerConfig         { scVersions = [Version2, Version1]-        , scCiphers = supportedCiphers defaultSupported+        , scCiphers = defaultCiphers         , scGroups = supportedGroups defaultSupported         , scParameters = defaultParameters #if MIN_VERSION_tls(2,1,10)
Network/QUIC/Connection/Crypto.hs view
@@ -25,6 +25,7 @@ ) where  import Control.Concurrent.STM+import Network.TLS.Extra.Cipher import Network.TLS.QUIC  import Network.QUIC.Connection.Misc@@ -105,6 +106,9 @@  ---------------------------------------------------------------- +fusionCiphers :: [Cipher]+fusionCiphers = [cipher13_AES_128_GCM_SHA256, cipher13_AES_256_GCM_SHA384]+ initializeCoder :: Connection -> EncryptionLevel -> TrafficSecrets a -> IO () initializeCoder conn lvl sec = do     ver <-@@ -114,7 +118,7 @@     cipher <- getCipher conn lvl     avail <- isFusionAvailable     (coder, protector) <--        if useFusion && avail+        if useFusion && avail && cipher `elem` fusionCiphers             then genFusionCoder (isClient conn) ver cipher sec             else genNiteCoder (isClient conn) ver cipher sec     writeArray (coders conn) lvl coder@@ -126,7 +130,7 @@     cipher <- getCipher conn RTT1Level     avail <- isFusionAvailable     (coder, protector) <--        if useFusion && avail+        if useFusion && avail && cipher `elem` fusionCiphers             then genFusionCoder (isClient conn) ver cipher sec             else genNiteCoder (isClient conn) ver cipher sec     let coder1 = Coder1RTT coder sec@@ -142,7 +146,7 @@     let secN1 = updateSecret ver cipher secN     avail <- isFusionAvailable     coderN1 <--        if useFusion && avail+        if useFusion && avail && cipher `elem` fusionCiphers             then genFusionCoder1RTT (isClient conn) ver cipher secN1 coder             else genNiteCoder1RTT (isClient conn) ver cipher secN1 coder     let nextCoder = Coder1RTT coderN1 secN1
Network/QUIC/Crypto/Fusion.hs view
@@ -36,9 +36,9 @@  fusionSetup :: Cipher -> FusionContext -> Key -> IV -> IO () fusionSetup cipher-  | cipher == cipher_TLS13_AES128GCM_SHA256        = fusionSetupAES128-  | cipher == cipher_TLS13_AES256GCM_SHA384        = fusionSetupAES256-  | otherwise                                      = error "fusionSetup"+  | cipher == cipher13_AES_128_GCM_SHA256 = fusionSetupAES128+  | cipher == cipher13_AES_256_GCM_SHA384 = fusionSetupAES256+  | otherwise                             = error "fusionSetup"  fusionSetupAES128 :: FusionContext -> Key -> IV -> IO () fusionSetupAES128 (FC fctx) (Key key) (IV iv) = withForeignPtr fctx $ \pctx ->@@ -88,8 +88,8 @@   SP <$> (c_supplement_new hpkeyp keylen >>= newForeignPtr p_supplement_free)  where   keylen-    | cipher == cipher_TLS13_AES128GCM_SHA256 = 16-    | otherwise                               = 32+    | cipher == cipher13_AES_128_GCM_SHA256 = 16+    | otherwise                             = 32  fusionSetSample :: Supplement -> Buffer -> IO () fusionSetSample (SP fsupp) p = withForeignPtr fsupp $ \psupp ->
Network/QUIC/Crypto/Nite.hs view
@@ -15,6 +15,8 @@ ) where  import Crypto.Cipher.AES+import qualified Crypto.Cipher.ChaCha as ChaCha+import Crypto.Cipher.ChaChaPoly1305 (aeadChacha20poly1305Init) import Crypto.Cipher.Types hiding (Cipher, IV) import Crypto.Error (maybeCryptoError) import qualified Data.ByteArray as Byte (convert)@@ -39,66 +41,60 @@ -- it's impossible. cipherEncrypt     :: Cipher -> Key -> Nonce -> PlainText -> AssDat -> Maybe (CipherText, CipherText)-cipherEncrypt cipher-    | cipher == cipher13_AES_128_GCM_SHA256 = aes128gcmEncrypt+cipherEncrypt cipher (Key key) (Nonce nonce)+    | cipher == cipher13_AES_128_GCM_SHA256 =+        quicAeadEncrypt (aesGCMInit key nonce :: Maybe (AEAD AES128)) 16     | cipher == cipher13_AES_128_CCM_SHA256 = error "cipher13_AES_128_CCM_SHA256"-    | cipher == cipher13_AES_256_GCM_SHA384 = aes256gcmEncrypt+    | cipher == cipher13_AES_256_GCM_SHA384 =+        quicAeadEncrypt (aesGCMInit key nonce :: Maybe (AEAD AES256)) 16+    | cipher == cipher13_CHACHA20_POLY1305_SHA256 =+        quicAeadEncrypt (maybeCryptoError $ aeadChacha20poly1305Init key nonce) 16     | otherwise = error "cipherEncrypt"  cipherDecrypt     :: Cipher -> Key -> Nonce -> CipherText -> AssDat -> Maybe PlainText-cipherDecrypt cipher-    | cipher == cipher13_AES_128_GCM_SHA256 = aes128gcmDecrypt+cipherDecrypt cipher (Key key) (Nonce nonce)+    | cipher == cipher13_AES_128_GCM_SHA256 =+        quicAeadDecrypt (aesGCMInit key nonce :: Maybe (AEAD AES128)) 16     | cipher == cipher13_AES_128_CCM_SHA256 = error "cipher13_AES_128_CCM_SHA256"-    | cipher == cipher13_AES_256_GCM_SHA384 = aes256gcmDecrypt+    | cipher == cipher13_AES_256_GCM_SHA384 =+        quicAeadDecrypt (aesGCMInit key nonce :: Maybe (AEAD AES256)) 16+    | cipher == cipher13_CHACHA20_POLY1305_SHA256 =+        quicAeadDecrypt (maybeCryptoError $ aeadChacha20poly1305Init key nonce) 16     | otherwise = error "cipherDecrypt"  -- IMPORTANT: Using 'let' so that parameters can be memorized.-aes128gcmEncrypt-    :: Key -> (Nonce -> PlainText -> AssDat -> Maybe (CipherText, CipherText))-aes128gcmEncrypt (Key key) = case maybeCryptoError $ cipherInit key of-    Nothing -> \_ _ _ -> Nothing-    Just (aes :: AES128) -> \(Nonce nonce) plaintext (AssDat ad) ->-        case maybeCryptoError $ aeadInit AEAD_GCM aes nonce of-            Nothing -> Nothing-            Just aead ->-                let (AuthTag tag0, ciphertext) = aeadSimpleEncrypt aead ad plaintext 16-                    tag = Byte.convert tag0-                 in Just (ciphertext, tag)+quicAeadEncrypt+    :: Maybe (AEAD cipher)+    -> Int+    -> PlainText+    -> AssDat+    -> Maybe (CipherText, CipherText)+quicAeadEncrypt Nothing _ = \_ _ -> Nothing+quicAeadEncrypt (Just aead) tagLen = \plaintext (AssDat ad) ->+    let (AuthTag tag0, ciphertext) = aeadSimpleEncrypt aead ad plaintext tagLen+        tag = Byte.convert tag0+     in Just (ciphertext, tag) -aes128gcmDecrypt :: Key -> (Nonce -> CipherText -> AssDat -> Maybe PlainText)-aes128gcmDecrypt (Key key) = case maybeCryptoError $ cipherInit key of-    Nothing -> \_ _ _ -> Nothing-    Just (aes :: AES128) -> \(Nonce nonce) ciphertag (AssDat ad) ->-        case maybeCryptoError $ aeadInit AEAD_GCM aes nonce of-            Nothing -> Nothing-            Just aead ->-                let (ciphertext, tag) = BS.splitAt (BS.length ciphertag - 16) ciphertag-                    authtag = AuthTag $ Byte.convert tag-                 in aeadSimpleDecrypt aead ad ciphertext authtag+quicAeadDecrypt+    :: Maybe (AEAD cipher) -> Int -> CipherText -> AssDat -> Maybe PlainText+quicAeadDecrypt Nothing _ = \_ _ -> Nothing+quicAeadDecrypt (Just aead) tagLen = \ciphertag (AssDat ad) ->+    let (ciphertext, tag) = BS.splitAt (BS.length ciphertag - tagLen) ciphertag+        authtag = AuthTag $ Byte.convert tag+     in aeadSimpleDecrypt aead ad ciphertext authtag -aes256gcmEncrypt-    :: Key -> (Nonce -> PlainText -> AssDat -> Maybe (CipherText, CipherText))-aes256gcmEncrypt (Key key) = case maybeCryptoError $ cipherInit key of-    Nothing -> \_ _ _ -> Nothing-    Just (aes :: AES256) -> \(Nonce nonce) plaintext (AssDat ad) ->-        case maybeCryptoError $ aeadInit AEAD_GCM aes nonce of-            Nothing -> Nothing-            Just aead ->-                let (AuthTag tag0, ciphertext) = aeadSimpleEncrypt aead ad plaintext 16-                    tag = Byte.convert tag0-                 in Just (ciphertext, tag)+aesGCMInit+    :: BlockCipher cipher => ByteString -> ByteString -> Maybe (AEAD cipher)+aesGCMInit key nonce =+    case maybeCryptoError $ cipherInit key of+        Nothing -> Nothing+        Just aes -> maybeCryptoError $ aeadInit AEAD_GCM aes nonce -aes256gcmDecrypt :: Key -> (Nonce -> CipherText -> AssDat -> Maybe PlainText)-aes256gcmDecrypt (Key key) = case maybeCryptoError $ cipherInit key of-    Nothing -> \_ _ _ -> Nothing-    Just (aes :: AES256) -> \(Nonce nonce) ciphertag (AssDat ad) ->-        case maybeCryptoError $ aeadInit AEAD_GCM aes nonce of-            Nothing -> Nothing-            Just aead ->-                let (ciphertext, tag) = BS.splitAt (BS.length ciphertag - 16) ciphertag-                    authtag = AuthTag $ Byte.convert tag-                 in aeadSimpleDecrypt aead ad ciphertext authtag+aes128gcmEncrypt+    :: Key -> Nonce -> PlainText -> AssDat -> Maybe (CipherText, CipherText)+aes128gcmEncrypt (Key key) (Nonce nonce) =+    quicAeadEncrypt (aesGCMInit key nonce :: Maybe (AEAD AES128)) 16  ---------------------------------------------------------------- @@ -228,6 +224,7 @@     | cipher == cipher13_AES_128_GCM_SHA256 = aes128ecbEncrypt key     | cipher == cipher13_AES_128_CCM_SHA256 = error "cipher13_AES_128_CCM_SHA256 "     | cipher == cipher13_AES_256_GCM_SHA384 = aes256ecbEncrypt key+    | cipher == cipher13_CHACHA20_POLY1305_SHA256 = chacha20HeaderProtection key     | otherwise =         error "cipherHeaderProtection" @@ -248,6 +245,15 @@          in \(Sample sample) ->                 let mask = encrypt sample                  in Mask mask++chacha20HeaderProtection :: Key -> (Sample -> Mask)+chacha20HeaderProtection (Key key) (Sample sample) =+    Mask $ fst $ ChaCha.combine st "\x00\x00\x00\x00\x00"+  where+    st = ChaCha.setCounter32 counter $ ChaCha.initialize 20 key nonce+    nonce = BS.drop 4 sample+    counter = idx 0 + idx 1 * 256 + idx 2 * 65536 + idx 3 * 16777216+    idx i = fromIntegral (sample `BS.index` i)  ---------------------------------------------------------------- 
Network/QUIC/Crypto/Utils.hs view
@@ -30,6 +30,7 @@     | cipher == cipher13_AES_128_GCM_SHA256 = 16     | cipher == cipher13_AES_128_CCM_SHA256 = 16     | cipher == cipher13_AES_256_GCM_SHA384 = 16+    | cipher == cipher13_CHACHA20_POLY1305_SHA256 = 16     | otherwise = error "tagLength"  sampleLength :: Cipher -> Int@@ -37,6 +38,7 @@     | cipher == cipher13_AES_128_GCM_SHA256 = 16     | cipher == cipher13_AES_128_CCM_SHA256 = 16     | cipher == cipher13_AES_256_GCM_SHA384 = 16+    | cipher == cipher13_CHACHA20_POLY1305_SHA256 = 16     | otherwise = error "sampleLength"  ----------------------------------------------------------------
quic.cabal view
@@ -1,6 +1,6 @@ cabal-version:      >=1.10 name:               quic-version:            0.2.22+version:            0.2.23 license:            BSD3 license-file:       LICENSE maintainer:         kazu@iij.ad.jp@@ -135,7 +135,7 @@         bytestring >=0.10,         containers,         crypto-token >=0.1.2 && <0.2,-        crypton >=0.34,+        crypton >=1.0.5,         crypton-x509 >=1.8.0 && <1.9,         crypton-x509-store >=1.8.0 && <1.9,         crypton-x509-system >=1.8.0 && <1.9,@@ -266,3 +266,10 @@      if os(windows)         ghc-options: -with-rtsopts=--io-manager=native++    if (flag(fusion) && arch(x86_64))+        cpp-options: -DUSE_FUSION+        cc-options:  -mavx2 -maes -mpclmul -mvaes -mvpclmulqdq+        c-sources:+            cbits/fusion.c+            cbits/picotls.c
test/TLSSpec.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -6,6 +7,7 @@ import Data.Bits import qualified Data.ByteString as BS import Data.Maybe+import Network.TLS.Extra.Cipher import Test.Hspec  import Network.QUIC.Internal@@ -22,9 +24,12 @@  spec :: Spec spec = do+    ----------------------------------------------------------------+    -- RFC 9001+    --     describe "test vector for version 1" $ do         let ver = Version1-        it "describes the examples of Keys" $ do+        it "describes the examples of Keys (RFC 9001: A.1)" $ do             ----------------------------------------------------------------             -- shared keys             let dcID = makeCID (dec16s "8394c8f03e515708")@@ -49,7 +54,7 @@             let shp = headerProtectionKey ver defaultCipher (Secret sis)             shp `shouldBe` Key (dec16 "c206b8d9b9f0f37644430b490eeaa314") -        it "describes the examples of Client Initial" $ do+        it "describes the examples of Client Initial (RFC 9001: A.2)" $ do             let dcID = makeCID (dec16s "8394c8f03e515708")                 ClientTrafficSecret cis = clientInitialSecret ver dcID                 ckey = aeadKey ver defaultCipher (Secret cis)@@ -91,7 +96,7 @@             let Mask mask = protectionMask defaultCipher chp sample             BS.take 5 mask `shouldBe` dec16 "437b9aec36" -        it "describes the examples of Server Initial" $ do+        it "describes the examples of Server Initial (RFC 9001: A.3)" $ do             let dcID = makeCID (dec16s "8394c8f03e515708")                 ServerTrafficSecret sis = serverInitialSecret ver dcID                 skey = aeadKey ver defaultCipher (Secret sis)@@ -132,7 +137,7 @@             let Mask mask = protectionMask defaultCipher shp sample             BS.take 5 mask `shouldBe` dec16 "2ec0d8356a" -        it "describes the examples of Retry" $ do+        it "describes the examples of Retry (RFC 9001: A.4)" $ do             let wire0 =                     dec16 "ff000000010008f067a5502a4262b5746f6b656e04a265ba2eff4d829058fb3f0f2496ba"             (ipkt, rest) <- decodePacket wire0 True@@ -146,7 +151,41 @@                     r0 `shouldBe` r1                 _ -> error "Retry version 1" -    describe "test vector for version 2" $ do+{- FOURMOLU_DISABLE -}+#ifndef USE_FUSION+        it+            "describes the examples of ChaCha20-Poly1305 Short Header Packet (RFC 9001: A.5)"+            $ do+                let cipher = cipher13_CHACHA20_POLY1305_SHA256+                    secret =+                        Secret $+                            dec16 "9ac312a7f877468ebe69422748ad00a15443f18203a07d6060f688f30f21632b"+                    key = aeadKey ver cipher secret+                    iv = initialVector ver cipher secret+                    hp = headerProtectionKey ver cipher secret+                    ku = nextSecret ver cipher secret+                    payloadCipherText = niteEncrypt cipher key iv (dec16 "01") (AssDat $ dec16 "4200bff4") 654360564+                    sample = Sample $ dec16 "5e5cd55c41f69080575d7999c25a5bfb"+                    mask = protectionMask cipher hp sample+                key+                    `shouldBe` Key (dec16 "c6d98ff3441c3fe1b2182094f69caa2ed4b716b65488960a7a984979fb23e1c8")+                iv+                    `shouldBe` IV (dec16 "e0459b3474bdd0e44a41c144")+                hp+                    `shouldBe` Key (dec16 "25a282b9e82f06f21f488917a4fc8f1b73573685608597d0efcb076b0ab7a7a4")+                ku+                    `shouldBe` Secret+                        (dec16 "1223504755036d556342ee9361d253421a826c9ecdf3c7148684b36b714881f9")+                payloadCipherText+                    `shouldBe` Just (dec16 "65", dec16 "5e5cd55c41f69080575d7999c25a5bfb")+                mask `shouldBe` Mask (dec16 "aefefe7d03")+#endif+{- FOURMOLU_ENSABLE -}++    ----------------------------------------------------------------+    -- RFC 9369+    --+    describe "test vector for version 2 (RFC 9369: A1)" $ do         let ver = Version2         it "describes the examples of Keys" $ do             ----------------------------------------------------------------@@ -173,7 +212,7 @@             let shp = headerProtectionKey ver defaultCipher (Secret sis)             shp `shouldBe` Key (dec16 "edf6d05c83121201b436e16877593c3a") -        it "describes the examples of Client Initial" $ do+        it "describes the examples of Client Initial (RFC 9369: A2)" $ do             let dcID = makeCID (dec16s "8394c8f03e515708")                 ClientTrafficSecret cis = clientInitialSecret ver dcID                 ckey = aeadKey ver defaultCipher (Secret cis)@@ -215,7 +254,7 @@             let Mask mask = protectionMask defaultCipher chp sample             BS.take 5 mask `shouldBe` dec16 "94a0c95e80" -        it "describes the examples of Server Initial" $ do+        it "describes the examples of Server Initial (RFC 9369: A3)" $ do             let dcID = makeCID (dec16s "8394c8f03e515708")                 ServerTrafficSecret sis = serverInitialSecret ver dcID                 skey = aeadKey ver defaultCipher (Secret sis)@@ -256,7 +295,7 @@             let Mask mask = protectionMask defaultCipher shp sample             BS.take 5 mask `shouldBe` dec16 "4dd92e91ea" -        it "describes the examples of Retry" $ do+        it "describes the examples of Retry (RFC 9369: A4)" $ do             let wire0 =                     dec16 "cf6b3343cf0008f067a5502a4262b5746f6b656ec8646ce8bfe33952d955543665dcc7b6"             (ipkt, rest) <- decodePacket wire0 True@@ -269,6 +308,37 @@                     f0 .&. 0xf0 `shouldBe` f1 .&. 0xf0                     r0 `shouldBe` r1                 _ -> error "Retry version 2"++{- FOURMOLU_DISABLE -}+#ifndef USE_FUSION+        it+            "describes the examples of ChaCha20-Poly1305 Short Header Packet (RFC 9369: A.5)"+            $ do+                let cipher = cipher13_CHACHA20_POLY1305_SHA256+                    secret =+                        Secret $+                            dec16 "9ac312a7f877468ebe69422748ad00a15443f18203a07d6060f688f30f21632b"+                    key = aeadKey ver cipher secret+                    iv = initialVector ver cipher secret+                    hp = headerProtectionKey ver cipher secret+                    ku = nextSecret ver cipher secret+                    payloadCipherText = niteEncrypt cipher key iv (dec16 "01") (AssDat $ dec16 "4200bff4") 654360564+                    sample = Sample $ dec16 "e7b6b932bc27d786f4bc2bb20f2162ba"+                    mask = protectionMask cipher hp sample+                key+                    `shouldBe` Key (dec16 "3bfcddd72bcf02541d7fa0dd1f5f9eeea817e09a6963a0e6c7df0f9a1bab90f2")+                iv+                    `shouldBe` IV (dec16 "a6b5bc6ab7dafce30ffff5dd")+                hp+                    `shouldBe` Key (dec16 "d659760d2ba434a226fd37b35c69e2da8211d10c4f12538787d65645d5d1b8e2")+                ku+                    `shouldBe` Secret+                        (dec16 "c69374c49e3d2a9466fa689e49d476db5d0dfbc87d32ceeaa6343fd0ae4c7d88")+                payloadCipherText+                    `shouldBe` Just (dec16 "0a", dec16 "e7b6b932bc27d786f4bc2bb20f2162ba")+                mask `shouldBe` Mask (dec16 "97580e32bf")+#endif+{- FOURMOLU_ENABLE -}  serverCRYPTOframe :: BS.ByteString serverCRYPTOframe =