From 2d1609f222a38250db49d43998743d9bf52fc3a5 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Fri, 19 Apr 2024 20:24:25 +0100 Subject: [PATCH] update envelope sizes for proxied messages, remove unnecessary proxy-relay encryption padding (#1107) * update envelope sizes for proxied messages * remove unnecessary padding from proxy-relay encryption --- src/Simplex/Messaging/Client.hs | 4 ++-- src/Simplex/Messaging/Protocol.hs | 26 +++++++++----------------- src/Simplex/Messaging/Server.hs | 7 ++++--- src/Simplex/Messaging/Transport.hs | 5 ----- tests/SMPProxyTests.hs | 15 ++++++++------- tests/ServerTests.hs | 4 ++-- 6 files changed, 25 insertions(+), 36 deletions(-) diff --git a/src/Simplex/Messaging/Client.hs b/src/Simplex/Messaging/Client.hs index 11243b4e0..8d4db29d9 100644 --- a/src/Simplex/Messaging/Client.hs +++ b/src/Simplex/Messaging/Client.hs @@ -732,12 +732,12 @@ forwardSMPMessage c@ProtocolClient {thParams, client_ = PClient {clientCorrId = nonce <- liftIO . atomically $ C.randomCbNonce g -- wrap let fwdT = FwdTransmission {fwdCorrId, fwdKey, fwdTransmission} - eft <- liftEitherWith PCECryptoError $ EncFwdTransmission <$> C.cbEncrypt sessSecret nonce (smpEncode fwdT) paddedForwardedMsgLength + eft = EncFwdTransmission $ C.cbEncryptNoPad sessSecret nonce (smpEncode fwdT) -- send sendProtocolCommand_ c (Just nonce) Nothing "" (Cmd SSender (RFWD eft)) >>= \case RRES (EncFwdResponse efr) -> do -- unwrap - r' <- liftEitherWith PCECryptoError $ C.cbDecrypt sessSecret (C.reverseNonce nonce) efr + r' <- liftEitherWith PCECryptoError $ C.cbDecryptNoPad sessSecret (C.reverseNonce nonce) efr FwdResponse {fwdCorrId = _, fwdResponse} <- liftEitherWith (const $ PCEResponseError BLOCK) $ smpDecode r' pure fwdResponse r -> throwE . PCEUnexpectedResponse $ bshow r diff --git a/src/Simplex/Messaging/Protocol.hs b/src/Simplex/Messaging/Protocol.hs index fafd8a340..118f3b084 100644 --- a/src/Simplex/Messaging/Protocol.hs +++ b/src/Simplex/Messaging/Protocol.hs @@ -44,7 +44,6 @@ module Simplex.Messaging.Protocol supportedSMPClientVRange, maxMessageLength, paddedProxiedMsgLength, - paddedForwardedMsgLength, e2eEncConfirmationLength, e2eEncMessageLength, @@ -243,23 +242,16 @@ currentSMPClientVersion = VersionSMPC 2 supportedSMPClientVRange :: VersionRangeSMPC supportedSMPClientVRange = mkVersionRange initialSMPClientVersion currentSMPClientVersion -maxMessageLength :: Int -maxMessageLength = 16088 +-- TODO v6.0 remove dependency on version +maxMessageLength :: VersionSMP -> Int +maxMessageLength v + | v >= sendingProxySMPVersion = 16064 -- max 16067 + | otherwise = 16088 -- 16064 - always use this size to determine allowed ranges --- 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 = 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 = 16320 +paddedProxiedMsgLength = 16244 -- 16241 .. 16245 +-- TODO v6.0 change to 16064 type MaxMessageLen = 16088 -- 16 extra bytes: 8 for timestamp and 8 for flags (7 flags and the space, only 1 flag is currently used) @@ -267,10 +259,10 @@ type MaxRcvMessageLen = MaxMessageLen + 16 -- 16104, the padded size is 16106 -- it is shorter to allow per-queue e2e encryption DH key in the "public" header e2eEncConfirmationLength :: Int -e2eEncConfirmationLength = 15936 +e2eEncConfirmationLength = 15920 -- 15881 .. 15976 e2eEncMessageLength :: Int -e2eEncMessageLength = 16032 +e2eEncMessageLength = 16016 -- 16004 .. 16021 -- | SMP protocol clients data Party = Recipient | Sender | Notifier | ProxiedClient diff --git a/src/Simplex/Messaging/Server.hs b/src/Simplex/Messaging/Server.hs index b4c9722f7..d1fcfbc24 100644 --- a/src/Simplex/Messaging/Server.hs +++ b/src/Simplex/Messaging/Server.hs @@ -856,7 +856,7 @@ client thParams' clnt@Client {subscriptions, ntfSubscriptions, rcvQ, sndQ, sessi sendMessage :: QueueRec -> MsgFlags -> MsgBody -> M (Transmission BrokerMsg) sendMessage qr msgFlags msgBody - | B.length msgBody > maxMessageLength = pure $ err LARGE_MSG + | B.length msgBody > maxMessageLength thVersion = pure $ err LARGE_MSG | otherwise = case status qr of QueueOff -> return $ err AUTH QueueActive -> @@ -880,6 +880,7 @@ client thParams' clnt@Client {subscriptions, ntfSubscriptions, rcvQ, sndQ, sessi atomically $ updatePeriodStats (activeQueues stats) (recipientId qr) pure ok where + THandleParams {thVersion} = thParams' mkMessage :: C.MaxLenBS MaxMessageLen -> M Message mkMessage body = do msgId <- randomId =<< asks (msgIdBytes . config) @@ -921,7 +922,7 @@ client thParams' clnt@Client {subscriptions, ntfSubscriptions, rcvQ, sndQ, sessi sessSecret <- maybe (throwError $ ERR INTERNAL) pure sessSecret' let proxyNonce = C.cbNonce $ bs corrId -- TODO error - s' <- liftEitherWith internalErr $ C.cbDecrypt sessSecret proxyNonce s + s' <- liftEitherWith internalErr $ C.cbDecryptNoPad sessSecret proxyNonce s -- TODO error FwdTransmission {fwdCorrId, fwdKey, fwdTransmission = EncTransmission et} <- liftEitherWith internalErr $ smpDecode s' -- TODO error - this error is reported to proxy, as we failed to get to client's transmission @@ -949,7 +950,7 @@ client thParams' clnt@Client {subscriptions, ntfSubscriptions, rcvQ, sndQ, sessi r2 <- liftEitherWith internalErr $ EncResponse <$> C.cbEncrypt clientSecret (C.reverseNonce clientNonce) r' paddedProxiedMsgLength -- encrypt to proxy let fr = FwdResponse {fwdCorrId, fwdResponse = r2} - r3 <- liftEitherWith internalErr $ EncFwdResponse <$> C.cbEncrypt sessSecret (C.reverseNonce proxyNonce) (smpEncode fr) paddedForwardedMsgLength + r3 = EncFwdResponse $ C.cbEncryptNoPad sessSecret (C.reverseNonce proxyNonce) (smpEncode fr) pure $ RRES r3 where internalErr _ = ERR INTERNAL -- TODO errors diff --git a/src/Simplex/Messaging/Transport.hs b/src/Simplex/Messaging/Transport.hs index 001d77fa7..a353849da 100644 --- a/src/Simplex/Messaging/Transport.hs +++ b/src/Simplex/Messaging/Transport.hs @@ -115,11 +115,6 @@ 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 diff --git a/tests/SMPProxyTests.hs b/tests/SMPProxyTests.hs index 1ab2779c8..2a33ec055 100644 --- a/tests/SMPProxyTests.hs +++ b/tests/SMPProxyTests.hs @@ -39,6 +39,7 @@ smpProxyTests = do xit "batching proxy requests" todo describe "forwarding requests" $ do describe "deliver message via SMP proxy" $ do + let maxLen = maxMessageLength sendingProxySMPVersion it "same server" $ withSmpServerConfigOn (transport @TLS) proxyCfg testPort $ \_ -> do let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash @@ -50,12 +51,12 @@ smpProxyTests = do let proxyServ = SMPServer SMP.testHost SMP.testPort SMP.testKeyHash let relayServ = SMPServer SMP.testHost SMP.testPort2 SMP.testKeyHash deliverMessageViaProxy proxyServ relayServ C.SEd448 "hello 1" "hello 2" - xit "max message size, Ed448 keys" $ + it "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 + msg <- atomically $ C.randomBytes maxLen g + msg' <- atomically $ C.randomBytes maxLen 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' @@ -63,8 +64,8 @@ smpProxyTests = do 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 + msg <- atomically $ C.randomBytes maxLen g + msg' <- atomically $ C.randomBytes maxLen 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' @@ -72,8 +73,8 @@ smpProxyTests = do 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 + msg <- atomically $ C.randomBytes maxLen g + msg' <- atomically $ C.randomBytes maxLen 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' diff --git a/tests/ServerTests.hs b/tests/ServerTests.hs index a7e8fee86..b0ed67913 100644 --- a/tests/ServerTests.hs +++ b/tests/ServerTests.hs @@ -183,12 +183,12 @@ testCreateSecure (ATransport t) = Resp "dabc" _ err5 <- sendRecv s ("", "dabc", sId, _SEND "hello") (err5, ERR AUTH) #== "rejects unsigned SEND" - let maxAllowedMessage = B.replicate maxMessageLength '-' + let maxAllowedMessage = B.replicate (maxMessageLength currentClientSMPRelayVersion) '-' Resp "bcda" _ OK <- signSendRecv s sKey ("bcda", sId, _SEND maxAllowedMessage) Resp "" _ (Msg mId3 msg3) <- tGet1 r (dec mId3 msg3, Right maxAllowedMessage) #== "delivers message of max size" - let biggerMessage = B.replicate (maxMessageLength + 1) '-' + let biggerMessage = B.replicate (maxMessageLength currentClientSMPRelayVersion + 1) '-' Resp "bcda" _ (ERR LARGE_MSG) <- signSendRecv s sKey ("bcda", sId, _SEND biggerMessage) pure ()