From f9b1d780cfc03a9806ecc047cd10190310d0ed7d Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 6 Apr 2020 11:29:45 +0100 Subject: [PATCH] encrypt PBFT request and response messages (#1034) --- src/consensus/pbft/pbft.h | 113 +++++++++++++++++++++++++------- src/consensus/pbft/pbft_types.h | 1 + src/node/channels.h | 2 +- src/node/node_to_node.h | 18 +++-- src/node/rpc/forwarder.h | 6 +- src/node/test/channel_stub.h | 5 +- 6 files changed, 114 insertions(+), 31 deletions(-) diff --git a/src/consensus/pbft/pbft.h b/src/consensus/pbft/pbft.h index d4b34d06bf0..ee68f5e7e6d 100644 --- a/src/consensus/pbft/pbft.h +++ b/src/consensus/pbft/pbft.h @@ -138,6 +138,15 @@ namespace pbft } } + bool should_encrypt(int tag) + { +#ifdef USE_NULL_ENCRYPTOR + return false; +#else + return tag == Request_tag || tag == Reply_tag; +#endif + } + std::vector serialized_msg; public: @@ -193,16 +202,19 @@ namespace pbft struct SendAuthenticatedMsg { SendAuthenticatedMsg( + bool should_encrypt_, std::vector data_, PbftEnclaveNetwork* self_, ccf::NodeMsgType type_, pbft::NodeId to_) : + should_encrypt(should_encrypt_), data(std::move(data_)), self(self_), type(type_), to(to_) {} + bool should_encrypt; std::vector data; ccf::NodeMsgType type; pbft::NodeId to; @@ -212,8 +224,18 @@ namespace pbft static void send_authenticated_msg_cb( std::unique_ptr> msg) { - msg->data.self->n2n_channels->send_authenticated( - msg->data.type, msg->data.to, msg->data.data); + if (msg->data.should_encrypt) + { + PbftHeader hdr = {PbftMsgType::encrypted_pbft_message, + msg->data.self->id}; + msg->data.self->n2n_channels->send_encrypted( + ccf::NodeMsgType::consensus_msg, msg->data.to, msg->data.data, hdr); + } + else + { + msg->data.self->n2n_channels->send_authenticated( + msg->data.type, msg->data.to, msg->data.data); + } } int Send(Message* msg, IPrincipal& principal) override @@ -245,15 +267,27 @@ namespace pbft return msg->size(); } - PbftHeader hdr = {PbftMsgType::pbft_message, id}; - auto space = (sizeof(PbftHeader) + msg->size()); - serialized_msg.resize(space); - auto data_ = serialized_msg.data(); - serialized::write(data_, space, hdr); - serialize_message(data_, space, msg); + bool encrypt = should_encrypt(msg->tag()); + if (encrypt) + { + size_t space = msg->size(); + serialized_msg.resize(space); + auto data_ = serialized_msg.data(); + serialize_message(data_, space, msg); + } + else + { + PbftHeader hdr = {PbftMsgType::pbft_message, id}; + auto space = (sizeof(PbftHeader) + msg->size()); + serialized_msg.resize(space); + auto data_ = serialized_msg.data(); + serialized::write(data_, space, hdr); + serialize_message(data_, space, msg); + } auto tmsg = std::make_unique>( &send_authenticated_msg_cb, + encrypt, std::move(serialized_msg), this, ccf::NodeMsgType::consensus_msg, @@ -580,12 +614,16 @@ namespace pbft struct RecvAuthenticatedMsg { RecvAuthenticatedMsg( - OArray&& d_, Pbft* self_) : + bool should_decrypt_, + OArray&& d_, + Pbft* self_) : + should_decrypt(should_decrypt_), d(std::move(d_)), self(self_), result(false) {} + bool should_decrypt; OArray d; Pbft* self; bool result; @@ -594,21 +632,40 @@ namespace pbft static void recv_authenticated_msg_cb( std::unique_ptr> msg) { - try + if (msg->data.should_decrypt) { - auto r = msg->data.self->channels - ->template recv_authenticated_with_load( - msg->data.d.data(), msg->data.d.size()); - msg->data.d.data() = r.p; - msg->data.d.size() = r.n; - msg->data.result = true; + std::pair> r; + try + { + r = msg->data.self->channels->template recv_encrypted( + msg->data.d.data(), msg->data.d.size()); + OArray decrypted(std::move(r.second)); + msg->data.d = std::move(decrypted); + } + catch (const std::logic_error& err) + { + LOG_FAIL_FMT("Invalid encrypted pbft message: {}", err.what()); + return; + } } - catch (const std::logic_error& err) + else { - LOG_FAIL_FMT("Invalid pbft message: {}", err.what()); - return; + try + { + auto r = msg->data.self->channels + ->template recv_authenticated_with_load( + msg->data.d.data(), msg->data.d.size()); + msg->data.d.data() = r.p; + msg->data.d.size() = r.n; + } + catch (const std::logic_error& err) + { + LOG_FAIL_FMT("Invalid pbft message: {}", err.what()); + return; + } } + msg->data.result = true; enclave::ThreadMessaging::ChangeTmsgCallback( msg, &recv_authenticated_msg_process_cb); if (enclave::ThreadMessaging::thread_count > 1) @@ -638,13 +695,25 @@ namespace pbft PbftHeader hdr = serialized::peek(data, size); switch (hdr.msg) { + case encrypted_pbft_message: case pbft_message: { + bool should_decrypt = (hdr.msg == encrypted_pbft_message); auto tmsg = std::make_unique>( - &recv_authenticated_msg_cb, std::move(d), this); + &recv_authenticated_msg_cb, should_decrypt, std::move(d), this); - auto recv_nonce = channels->template get_recv_nonce( - tmsg->data.d.data(), tmsg->data.d.size()); + ccf::RecvNonce recv_nonce(0); + if (should_decrypt) + { + recv_nonce = + channels->template get_encrypted_recv_nonce( + tmsg->data.d.data(), tmsg->data.d.size()); + } + else + { + recv_nonce = channels->template get_recv_nonce( + tmsg->data.d.data(), tmsg->data.d.size()); + } if (enclave::ThreadMessaging::thread_count > 1) { diff --git a/src/consensus/pbft/pbft_types.h b/src/consensus/pbft/pbft_types.h index eceaf0352da..0764ce73876 100644 --- a/src/consensus/pbft/pbft_types.h +++ b/src/consensus/pbft/pbft_types.h @@ -18,6 +18,7 @@ namespace pbft enum PbftMsgType : Node2NodeMsg { pbft_message = 1000, + encrypted_pbft_message, pbft_append_entries }; diff --git a/src/node/channels.h b/src/node/channels.h index a3a3381bf4d..c3b7d3ca657 100644 --- a/src/node/channels.h +++ b/src/node/channels.h @@ -185,7 +185,7 @@ namespace ccf key->encrypt(header.get_iv(), nullb, aad, nullptr, header.tag); } - RecvNonce get_nonce(const GcmHdr& header) + static RecvNonce get_nonce(const GcmHdr& header) { return RecvNonce(header.get_iv_int()); } diff --git a/src/node/node_to_node.h b/src/node/node_to_node.h index ad6871bbc4c..51547d4d1d7 100644 --- a/src/node/node_to_node.h +++ b/src/node/node_to_node.h @@ -123,9 +123,15 @@ namespace ccf const auto& t = serialized::overlay(data, size); serialized::skip(data, size, (size - sizeof(GcmHdr))); const auto& hdr = serialized::overlay(data, size); - auto& n2n_channel = channels->get(t.from_node); + return ccf::Channel::get_nonce(hdr); + } - return n2n_channel.get_nonce(hdr); + template + RecvNonce get_encrypted_recv_nonce(const uint8_t* data, size_t size) + { + const auto& t = serialized::overlay(data, size); + const auto& hdr = serialized::overlay(data, size); + return ccf::Channel::get_nonce(hdr); } template @@ -156,7 +162,10 @@ namespace ccf template bool send_encrypted( - NodeId to, const std::vector& data, const T& msg_hdr) + const NodeMsgType& msg_type, + NodeId to, + const std::vector& data, + const T& msg_hdr) { auto& n2n_channel = channels->get(to); if (!try_established_channel(to, n2n_channel)) @@ -168,8 +177,7 @@ namespace ccf std::vector cipher(data.size()); n2n_channel.encrypt(hdr, asCb(msg_hdr), data, cipher); - to_host->write( - node_outbound, to, NodeMsgType::forwarded_msg, msg_hdr, hdr, cipher); + to_host->write(node_outbound, to, msg_type, msg_hdr, hdr, cipher); return true; } diff --git a/src/node/rpc/forwarder.h b/src/node/rpc/forwarder.h index 0e8616ed77d..a284d0edfee 100644 --- a/src/node/rpc/forwarder.h +++ b/src/node/rpc/forwarder.h @@ -77,7 +77,8 @@ namespace ccf ForwardedHeader msg = {ForwardedMsg::forwarded_cmd, self}; - return n2n_channels->send_encrypted(to, plain, msg); + return n2n_channels->send_encrypted( + NodeMsgType::forwarded_msg, to, plain, msg); } std::optional, NodeId>> @@ -130,7 +131,8 @@ namespace ccf ForwardedHeader msg = {ForwardedMsg::forwarded_response, self}; - return n2n_channels->send_encrypted(from_node, plain, msg); + return n2n_channels->send_encrypted( + NodeMsgType::forwarded_msg, from_node, plain, msg); } std::optional>> diff --git a/src/node/test/channel_stub.h b/src/node/test/channel_stub.h index a5dd62d3104..964105a39bf 100644 --- a/src/node/test/channel_stub.h +++ b/src/node/test/channel_stub.h @@ -18,7 +18,10 @@ namespace ccf template bool send_encrypted( - NodeId to, const std::vector& data, const T& msg) + const NodeMsgType& msg_type, + NodeId to, + const std::vector& data, + const T& msg) { sent_encrypted_messages.push_back(data); return true;