From 054b6edb14c323d4e83c6aea6c22deaffd681147 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sun, 10 Mar 2024 11:27:31 +0000 Subject: [PATCH] pqdr: clean up (#1039) --- src/Simplex/Messaging/Agent.hs | 9 +++------ src/Simplex/Messaging/Crypto/Ratchet.hs | 22 ++++++++-------------- tests/AgentTests/DoubleRatchetTests.hs | 2 +- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/Simplex/Messaging/Agent.hs b/src/Simplex/Messaging/Agent.hs index df79181e9..08678140e 100644 --- a/src/Simplex/Messaging/Agent.hs +++ b/src/Simplex/Messaging/Agent.hs @@ -700,7 +700,7 @@ startJoinInvitation userId connId enableNtfs cReqUri pqSup = (_, rcDHRs) <- atomically $ C.generateKeyPair g rcParams <- liftEitherWith cryptoError $ CR.pqX3dhSnd pk1 pk2 pKem e2eRcvParams maxSupported <- asks $ maxVersion . ($ pqSup) . e2eEncryptVRange . config - let rcVs = CR.RVersions {current = v, maxSupported} + let rcVs = CR.RatchetVersions {current = v, maxSupported} rc = CR.initSndRatchet rcVs rcDHRr rcDHRs rcParams q <- newSndQueue userId "" qInfo let cData = ConnData {userId, connId, connAgentVersion, enableNtfs, lastExternalSndId = 0, deleted = False, ratchetSyncState = RSOk, pqSupport} @@ -2183,8 +2183,7 @@ processSMPTransmission c@AgentClient {smpClients, subQ} (tSess@(_, srv, _), _v, unless (e2eVersion `isCompatible` e2eVRange) (throwError $ AGENT A_VERSION) (pk1, rcDHRs, pKem) <- withStore c (`getRatchetX3dhKeys` connId) rcParams <- liftError cryptoError $ CR.pqX3dhRcv pk1 rcDHRs pKem e2eSndParams - -- TODO PQ combine isCompatible check and construction in one call - let rcVs = CR.RVersions {current = e2eVersion, maxSupported = maxVersion e2eVRange} + let rcVs = CR.RatchetVersions {current = e2eVersion, maxSupported = maxVersion e2eVRange} pqSupport' = pqSupport `CR.pqSupportAnd` versionPQSupport_ agentVersion (Just e2eVersion) rc = CR.initRcvRatchet rcVs rcDHRs rcParams pqSupport' g <- asks random @@ -2379,7 +2378,6 @@ processSMPTransmission c@AgentClient {smpClients, subQ} (tSess@(_, srv, _), _v, DuplexConnection {} -> action conn' _ -> qError $ name <> ": message must be sent to duplex connection" - -- TODO PQ make sure pqEncryption is set correctly here newRatchetKey :: CR.RcvE2ERatchetParams 'C.X448 -> Connection 'CDuplex -> m () newRatchetKey e2eOtherPartyParams@(CR.E2ERatchetParams e2eVersion k1Rcv k2Rcv _) conn'@(DuplexConnection cData'@ConnData {lastExternalSndId, pqSupport} _ sqs) = unlessM ratchetExists $ do @@ -2387,8 +2385,7 @@ processSMPTransmission c@AgentClient {smpClients, subQ} (tSess@(_, srv, _), _v, let connE2EVRange = e2eEncryptVRange pqSupport unless (e2eVersion `isCompatible` connE2EVRange) (throwError $ AGENT A_VERSION) keys <- getSendRatchetKeys - -- TODO PQ combine with `isCompatible` check above - let rcVs = CR.RVersions {current = e2eVersion, maxSupported = maxVersion connE2EVRange} + let rcVs = CR.RatchetVersions {current = e2eVersion, maxSupported = maxVersion connE2EVRange} initRatchet rcVs keys notifyAgreed where diff --git a/src/Simplex/Messaging/Crypto/Ratchet.hs b/src/Simplex/Messaging/Crypto/Ratchet.hs index 4b15e5766..a3251c26c 100644 --- a/src/Simplex/Messaging/Crypto/Ratchet.hs +++ b/src/Simplex/Messaging/Crypto/Ratchet.hs @@ -488,7 +488,7 @@ data Ratchet a = Ratchet } deriving (Show) -data RatchetVersions = RVersions +data RatchetVersions = RatchetVersions { current :: VersionE2E, maxSupported :: VersionE2E } @@ -496,8 +496,8 @@ data RatchetVersions = RVersions instance ToJSON RatchetVersions where -- TODO v5.7 or v5.8 change to the default record encoding - toJSON (RVersions v1 v2) = toJSON (v1, v2) - toEncoding (RVersions v1 v2) = toEncoding (v1, v2) + toJSON (RatchetVersions v1 v2) = toJSON (v1, v2) + toEncoding (RatchetVersions v1 v2) = toEncoding (v1, v2) instance FromJSON RatchetVersions where -- TODO v6.0 replace with the default record parser @@ -509,7 +509,7 @@ instance FromJSON RatchetVersions where toRV (v1, v2) = maybe (fail "bad version range") (pure . ratchetVersions) $ safeVersionRange v1 v2 ratchetVersions :: VersionRangeE2E -> RatchetVersions -ratchetVersions (VersionRange v1 v2) = RVersions {current = v1, maxSupported = v2} +ratchetVersions (VersionRange v1 v2) = RatchetVersions {current = v1, maxSupported = v2} data SndRatchet a = SndRatchet { rcDHRr :: PublicKey a, @@ -671,7 +671,6 @@ data MsgHeader a = MsgHeader -- to allow extension without increasing the size, the actual header length is: -- 69 = 2 (original size) + 2 + 1+56 (Curve448) + 4 + 4 --- TODO PQ this must be version-dependent -- TODO this is the exact size, some reserve should be added paddedHeaderLen :: VersionE2E -> PQSupport -> Int paddedHeaderLen v = \case @@ -679,7 +678,7 @@ paddedHeaderLen v = \case _ -> 88 -- only used in tests to validate correct padding --- (2 bytes - version size, 1 byte - header size, not to have it fixed or version-dependent) +-- (2 bytes - version size, 1 byte - header size) fullHeaderLen :: VersionE2E -> PQSupport -> Int fullHeaderLen v pq = 2 + 1 + paddedHeaderLen v pq + authTagSize + ivSize @AES256 @@ -862,7 +861,8 @@ rcEncrypt rc@Ratchet {rcSnd = Just sr@SndRatchet {rcCKs, rcHKs}, rcDHRs, rcKEM, rcSupportKEM' = pqEnableSupport v rcSupportKEM rcEnableKEM' -- This sets max version to support PQ encryption. -- Current version upgrade happens when peer decrypts the message. - -- TODO v5.7 remove version upgrade here, as it's already upgraded above + -- TODO note that maxSupported will not downgrade here below current (v). + -- TODO PQ currentE2EEncryptVersion should be passed via config maxSupported' = max currentE2EEncryptVersion $ if pqEnc_ == Just PQEncOn then pqRatchetE2EEncryptVersion else v rcVersion' = rcVersion {maxSupported = maxSupported'} -- enc_header = HENCRYPT(state.HKs, header) @@ -871,12 +871,6 @@ rcEncrypt rc@Ratchet {rcSnd = Just sr@SndRatchet {rcCKs, rcHKs}, rcDHRs, rcKEM, let emHeader = smpEncode EncMessageHeader {ehVersion = v, ehBody, ehAuthTag, ehIV} (emAuthTag, emBody) <- encryptAEAD mk iv paddedMsgLen (rcAD <> emHeader) msg let msg' = encodeEncRatchetMessage v EncRatchetMessage {emHeader, emBody, emAuthTag} - -- TODO v5.8 remove comments below - -- Note that maxSupported will not downgrade here below current. - -- TODO v5.7 remove comments below - -- TODO PQ It will downgrade when decrypting the message when the current version downgrades to remove support for PQ encryption. - -- TODO v5.8 possibly, replace `max v currentE2EEncryptVersion` with `v` (to allow downgrade when app downgraded)? - -- -- state.Ns += 1 rc' = rc @@ -973,7 +967,7 @@ rcDecrypt g rc@Ratchet {rcRcv, rcAD = Str rcAD, rcVersion} rcMKSkipped msg' = do | msgMaxVersion > current = rc {rcVersion = rcVersion {current = max current $ min msgMaxVersion maxSupported}} | otherwise = rc where - RVersions {current, maxSupported} = rcVersion + RatchetVersions {current, maxSupported} = rcVersion smkDiff :: SkippedMsgKeys -> SkippedMsgDiff smkDiff smks = if M.null smks then SMDNoChange else SMDAdd smks ratchetStep :: Ratchet a -> MsgHeader a -> ExceptT CryptoError IO (Ratchet a) diff --git a/tests/AgentTests/DoubleRatchetTests.hs b/tests/AgentTests/DoubleRatchetTests.hs index c64f5fb96..e6057fc02 100644 --- a/tests/AgentTests/DoubleRatchetTests.hs +++ b/tests/AgentTests/DoubleRatchetTests.hs @@ -580,7 +580,7 @@ initRatchetsKEMProposedAgain = do testRatchetVersions :: PQSupport -> RatchetVersions testRatchetVersions pq = let v = maxVersion $ supportedE2EEncryptVRange pq - in RVersions v v + in RatchetVersions v v encrypt_ :: AlgorithmI a => Maybe PQEncryption -> (TVar ChaChaDRG, Ratchet a, SkippedMsgKeys) -> ByteString -> IO (Either CryptoError (ByteString, Ratchet a, SkippedMsgDiff)) encrypt_ pqEnc_ (_, rc, _) msg =