diff --git a/src/Simplex/Messaging/Agent.hs b/src/Simplex/Messaging/Agent.hs index 195c93833..e3b1bccf4 100644 --- a/src/Simplex/Messaging/Agent.hs +++ b/src/Simplex/Messaging/Agent.hs @@ -2307,12 +2307,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 c4058b75a..efe75e2f5 100644 --- a/src/Simplex/Messaging/Agent/Protocol.hs +++ b/src/Simplex/Messaging/Agent/Protocol.hs @@ -1504,6 +1504,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 @@ -1513,12 +1515,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 = @@ -1563,6 +1567,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