core: limit the number of skipped keys during remote access (#7622)

* core: limit the number of skipped keys during remote access

* simplify

* core: restrict body size for XRCP commands and responses, limit decompressed size (#7616)

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
This commit is contained in:
Evgeny
2026-09-30 07:16:52 +01:00
committed by GitHub
co-authored by Evgeny @ SimpleX Chat
parent 8b804a4fba
commit be39a42121
2 changed files with 20 additions and 0 deletions
+3
View File
@@ -18,6 +18,7 @@ import Control.Monad (when)
import qualified Data.Aeson.TH as J
import Data.ByteString (ByteString)
import Data.Int (Int64)
import qualified Data.Map.Strict as M
import Data.Text (Text)
import Data.Word (Word16, Word32)
import Simplex.Chat.Remote.AppVersion
@@ -73,8 +74,10 @@ getRemoteRcvKeys RemoteCrypto {rcvCounter, chainKeys = TSbChainKeys {rcvKey}, sk
| otherwise = do -- prevCorrId < corrId
writeTVar rcvCounter corrId
skipKeys (prevCorrId + 1)
modifyTVar' skippedKeys $ \m -> M.drop (M.size m - maxSkippedKeys) m
Right <$> getKeys
maxSkip = 256
maxSkippedKeys = 1024
getKeys = (,) <$> stateTVar rcvKey C.sbcHkdf <*> stateTVar rcvKey C.sbcHkdf
skipKeys !cId =
when (cId < corrId) $ do
+17
View File
@@ -61,6 +61,23 @@ remoteTests = describe "Remote" $ do
filter (not . sanitized) fileNames `shouldBe` []
it "sanitizes to a name with no directory components" $ \_ ->
filter (not . bareName) fileNames `shouldBe` []
describe "skipped keys" $ do
it "keeps the most recent skipped keys" $ \_ -> do
(_, pk) <- atomically . C.generateKeyPair =<< C.newRandom
let (ck, _) = C.sbcInit "" ("secret" :: B.ByteString)
sndCounter <- newTVarIO 0
rcvCounter <- newTVarIO 0
sndKey <- newTVarIO ck
rcvKey <- newTVarIO ck
skippedKeys <- newTVarIO M.empty
let rc = RemoteCrypto {sessionCode = "", sndCounter, rcvCounter, chainKeys = TSbChainKeys {sndKey, rcvKey}, skippedKeys, signatures = RSSign pk pk, compression = False}
receive corrId = eitherToMaybe <$> atomically (getRemoteRcvKeys rc corrId)
sent <- replicateM 1280 $ atomically $ getRemoteSndKeys rc
let sentKeys = M.fromList [(corrId, (cmdKN, fileKN)) | (corrId, cmdKN, fileKN) <- sent]
forM_ [256, 512 .. 1280] $ \corrId -> receive corrId `shouldReturn` M.lookup corrId sentKeys
M.size <$> readTVarIO skippedKeys `shouldReturn` 1024
receive 251 `shouldReturn` Nothing
receive 252 `shouldReturn` M.lookup 252 sentKeys
describe "body size limit" $ do
it "rejects encrypted body above limit without reading it" $ \_ -> do
rc <- testRemoteCrypto