diff --git a/src/Simplex/Messaging/Protocol.hs b/src/Simplex/Messaging/Protocol.hs index 9e7faf2d3..459f9a0df 100644 --- a/src/Simplex/Messaging/Protocol.hs +++ b/src/Simplex/Messaging/Protocol.hs @@ -244,11 +244,19 @@ supportedSMPClientVRange = mkVersionRange initialSMPClientVersion currentSMPClie maxMessageLength :: Int maxMessageLength = 16088 +-- without signature works with min 16151 (fails with 16150) +-- with Ed448: 16265 (fails with 16264) +-- with Ed25519: 16215 (fails with 16214) +-- with X25519: 16232 (fails with 16231) paddedProxiedMsgLength :: Int -paddedProxiedMsgLength = 16388 +paddedProxiedMsgLength = 16232 +-- without signature works with min 16239 (fails with 16238) +-- with Ed448: 16353 (fails with 16352) +-- with Ed25519: 16303 (fails with 16302) +-- with X25519: 16320 (fails with 16319) paddedForwardedMsgLength :: Int -paddedForwardedMsgLength = 16688 +paddedForwardedMsgLength = 16320 type MaxMessageLen = 16088 diff --git a/src/Simplex/Messaging/Transport.hs b/src/Simplex/Messaging/Transport.hs index 3b37e4006..33aae5c60 100644 --- a/src/Simplex/Messaging/Transport.hs +++ b/src/Simplex/Messaging/Transport.hs @@ -115,8 +115,13 @@ import UnliftIO.STM -- * Transport parameters +-- min size it works with: +-- unsigned message: 16292 (paddedProxiedMsgLength = 16151, paddedForwardedMsgLength = 16239) +-- Ed448: 16406 (16384 + 22, fails with 21) +-- Ed25519: 16356 +-- X25519: 16381 smpBlockSize :: Int -smpBlockSize = 16384 + 1024 +smpBlockSize = 16384 -- SMP protocol version history: -- 1 - binary protocol encoding (1/1/2022) diff --git a/tests/SMPProxyTests.hs b/tests/SMPProxyTests.hs index 1fe20943f..1ab2779c8 100644 --- a/tests/SMPProxyTests.hs +++ b/tests/SMPProxyTests.hs @@ -11,7 +11,7 @@ module SMPProxyTests where import AgentTests.FunctionalAPITests (runRight_) -import Debug.Trace +import Data.ByteString.Char8 (ByteString) import SMPAgentClient (testSMPServer, testSMPServer2) import SMPClient import qualified SMPClient as SMP @@ -43,37 +43,75 @@ smpProxyTests = do withSmpServerConfigOn (transport @TLS) proxyCfg testPort $ \_ -> do let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash let relayServ = proxyServ - deliverMessageViaProxy proxyServ relayServ + deliverMessageViaProxy proxyServ relayServ C.SEd448 "hello 1" "hello 2" it "different servers" $ withSmpServerConfigOn (transport @TLS) proxyCfg testPort $ \_ -> withSmpServerConfigOn (transport @TLS) cfgV7 testPort2 $ \_ -> do let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash let relayServ = SMPServer SMP.testHost SMP.testPort2 SMP.testKeyHash - deliverMessageViaProxy proxyServ relayServ + deliverMessageViaProxy proxyServ relayServ C.SEd448 "hello 1" "hello 2" + xit "max message size, Ed448 keys" $ + withSmpServerConfigOn (transport @TLS) proxyCfg testPort $ \_ -> + withSmpServerConfigOn (transport @TLS) cfgV7 testPort2 $ \_ -> do + g <- C.newRandom + msg <- atomically $ C.randomBytes maxMessageLength g + msg' <- atomically $ C.randomBytes maxMessageLength g + let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash + let relayServ = SMPServer SMP.testHost SMP.testPort2 SMP.testKeyHash + deliverMessageViaProxy proxyServ relayServ C.SEd448 msg msg' + it "max message size, Ed25519 keys" $ + withSmpServerConfigOn (transport @TLS) proxyCfg testPort $ \_ -> + withSmpServerConfigOn (transport @TLS) cfgV7 testPort2 $ \_ -> do + g <- C.newRandom + msg <- atomically $ C.randomBytes maxMessageLength g + msg' <- atomically $ C.randomBytes maxMessageLength g + let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash + let relayServ = SMPServer SMP.testHost SMP.testPort2 SMP.testKeyHash + deliverMessageViaProxy proxyServ relayServ C.SEd25519 msg msg' + it "max message size, X25519 keys" $ + withSmpServerConfigOn (transport @TLS) proxyCfg testPort $ \_ -> + withSmpServerConfigOn (transport @TLS) cfgV7 testPort2 $ \_ -> do + g <- C.newRandom + msg <- atomically $ C.randomBytes maxMessageLength g + msg' <- atomically $ C.randomBytes maxMessageLength g + let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash + let relayServ = SMPServer SMP.testHost SMP.testPort2 SMP.testKeyHash + deliverMessageViaProxy proxyServ relayServ C.SX25519 msg msg' xit "sender-proxy-relay-recipient works" todo xit "similar timing for proxied and direct sends" todo -deliverMessageViaProxy :: SMPServer -> SMPServer -> IO () -deliverMessageViaProxy proxyServ relayServ = do +deliverMessageViaProxy :: (C.AlgorithmI a, C.AuthAlgorithm a) => SMPServer -> SMPServer -> C.SAlgorithm a -> ByteString -> ByteString -> IO () +deliverMessageViaProxy proxyServ relayServ alg msg msg' = do g <- C.newRandom -- set up proxy Right pc <- getProtocolClient g (1, proxyServ, Nothing) defaultSMPClientConfig {serverVRange = mkVersionRange batchCmdsSMPVersion sendingProxySMPVersion} Nothing (\_ -> pure ()) THAuthClient {} <- maybe (fail "getProtocolClient returned no thAuth") pure $ thAuth $ thParams pc -- set up relay msgQ <- newTBQueueIO 4 - Right rc <- getProtocolClient g (2, relayServ, Nothing) defaultSMPClientConfig (Just msgQ) (\_ -> pure ()) + Right rc <- getProtocolClient g (2, relayServ, Nothing) defaultSMPClientConfig {serverVRange = mkVersionRange batchCmdsSMPVersion authCmdsSMPVersion} (Just msgQ) (\_ -> pure ()) runRight_ $ do -- prepare receiving queue - (rPub, rPriv) <- atomically $ C.generateAuthKeyPair C.SEd448 g + (rPub, rPriv) <- atomically $ C.generateAuthKeyPair alg g (rdhPub, rdhPriv :: C.PrivateKeyX25519) <- atomically $ C.generateKeyPair g - QIK {sndId, rcvPublicDhKey = srvDh} <- createSMPQueue rc (rPub, rPriv) rdhPub (Just "correct") SMSubscribe + QIK {rcvId, sndId, rcvPublicDhKey = srvDh} <- createSMPQueue rc (rPub, rPriv) rdhPub (Just "correct") SMSubscribe let dec = decryptMsgV3 $ C.dh' srvDh rdhPriv - -- run proxy test + -- get proxy session (sessId, v, relayKey) <- createSMPProxySession pc relayServ (Just "correct") - proxySMPMessage pc sessId v relayKey Nothing sndId noMsgFlags "hello" - -- check delivery + -- send via proxy to unsecured queue + proxySMPMessage pc sessId v relayKey Nothing sndId noMsgFlags msg + -- receive 1 (_tSess, _v, _sid, _ety, MSG RcvMessage {msgId, msgBody = EncRcvMsgBody encBody}) <- atomically $ readTBQueue msgQ - liftIO $ dec msgId encBody `shouldBe` Right "hello" + liftIO $ dec msgId encBody `shouldBe` Right msg + ackSMPMessage rc rPriv rcvId msgId + -- secure queue + (sPub, sPriv) <- atomically $ C.generateAuthKeyPair alg g + secureSMPQueue rc rPriv rcvId sPub + -- send via proxy to secured queue + proxySMPMessage pc sessId v relayKey (Just sPriv) sndId noMsgFlags msg' + -- receive 2 + (_tSess, _v, _sid, _ety, MSG RcvMessage {msgId = msgId', msgBody = EncRcvMsgBody encBody'}) <- atomically $ readTBQueue msgQ + liftIO $ dec msgId' encBody' `shouldBe` Right msg' + ackSMPMessage rc rPriv rcvId msgId' proxyVRange :: VersionRangeSMP proxyVRange = mkVersionRange batchCmdsSMPVersion sendingProxySMPVersion @@ -89,8 +127,7 @@ testProxyAuth :: IO () testProxyAuth = do withSmpServerConfigOn (transport @TLS) proxyCfgAuth testPort $ \_ -> do testSMPClient_ "127.0.0.1" testPort proxyVRange $ \(th :: THandleSMP TLS 'TClient) -> do - (_, s, (_corrId, _entityId, reply)) <- sendRecv th (Nothing, "0", "", PRXY testSMPServer2 $ Just "wrong") - traceShowM s + (_, _s, (_corrId, _entityId, reply)) <- sendRecv th (Nothing, "0", "", PRXY testSMPServer2 $ Just "wrong") reply `shouldBe` Right (ERR AUTH) where proxyCfgAuth = proxyCfg {newQueueBasicAuth = Just "correct"}