mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-10-12 02:22:45 +00:00
smp: strict 24-byte nonce for forwarded corrId
This commit is contained in:
@@ -1263,14 +1263,14 @@ proxySMPCommand c@ProtocolClient {thParams = proxyThParams, client_ = PClient {c
|
||||
-- proxy should send PRES to the client with EncResponse
|
||||
-- Always uses background timeout mode
|
||||
forwardSMPTransmission :: SMPClient -> CorrId -> VersionSMP -> C.PublicKeyX25519 -> EncTransmission -> ExceptT SMPClientError IO (Maybe C.CbNonce, EncResponse)
|
||||
forwardSMPTransmission c@ProtocolClient {thParams, client_ = PClient {clientCorrId = g}} fwdCorrId fwdVersion fwdKey fwdTransmission = do
|
||||
forwardSMPTransmission c@ProtocolClient {thParams, client_ = PClient {clientCorrId = g}} (CorrId corrId) fwdVersion fwdKey fwdTransmission = do
|
||||
-- prepare params
|
||||
sessSecret <- case thAuth thParams of
|
||||
Nothing -> throwE $ PCETransportError TENoServerAuth
|
||||
Just THAuthClient {sessSecret} -> maybe (throwE $ PCETransportError TENoServerAuth) pure sessSecret
|
||||
nonce <- liftIO . atomically $ C.randomCbNonce g
|
||||
-- wrap
|
||||
let fwdT = FwdTransmission {fwdCorrId, fwdVersion, fwdKey, fwdTransmission}
|
||||
let fwdT = FwdTransmission {fwdCorrId = C.StrictCbNonce corrId, fwdVersion, fwdKey, fwdTransmission}
|
||||
eft = EncFwdTransmission $ C.cbEncryptNoPad sessSecret nonce (smpEncode fwdT)
|
||||
-- send
|
||||
sendProtocolCommand_ c NRMBackground (Just nonce) Nothing Nothing NoEntity (Cmd SProxyService (RFWD eft)) >>= \case
|
||||
|
||||
@@ -142,6 +142,7 @@ module Simplex.Messaging.Crypto
|
||||
-- * NaCl crypto_box
|
||||
CbNonce (unCbNonce),
|
||||
pattern CbNonce,
|
||||
StrictCbNonce (..),
|
||||
cbEncrypt,
|
||||
cbEncryptNoPad,
|
||||
cbEncryptMaxLenBS,
|
||||
@@ -1426,6 +1427,14 @@ instance Encoding CbNonce where
|
||||
smpEncode = unCbNonce
|
||||
smpP = CryptoBoxNonce <$> A.take 24
|
||||
|
||||
-- | Length-prefixed nonce that fails to parse unless it is 24 bytes, unlike cbNonce that pads or truncates.
|
||||
newtype StrictCbNonce = StrictCbNonce {unStrictCbNonce :: ByteString}
|
||||
deriving (Eq, Show)
|
||||
|
||||
instance Encoding StrictCbNonce where
|
||||
smpEncode (StrictCbNonce s) = smpEncode s
|
||||
smpP = smpP >>= \s -> if B.length s == 24 then pure (StrictCbNonce s) else fail "bad nonce length"
|
||||
|
||||
newtype SbKey = SecretBoxKey {unSbKey :: ByteString}
|
||||
deriving (Eq, Show)
|
||||
deriving newtype (FromField)
|
||||
|
||||
@@ -125,7 +125,6 @@ module Simplex.Messaging.Protocol
|
||||
SrvLoc (..),
|
||||
CorrId (..),
|
||||
pattern NoCorrId,
|
||||
corrIdNonce,
|
||||
EntityId (..),
|
||||
pattern NoEntity,
|
||||
QueueId,
|
||||
@@ -251,7 +250,6 @@ import qualified Data.ByteString.Char8 as B
|
||||
import qualified Data.ByteString.Lazy as LB
|
||||
import Data.Char (isPrint, isSpace)
|
||||
import Data.Constraint (Dict (..))
|
||||
import Data.Either (isLeft)
|
||||
import Data.Functor (($>))
|
||||
import Data.Int (Int64)
|
||||
import Data.Kind
|
||||
@@ -711,18 +709,18 @@ encTransmissionNonce v nonce@(C.CbNonce s)
|
||||
| otherwise = nonce
|
||||
|
||||
data FwdTransmission = FwdTransmission
|
||||
{ fwdCorrId :: CorrId,
|
||||
{ fwdCorrId :: C.StrictCbNonce,
|
||||
fwdVersion :: VersionSMP,
|
||||
fwdKey :: C.PublicKeyX25519,
|
||||
fwdTransmission :: EncTransmission
|
||||
}
|
||||
|
||||
instance Encoding FwdTransmission where
|
||||
smpEncode FwdTransmission {fwdCorrId = CorrId corrId, fwdVersion, fwdKey, fwdTransmission = EncTransmission t} =
|
||||
smpEncode (corrId, fwdVersion, fwdKey, Tail t)
|
||||
smpEncode FwdTransmission {fwdCorrId, fwdVersion, fwdKey, fwdTransmission = EncTransmission t} =
|
||||
smpEncode (fwdCorrId, fwdVersion, fwdKey, Tail t)
|
||||
smpP = do
|
||||
(corrId, fwdVersion, fwdKey, Tail t) <- smpP
|
||||
pure FwdTransmission {fwdCorrId = CorrId corrId, fwdVersion, fwdKey, fwdTransmission = EncTransmission t}
|
||||
(fwdCorrId, fwdVersion, fwdKey, Tail t) <- smpP
|
||||
pure FwdTransmission {fwdCorrId, fwdVersion, fwdKey, fwdTransmission = EncTransmission t}
|
||||
|
||||
newtype EncFwdTransmission = EncFwdTransmission ByteString
|
||||
deriving (Show)
|
||||
@@ -768,16 +766,16 @@ newtype EncFwdResponse = EncFwdResponse ByteString
|
||||
deriving (Eq, Show)
|
||||
|
||||
data FwdResponse = FwdResponse
|
||||
{ fwdCorrId :: CorrId,
|
||||
{ fwdCorrId :: C.StrictCbNonce,
|
||||
fwdResponse :: EncResponse
|
||||
}
|
||||
|
||||
instance Encoding FwdResponse where
|
||||
smpEncode FwdResponse {fwdCorrId = CorrId corrId, fwdResponse = EncResponse t} =
|
||||
smpEncode (corrId, Tail t)
|
||||
smpEncode FwdResponse {fwdCorrId, fwdResponse = EncResponse t} =
|
||||
smpEncode (fwdCorrId, Tail t)
|
||||
smpP = do
|
||||
(corrId, Tail t) <- smpP
|
||||
pure FwdResponse {fwdCorrId = CorrId corrId, fwdResponse = EncResponse t}
|
||||
(fwdCorrId, Tail t) <- smpP
|
||||
pure FwdResponse {fwdCorrId, fwdResponse = EncResponse t}
|
||||
|
||||
newtype EncResponse = EncResponse ByteString
|
||||
deriving (Eq, Show)
|
||||
@@ -1435,10 +1433,6 @@ instance IsString CorrId where
|
||||
fromString = CorrId . fromString
|
||||
{-# INLINE fromString #-}
|
||||
|
||||
-- | Fails unless corrId is exactly 24 bytes, so it is never padded or truncated.
|
||||
corrIdNonce :: CorrId -> Either String C.CbNonce
|
||||
corrIdNonce = smpDecode . bs
|
||||
|
||||
instance StrEncoding CorrId where
|
||||
strEncode (CorrId cId) = strEncode cId
|
||||
strDecode s = CorrId <$> strDecode s
|
||||
@@ -2427,12 +2421,7 @@ tDecodeServer THandleParams {sessionId, thVersion = v, implySessId} = \case
|
||||
| implySessId || sessId == sessionId -> case decodeTAuthBytes authenticator serviceSig of
|
||||
Right tAuth -> bimap t ((tAuth,authorized,) . t) cmdOrErr
|
||||
where
|
||||
cmdOrErr
|
||||
| invalidAuthNonce = Left $ fromProtocolError @v @err @cmd PECmdSyntax
|
||||
| otherwise = parseProtocol @v @err @cmd v command >>= checkCredentials tAuth entityId
|
||||
invalidAuthNonce = case tAuth of
|
||||
Just (TAAuthenticator _, _) -> isLeft $ corrIdNonce corrId
|
||||
_ -> False
|
||||
cmdOrErr = parseProtocol @v @err @cmd v command >>= checkCredentials tAuth entityId
|
||||
t :: a -> (CorrId, EntityId, a)
|
||||
t = (corrId,entityId,)
|
||||
Left _ -> tError corrId PEBlock
|
||||
|
||||
@@ -64,7 +64,7 @@ import qualified Data.ByteString.Char8 as B
|
||||
import qualified Data.ByteString.Lazy.Char8 as LB
|
||||
import Data.Constraint (Dict (..))
|
||||
import Data.Dynamic (toDyn)
|
||||
import Data.Either (fromRight, isLeft, partitionEithers)
|
||||
import Data.Either (fromRight, partitionEithers)
|
||||
import Data.Foldable (foldrM)
|
||||
import Data.Functor (($>), (<&>))
|
||||
import Data.IORef
|
||||
@@ -1453,22 +1453,20 @@ client
|
||||
Just THAuthClient {peerServerCertKey} -> PKEY srvSessId vr peerServerCertKey
|
||||
Nothing -> ERR $ transportErr TENoServerAuth
|
||||
_ -> ERR $ transportErr TEVersion
|
||||
PFWD fwdV pubKey encBlock
|
||||
| isLeft (corrIdNonce corrId) -> pure $ Just $ ERR $ CMD SYNTAX
|
||||
| otherwise -> do
|
||||
ProxyAgent {smpAgent = a} <- asks proxyAgent
|
||||
ServerStats {pMsgFwds, pMsgFwdsOwn} <- asks serverStats
|
||||
let inc = mkIncProxyStats pMsgFwds pMsgFwdsOwn
|
||||
liftIO (lookupSMPServerClient a sessId) >>= \case
|
||||
Just (own, smp) -> do
|
||||
inc own pRequests
|
||||
forkProxiedCmd $ do
|
||||
liftIO (runExceptT (forwardSMPTransmission smp corrId fwdV pubKey encBlock) `E.catches` clientHandlers) >>= \case
|
||||
Right (nonce_, r) -> PRES nonce_ r <$ inc own pSuccesses
|
||||
Left e -> ERR (smpProxyError e) <$ case e of
|
||||
PCEProtocolError {} -> inc own pSuccesses
|
||||
_ -> inc own pErrorsOther
|
||||
Nothing -> inc False pRequests >> inc False pErrorsConnect $> Just (ERR $ PROXY NO_SESSION)
|
||||
PFWD fwdV pubKey encBlock -> do
|
||||
ProxyAgent {smpAgent = a} <- asks proxyAgent
|
||||
ServerStats {pMsgFwds, pMsgFwdsOwn} <- asks serverStats
|
||||
let inc = mkIncProxyStats pMsgFwds pMsgFwdsOwn
|
||||
liftIO (lookupSMPServerClient a sessId) >>= \case
|
||||
Just (own, smp) -> do
|
||||
inc own pRequests
|
||||
forkProxiedCmd $ do
|
||||
liftIO (runExceptT (forwardSMPTransmission smp corrId fwdV pubKey encBlock) `E.catches` clientHandlers) >>= \case
|
||||
Right (nonce_, r) -> PRES nonce_ r <$ inc own pSuccesses
|
||||
Left e -> ERR (smpProxyError e) <$ case e of
|
||||
PCEProtocolError {} -> inc own pSuccesses
|
||||
_ -> inc own pErrorsOther
|
||||
Nothing -> inc False pRequests >> inc False pErrorsConnect $> Just (ERR $ PROXY NO_SESSION)
|
||||
where
|
||||
forkProxiedCmd :: M s BrokerMsg -> M s (Maybe BrokerMsg)
|
||||
forkProxiedCmd = forkCmd serverClientConcurrency corrId (EntityId sessId)
|
||||
@@ -2127,12 +2125,12 @@ client
|
||||
processForwardedCommand (EncFwdTransmission s) = fmap (either (Just . ERR) id) . runExceptT $ do
|
||||
THAuthServer {serverPrivKey, sessSecret'} <- maybe (throwE $ transportErr TENoServerAuth) pure (thAuth thParams')
|
||||
sessSecret <- maybe (throwE $ transportErr TENoServerAuth) pure sessSecret'
|
||||
proxyNonce <- liftEitherWith (const $ CMD SYNTAX) $ corrIdNonce corrId
|
||||
let proxyNonce = C.cbNonce $ bs corrId
|
||||
s' <- liftEitherWith (const CRYPTO) $ C.cbDecryptNoPad sessSecret proxyNonce s
|
||||
FwdTransmission {fwdCorrId, fwdVersion, fwdKey, fwdTransmission = EncTransmission et} <- liftEitherWith (const $ CMD SYNTAX) $ smpDecode s'
|
||||
unless (fwdVersion `isCompatible` thServerVRange thParams') $ throwE $ transportErr TEVersion
|
||||
clientNonce <- liftEitherWith (const $ CMD SYNTAX) $ corrIdNonce fwdCorrId
|
||||
let clientSecret = C.dh' fwdKey serverPrivKey
|
||||
clientNonce = C.cbNonce $ C.unStrictCbNonce fwdCorrId
|
||||
b <- liftEitherWith (const CRYPTO) $ C.cbDecrypt clientSecret (encTransmissionNonce fwdVersion clientNonce) et
|
||||
let clntTHParams = smpTHParamsSetVersion fwdVersion thParams'
|
||||
-- only allowing single forwarded transactions
|
||||
|
||||
+20
-48
@@ -21,12 +21,13 @@ import Control.Logger.Simple
|
||||
import Control.Monad (forM, forM_, forever, replicateM_)
|
||||
import Control.Monad.Trans.Except (ExceptT, runExceptT)
|
||||
import Data.ByteString.Char8 (ByteString)
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.List.NonEmpty (NonEmpty)
|
||||
import qualified Data.List.NonEmpty as L
|
||||
import Data.Time.Clock (getCurrentTime)
|
||||
import SMPAgentClient
|
||||
import SMPClient
|
||||
import ServerTests (decryptMsgV3, sendRecv, wrongSizeCorrIds)
|
||||
import ServerTests (decryptMsgV3, sendRecv)
|
||||
import Simplex.Messaging.Agent hiding (createConnection, joinConnection, sendMessage)
|
||||
import qualified Simplex.Messaging.Agent as A
|
||||
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..))
|
||||
@@ -36,13 +37,11 @@ import Simplex.Messaging.Client
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.Ratchet (pattern PQSupportOn)
|
||||
import qualified Simplex.Messaging.Crypto.Ratchet as CR
|
||||
import Simplex.Messaging.Encoding (smpEncode)
|
||||
import Simplex.Messaging.Protocol (EncRcvMsgBody (..), MsgBody, QueueReqData (..), RcvMessage (..), SubscriptionMode (..), maxMessageLength, noMsgFlags)
|
||||
import qualified Simplex.Messaging.Protocol as SMP
|
||||
import Simplex.Messaging.Server.Env.STM (AStoreType (..), ServerConfig (..))
|
||||
import Simplex.Messaging.Server.MsgStore.Types (SQSType (..))
|
||||
import Simplex.Messaging.Transport
|
||||
import qualified Simplex.Messaging.Transport.Client as TC
|
||||
import Simplex.Messaging.Util (bshow, tshow)
|
||||
import Simplex.Messaging.Version (mkVersionRange)
|
||||
import System.FilePath (splitExtensions)
|
||||
@@ -60,9 +59,6 @@ smpProxyTests = do
|
||||
describe "server configuration" $ do
|
||||
it "refuses proxy handshake unless enabled" testNoProxy
|
||||
it "checks basic auth in proxy requests" testProxyAuth
|
||||
describe "corrId used as nonce" $ do
|
||||
it "proxy rejects PFWD with corrId of wrong size" testPFWDCorrIdSize
|
||||
it "relay rejects RFWD with corrId of wrong size" testRFWDCorrIdSize
|
||||
describe "relay reconnection" $ do
|
||||
it "recovers when unresponsive relay restarts (control, no disconnect)" $ \_ ->
|
||||
testProxyRecoversWithoutDisconnect
|
||||
@@ -80,6 +76,8 @@ smpProxyTests = do
|
||||
xit "batching proxy requests" todo
|
||||
it "relay rejects forwarded command with changed version" $ \_ ->
|
||||
testChangedFwdVersion
|
||||
it "relay rejects forwarded corrId of wrong size" $ \_ ->
|
||||
testFwdCorrIdSize
|
||||
describe "deliver message via SMP proxy" $ do
|
||||
let srv1 = SMPServer testHost testPort testKeyHash
|
||||
srv2 = SMPServer testHost2 testPort2 testKeyHash
|
||||
@@ -459,48 +457,6 @@ testProxyAuth msType = do
|
||||
where
|
||||
proxyCfgAuth = updateCfg (proxyCfgMS msType) $ \cfg_ -> cfg_ {newQueueBasicAuth = Just "correct"}
|
||||
|
||||
testPFWDCorrIdSize :: AStoreType -> IO ()
|
||||
testPFWDCorrIdSize msType =
|
||||
withSmpServerConfigOn (transport @TLS) (proxyCfgMS msType) testPort $ \_ ->
|
||||
testSMPClient_ "127.0.0.1" testPort supportedServerSMPRelayVRange Nothing $ \(th@THandle {params} :: THandleSMP TLS 'TClient) -> do
|
||||
g <- C.newRandom
|
||||
(cmdKey, _ :: C.PrivateKeyX25519) <- atomically $ C.generateKeyPair g
|
||||
let pfwd corrId = do
|
||||
(_, _, reply) <- sendRecv th (Nothing, corrId, SMP.EntityId "unknown session", SMP.PFWD (thVersion params) cmdKey $ SMP.EncTransmission "invalid")
|
||||
pure reply
|
||||
corrId <- atomically $ C.randomBytes 24 g
|
||||
pfwd corrId `shouldReturn` Right (SMP.ERR $ SMP.PROXY SMP.NO_SESSION)
|
||||
forM_ (wrongSizeCorrIds corrId) $ \badCorrId ->
|
||||
pfwd badCorrId `shouldReturn` Right (SMP.ERR $ SMP.CMD SMP.SYNTAX)
|
||||
|
||||
testRFWDCorrIdSize :: AStoreType -> IO ()
|
||||
testRFWDCorrIdSize msType =
|
||||
withSmpServerConfigOn (transport @TLS) (cfgMS msType) testPort2 $ \_ ->
|
||||
testProxyModeClient $ \th@THandle {params = THandleParams {thVersion, thAuth}} -> do
|
||||
Just THAuthClient {sessSecret = Just sessSecret} <- pure thAuth
|
||||
g <- C.newRandom
|
||||
(fwdKey, _ :: C.PrivateKeyX25519) <- atomically $ C.generateKeyPair g
|
||||
let rfwd corrId fwdCorrId = do
|
||||
let fwdT = SMP.FwdTransmission {fwdCorrId = SMP.CorrId fwdCorrId, fwdVersion = thVersion, fwdKey, fwdTransmission = SMP.EncTransmission "invalid"}
|
||||
eft = SMP.EncFwdTransmission $ C.cbEncryptNoPad sessSecret (C.cbNonce corrId) (smpEncode fwdT)
|
||||
(_, _, reply) <- sendRecv th (Nothing, corrId, NoEntity, SMP.RFWD eft)
|
||||
pure reply
|
||||
corrId <- atomically $ C.randomBytes 24 g
|
||||
fwdCorrId <- atomically $ C.randomBytes 24 g
|
||||
rfwd corrId fwdCorrId `shouldReturn` Right (SMP.ERR SMP.CRYPTO)
|
||||
forM_ (wrongSizeCorrIds corrId) $ \badCorrId -> do
|
||||
rfwd badCorrId fwdCorrId `shouldReturn` Right (SMP.ERR $ SMP.CMD SMP.SYNTAX)
|
||||
rfwd corrId badCorrId `shouldReturn` Right (SMP.ERR $ SMP.CMD SMP.SYNTAX)
|
||||
|
||||
-- Connect to the relay on testPort2 the same way the proxy does, with the session secret.
|
||||
testProxyModeClient :: (THandleSMP TLS 'TClient -> IO a) -> IO a
|
||||
testProxyModeClient client = do
|
||||
g <- C.newRandom
|
||||
ks <- atomically $ C.generateKeyPair g
|
||||
let tcConfig = TC.defaultTransportClientConfig {TC.clientALPN = Just alpnSupportedSMPHandshakes}
|
||||
TC.runTransportClient tcConfig Nothing "127.0.0.1" testPort2 (Just testKeyHash) $ \h ->
|
||||
runExceptT (smpClientHandshake h (Just ks) testKeyHash supportedClientSMPRelayVRange True Nothing) >>= either (fail . show) client
|
||||
|
||||
-- Connect a sender client to the proxy and request a relay session to testSMPServer2 (PRXY).
|
||||
-- On success the reply is PKEY; otherwise it is the proxy error for the relay connection.
|
||||
requestRelaySession :: IO (Either SMP.ErrorType SMP.BrokerMsg)
|
||||
@@ -523,6 +479,22 @@ testChangedFwdVersion =
|
||||
_ <- runExceptT' $ forward v
|
||||
runExceptT (forward $ prevVersion v) `shouldReturn` Left (PCEProtocolError SMP.CRYPTO)
|
||||
|
||||
testFwdCorrIdSize :: IO ()
|
||||
testFwdCorrIdSize =
|
||||
withSmpServerConfigOn (transport @TLS) cfg testPort $ \_ -> do
|
||||
g <- C.newRandom
|
||||
ts <- getCurrentTime
|
||||
rc <- either (fail . show) pure =<< getProtocolClient g NRMInteractive (1, testSMPServer, Nothing) defaultSMPClientConfig [] Nothing ts (\_ -> pure ())
|
||||
THAuthClient {peerServerPubKey} <- maybe (fail "getProtocolClient returned no thAuth") pure $ thAuth $ thParams rc
|
||||
(cmdPubKey, cmdPrivKey) <- atomically $ C.generateKeyPair g
|
||||
nonce@(C.CbNonce corrId) <- atomically $ C.randomCbNonce g
|
||||
let v = currentClientSMPRelayVersion
|
||||
et <- either (fail . show) (pure . SMP.EncTransmission) $ C.cbEncrypt (C.dh' peerServerPubKey cmdPrivKey) (SMP.encTransmissionNonce v nonce) "" SMP.paddedProxiedTLength
|
||||
let forward cId = runExceptT $ forwardSMPTransmission rc (SMP.CorrId cId) v cmdPubKey et
|
||||
Right _ <- forward corrId
|
||||
forM_ (["", B.take 23 corrId, corrId <> "x"] :: [ByteString]) $ \cId ->
|
||||
forward cId `shouldReturn` Left (PCEProtocolError $ SMP.CMD SMP.SYNTAX)
|
||||
|
||||
-- Shared "phase 2" of the reconnection tests: start a healthy relay, confirm it is reachable
|
||||
-- directly (PING, not via the proxy) so a proxy failure can only mean the proxy didn't reconnect,
|
||||
-- let any stored connection error expire, then require the proxy to establish the session (PKEY).
|
||||
|
||||
+7
-37
@@ -97,7 +97,6 @@ serverTests = do
|
||||
describe "Restore messages (old / v2)" testRestoreExpireMessages
|
||||
describe "Save prometheus metrics" testPrometheusMetrics
|
||||
describe "Timing of AUTH error" testTiming
|
||||
describe "Authenticator nonce" testAuthenticatorCorrIdSize
|
||||
describe "Message notifications" $ do
|
||||
testMessageNotifications
|
||||
testMessageServiceNotifications
|
||||
@@ -1303,9 +1302,9 @@ testTiming =
|
||||
g <- C.newRandom
|
||||
(rPub, rKey) <- atomically $ C.generateAuthKeyPair goodKeyAlg g
|
||||
(dhPub, dhPriv :: C.PrivateKeyX25519) <- atomically $ C.generateKeyPair g
|
||||
Resp "abcdabcdabcdabcdabcdabcd" NoEntity (Ids rId sId srvDh) <- signSendRecv rh rKey ("abcdabcdabcdabcdabcdabcd", NoEntity, New rPub dhPub)
|
||||
Resp "abcd" NoEntity (Ids rId sId srvDh) <- signSendRecv rh rKey ("abcd", NoEntity, New rPub dhPub)
|
||||
let dec = decryptMsgV3 $ C.dh' srvDh dhPriv
|
||||
Resp "cdabcdabcdabcdabcdabcdab" _ resp <- signSendRecv rh rKey ("cdabcdabcdabcdabcdabcdab", rId, SUB)
|
||||
Resp "cdab" _ resp <- signSendRecv rh rKey ("cdab", rId, SUB)
|
||||
case resp of
|
||||
OK -> pure ()
|
||||
SOK Nothing -> pure ()
|
||||
@@ -1315,9 +1314,9 @@ testTiming =
|
||||
runTimingTest rh badKey rId SUB
|
||||
|
||||
(sPub, sKey) <- atomically $ C.generateAuthKeyPair goodKeyAlg g
|
||||
Resp "dabcdabcdabcdabcdabcdabc" _ OK <- signSendRecv rh rKey ("dabcdabcdabcdabcdabcdabc", rId, KEY sPub)
|
||||
Resp "dabc" _ OK <- signSendRecv rh rKey ("dabc", rId, KEY sPub)
|
||||
|
||||
Resp "bcdabcdabcdabcdabcdabcda" _ OK <- signSendRecv sh sKey ("bcdabcdabcdabcdabcdabcda", sId, _SEND "hello")
|
||||
Resp "bcda" _ OK <- signSendRecv sh sKey ("bcda", sId, _SEND "hello")
|
||||
Resp "" _ (Msg mId msg) <- tGet1 rh
|
||||
(dec mId msg, Right "hello") #== "delivered from queue"
|
||||
|
||||
@@ -1328,15 +1327,15 @@ testTiming =
|
||||
threadDelay 100000
|
||||
_ <- timeRepeat n $ do
|
||||
-- "warm up" the server
|
||||
Resp "dabcdabcdabcdabcdabcdabc" _ (ERR AUTH) <- signSendRecv h badKey ("dabcdabcdabcdabcdabcdabc", EntityId "1234", cmd)
|
||||
Resp "dabc" _ (ERR AUTH) <- signSendRecv h badKey ("dabc", EntityId "1234", cmd)
|
||||
return ()
|
||||
threadDelay 100000
|
||||
timeWrongKey <- timeRepeat n $ do
|
||||
Resp "cdabcdabcdabcdabcdabcdab" _ (ERR AUTH) <- signSendRecv h badKey ("cdabcdabcdabcdabcdabcdab", qId, cmd)
|
||||
Resp "cdab" _ (ERR AUTH) <- signSendRecv h badKey ("cdab", qId, cmd)
|
||||
return ()
|
||||
threadDelay 100000
|
||||
timeNoQueue <- timeRepeat n $ do
|
||||
Resp "dabcdabcdabcdabcdabcdabc" _ (ERR AUTH) <- signSendRecv h badKey ("dabcdabcdabcdabcdabcdabc", EntityId "1234", cmd)
|
||||
Resp "dabc" _ (ERR AUTH) <- signSendRecv h badKey ("dabc", EntityId "1234", cmd)
|
||||
return ()
|
||||
let ok = similarTime timeNoQueue timeWrongKey msType
|
||||
unless ok . putStrLn . unwords $
|
||||
@@ -1348,35 +1347,6 @@ testTiming =
|
||||
]
|
||||
ok `shouldBe` True
|
||||
|
||||
testAuthenticatorCorrIdSize :: SpecWith (ASrvTransport, AStoreType)
|
||||
testAuthenticatorCorrIdSize =
|
||||
it "should reject X25519 authenticator unless corrId is 24 bytes" $ \(ATransport t, msType) ->
|
||||
smpTest2 t msType $ \r s -> do
|
||||
g <- C.newRandom
|
||||
let newCorrId = atomically $ C.randomBytes 24 g
|
||||
rejected cId entId = (CorrId cId, entId, Right (ERR $ CMD SYNTAX))
|
||||
badCorrIds <- wrongSizeCorrIds <$> newCorrId
|
||||
(rPub, rKey) <- atomically $ C.generateAuthKeyPair C.SX25519 g
|
||||
(dhPub, dhPriv :: C.PrivateKeyX25519) <- atomically $ C.generateKeyPair g
|
||||
forM_ badCorrIds $ \cId ->
|
||||
signSendRecv r rKey (cId, NoEntity, New rPub dhPub) `shouldReturn` rejected cId NoEntity
|
||||
corrId1 <- newCorrId
|
||||
Resp _ NoEntity (Ids rId sId srvDh) <- signSendRecv r rKey (corrId1, NoEntity, New rPub dhPub)
|
||||
(sPub, sKey) <- atomically $ C.generateAuthKeyPair C.SEd25519 g
|
||||
corrId2 <- newCorrId
|
||||
Resp _ _ OK <- signSendRecv r rKey (corrId2, rId, KEY sPub)
|
||||
Resp "bcda" _ OK <- signSendRecv s sKey ("bcda", sId, _SEND "hello")
|
||||
Resp "" _ (Msg mId msg) <- tGet1 r
|
||||
(decryptMsgV3 (C.dh' srvDh dhPriv) mId msg, Right "hello") #== "delivered from queue"
|
||||
forM_ badCorrIds $ \cId ->
|
||||
signSendRecv r rKey (cId, rId, ACK mId) `shouldReturn` rejected cId rId
|
||||
corrId3 <- newCorrId
|
||||
Resp _ _ OK <- signSendRecv r rKey (corrId3, rId, ACK mId)
|
||||
pure ()
|
||||
|
||||
wrongSizeCorrIds :: ByteString -> [ByteString]
|
||||
wrongSizeCorrIds corrId = ["", B.take 4 corrId, corrId <> "x"]
|
||||
|
||||
testMessageNotifications :: SpecWith (ASrvTransport, AStoreType)
|
||||
testMessageNotifications =
|
||||
it "should create simplex connection, subscribe notifier and deliver notifications" $ \(ATransport t, msType) -> do
|
||||
|
||||
Reference in New Issue
Block a user