From 7aae6f3cbe4aa2942371f8dd968eb439ccec3b15 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:55:20 +0400 Subject: [PATCH] agent: fix case of ratchet synchronization getting stuck in endless loop (#892) --- src/Simplex/Messaging/Agent.hs | 21 ++++++++++++++++++--- src/Simplex/Messaging/Agent/Protocol.hs | 5 +++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Simplex/Messaging/Agent.hs b/src/Simplex/Messaging/Agent.hs index 04236a78d..c7795644e 100644 --- a/src/Simplex/Messaging/Agent.hs +++ b/src/Simplex/Messaging/Agent.hs @@ -2267,12 +2267,27 @@ processSMPTransmission c@AgentClient {smpClients, subQ} (tSess@(_, srv, _), v, s unless exists $ addProcessedRatchetKeyHash db connId rkHashRcv pure exists getSendRatchetKeys :: m (C.PrivateKeyX448, C.PrivateKeyX448, C.PublicKeyX448, C.PublicKeyX448) - getSendRatchetKeys - | rss == RSStarted = withStore c (`getRatchetX3dhKeys'` connId) - | otherwise = do + getSendRatchetKeys = case rss of + RSOk -> sendReplyKey -- receiving client + RSAllowed -> sendReplyKey + RSRequired -> sendReplyKey + RSStarted -> withStore c (`getRatchetX3dhKeys'` connId) -- initiating client + RSAgreed -> do + withStore' c $ \db -> setConnRatchetSync db connId RSRequired + notifyRatchetSyncError + -- can communicate for other client to reset to RSRequired + -- - need to add new AgentMsgEnvelope, AgentMessage, AgentMessageType + -- - need to deduplicate on receiving side + throwError $ AGENT (A_CRYPTO RATCHET_SYNC) + where + sendReplyKey = do (pk1, pk2, e2eParams@(CR.E2ERatchetParams _ k1 k2)) <- liftIO . CR.generateE2EParams $ version e2eOtherPartyParams void $ enqueueRatchetKeyMsgs c cData' sqs e2eParams pure (pk1, pk2, k1, k2) + notifyRatchetSyncError = do + let cData'' = cData' {ratchetSyncState = RSRequired} :: ConnData + conn'' = updateConnection cData'' conn' + notify $ RSYNC RSRequired (Just RATCHET_SYNC) (connectionStats conn'') notifyAgreed :: m () notifyAgreed = do let cData'' = cData' {ratchetSyncState = RSAgreed} :: ConnData diff --git a/src/Simplex/Messaging/Agent/Protocol.hs b/src/Simplex/Messaging/Agent/Protocol.hs index 481034e01..d447b92b5 100644 --- a/src/Simplex/Messaging/Agent/Protocol.hs +++ b/src/Simplex/Messaging/Agent/Protocol.hs @@ -1501,6 +1501,8 @@ data AgentCryptoError RATCHET_EARLIER Word32 | -- | too many skipped messages RATCHET_SKIPPED Word32 + | -- | ratchet synchronization error + RATCHET_SYNC deriving (Eq, Read, Show, Exception) instance StrEncoding AgentCryptoError where @@ -1510,12 +1512,14 @@ instance StrEncoding AgentCryptoError where <|> "RATCHET_HEADER" $> RATCHET_HEADER <|> "RATCHET_EARLIER " *> (RATCHET_EARLIER <$> strP) <|> "RATCHET_SKIPPED " *> (RATCHET_SKIPPED <$> strP) + <|> "RATCHET_SYNC" $> RATCHET_SYNC strEncode = \case DECRYPT_AES -> "DECRYPT_AES" DECRYPT_CB -> "DECRYPT_CB" RATCHET_HEADER -> "RATCHET_HEADER" RATCHET_EARLIER n -> "RATCHET_EARLIER " <> strEncode n RATCHET_SKIPPED n -> "RATCHET_SKIPPED " <> strEncode n + RATCHET_SYNC -> "RATCHET_SYNC" instance StrEncoding AgentErrorType where strP = @@ -1558,6 +1562,7 @@ cryptoErrToSyncState = \case RATCHET_HEADER -> RSRequired RATCHET_EARLIER _ -> RSAllowed RATCHET_SKIPPED _ -> RSRequired + RATCHET_SYNC -> RSRequired -- | SMP agent command and response parser for commands passed via network (only parses binary length) networkCommandP :: Parser ACmd