From 5cfdbc49647b6be943d01e4ab141b705e9e5c86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Wed, 27 Jul 2022 22:01:50 +0200 Subject: Explicit identities in pairing request Actual device identities can change at any point during the pairing process, so it is necessary to fix the ones used for nonce confirmation and just initially verify that they belong to the respective sides. --- include/erebos/pairing.h | 2 ++ src/pairing.cpp | 47 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/erebos/pairing.h b/include/erebos/pairing.h index 936b3ac..ea349a9 100644 --- a/include/erebos/pairing.h +++ b/include/erebos/pairing.h @@ -83,6 +83,8 @@ private: struct State { mutex lock; StatePhase phase; + optional idReq; + optional idRsp; vector nonce; vector peerCheck; promise outcome; diff --git a/src/pairing.cpp b/src/pairing.cpp index babe886..f25cb5c 100644 --- a/src/pairing.cpp +++ b/src/pairing.cpp @@ -74,6 +74,24 @@ void PairingServiceBase::handle(Context & ctx) unique_lock lock_state(state->lock); if (auto request = rec->item("request").asBinary()) { + auto idReqRef = rec->item("id-req").asRef(); + if (!idReqRef) + return; + auto idReq = Identity::load(*idReqRef); + if (!idReq) + return; + if (!idReq->sameAs(*pid)) + return; + + auto idRspRef = rec->item("id-rsp").asRef(); + if (!idRspRef) + return; + auto idRsp = Identity::load(*idRspRef); + if (!idRsp) + return; + if (!idRsp->sameAs(ctx.peer().server().identity())) + return; + if (state->phase >= StatePhase::PairingDone) { auto nstate = make_shared(); lock_state = unique_lock(nstate->lock); @@ -85,6 +103,8 @@ void PairingServiceBase::handle(Context & ctx) requestInitHook(ctx.peer()); state->phase = StatePhase::PeerRequest; + state->idReq = idReq; + state->idRsp = idRsp; state->peerCheck = *request; state->nonce.resize(32); RAND_bytes(state->nonce.data(), state->nonce.size()); @@ -102,7 +122,7 @@ void PairingServiceBase::handle(Context & ctx) if (responseHook) { string confirm = confirmationNumber(nonceDigest( - ctx.peer().server().identity(), *pid, + *state->idReq, *state->idRsp, state->nonce, *response)); std::thread(&PairingServiceBase::waitForConfirmation, this, ctx.peer(), state, confirm, responseHook).detach(); @@ -116,8 +136,11 @@ void PairingServiceBase::handle(Context & ctx) } else if (auto reqnonce = rec->item("reqnonce").asBinary()) { + if (state->phase != StatePhase::PeerRequest) + return; + auto check = nonceDigest( - *pid, ctx.peer().server().identity(), + *state->idReq, *state->idRsp, *reqnonce, vector()); if (check != state->peerCheck) { if (requestNonceFailedHook) @@ -131,7 +154,7 @@ void PairingServiceBase::handle(Context & ctx) if (requestHook) { string confirm = confirmationNumber(nonceDigest( - *pid, ctx.peer().server().identity(), + *state->idReq, *state->idRsp, *reqnonce, state->nonce)); std::thread(&PairingServiceBase::waitForConfirmation, this, ctx.peer(), state, confirm, requestHook).detach(); @@ -174,25 +197,29 @@ void PairingServiceBase::requestPairing(UUID serviceId, const Peer & peer) } state->phase = StatePhase::OurRequest; + state->idReq = peer.server().identity(); + state->idRsp = pid; state->nonce.resize(32); RAND_bytes(state->nonce.data(), state->nonce.size()); vector items; + items.emplace_back("id-req", state->idReq->ref().value()); + items.emplace_back("id-rsp", state->idRsp->ref().value()); items.emplace_back("request", nonceDigest( - peer.server().identity(), *pid, + *state->idReq, *state->idRsp, state->nonce, vector())); peer.send(serviceId, Object(Record(std::move(items)))); } -vector PairingServiceBase::nonceDigest(const Identity & id1, const Identity & id2, - const vector & nonce1, const vector & nonce2) +vector PairingServiceBase::nonceDigest(const Identity & idReq, const Identity & idRsp, + const vector & nonceReq, const vector & nonceRsp) { vector items; - items.emplace_back("id", id1.ref().value()); - items.emplace_back("id", id2.ref().value()); - items.emplace_back("nonce", nonce1); - items.emplace_back("nonce", nonce2); + items.emplace_back("id-req", idReq.ref().value()); + items.emplace_back("id-rsp", idRsp.ref().value()); + items.emplace_back("nonce-req", nonceReq); + items.emplace_back("nonce-rsp", nonceRsp); const auto arr = Digest::of(Object(Record(std::move(items)))).arr(); vector ret(arr.size()); -- cgit v1.2.3