CCF
Loading...
Searching...
No Matches
channels.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
6#include "ccf/crypto/hkdf.h"
11#include "ccf/ds/hex.h"
12#include "ccf/ds/logger.h"
13#include "ccf/entity_id.h"
14#include "ccf/pal/locking.h"
15#include "crypto/key_exchange.h"
16#include "ds/serialized.h"
17#include "ds/state_machine.h"
18#include "ds/thread_messaging.h"
19#include "node_types.h"
20
21#include <iostream>
22#include <map>
23#include <openssl/crypto.h>
24
25// -Wpedantic flags token pasting of __VA_ARGS__
26#pragma clang diagnostic push
27#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
28
29#define CHANNEL_RECV_TRACE(s, ...) \
30 LOG_TRACE_FMT("<- {} ({}): " s, peer_id, status.value(), ##__VA_ARGS__)
31#define CHANNEL_SEND_TRACE(s, ...) \
32 LOG_TRACE_FMT("-> {} ({}): " s, peer_id, status.value(), ##__VA_ARGS__)
33
34#define CHANNEL_RECV_FAIL(s, ...) \
35 LOG_FAIL_FMT("<- {} ({}): " s, peer_id, status.value(), ##__VA_ARGS__)
36#define CHANNEL_SEND_FAIL(s, ...) \
37 LOG_FAIL_FMT("-> {} ({}): " s, peer_id, status.value(), ##__VA_ARGS__)
38
39namespace ccf
40{
48}
49
50FMT_BEGIN_NAMESPACE
51template <>
52struct formatter<ccf::ChannelStatus>
53{
54 template <typename ParseContext>
55 constexpr auto parse(ParseContext& ctx)
56 {
57 return ctx.begin();
58 }
59
60 template <typename FormatContext>
61 auto format(const ccf::ChannelStatus& cs, FormatContext& ctx) const
62 {
63 char const* s = "Unknown";
64 switch (cs)
65 {
66 case (ccf::INACTIVE):
67 {
68 s = "INACTIVE";
69 break;
70 }
71 case (ccf::INITIATED):
72 {
73 s = "INITIATED";
74 break;
75 }
77 {
78 s = "WAITING_FOR_FINAL";
79 break;
80 }
81 case (ccf::ESTABLISHED):
82 {
83 s = "ESTABLISHED";
84 break;
85 }
86 }
87
88 return format_to(ctx.out(), "{}", s);
89 }
90};
91FMT_END_NAMESPACE
92
93namespace ccf
94{
95 using MsgNonce = uint64_t;
97
98 // Receive nonces were previously stored per-thread. For backwards
99 // compatibility (live communication with nodes still using this format), we
100 // maintain this serialization struct, but with thread ID (tid) always set to
101 // 0
103 {
104 const uint8_t tid = 0;
105 uint64_t nonce : (sizeof(MsgNonce) - sizeof(tid)) * CHAR_BIT;
106
107 WireNonce(uint64_t nonce_) : nonce(nonce_) {}
108
109 uint64_t get_val() const
110 {
111 return *reinterpret_cast<const uint64_t*>(this);
112 }
113 };
114 static_assert(
115 sizeof(WireNonce) == sizeof(MsgNonce), "WireNonce is the wrong size");
116
117 // Static helper functions for serialization/deserialization
118 namespace
119 {
120 static inline WireNonce get_wire_nonce(const GcmHdr& header)
121 {
122 return *reinterpret_cast<const WireNonce*>(header.iv.data());
123 }
124
125 template <typename T>
126 static inline void append_value(std::vector<uint8_t>& target, const T& t)
127 {
128 const auto size_before = target.size();
129 auto size = sizeof(t);
130 target.resize(size_before + size);
131 auto data = target.data() + size_before;
132 serialized::write(data, size, t);
133 }
134
135 static inline void append_buffer(
136 std::vector<uint8_t>& target, std::span<const uint8_t> src)
137 {
138 const auto size_before = target.size();
139 auto size = src.size() + sizeof(src.size());
140 target.resize(size_before + size);
141 auto data = target.data() + size_before;
142 serialized::write(data, size, src.size());
143 serialized::write(data, size, src.data(), src.size());
144 }
145 }
146
147 // Key exchange states are:
148 // - Have nothing
149 // - Initiated (have my own share)
150 // - Have their share and my share (received init, or received response)
151 // - => Have shared secret
152 // - Know that THEY have shared secret (received response or final)
153 // As soon as we have both shares, we update our send key
154 // As soon as we know that they have shared secret, we update our recv key
155 // Note this assumes that the key exchange messages are reliably delivered,
156 // else we switch keys without telling the peer that we did.
157
159 {
160 public:
161 static std::chrono::system_clock::duration&
163 {
164 static std::chrono::system_clock::duration value =
165 std::chrono::seconds(2);
166 return value;
167 }
168
169 private:
170 struct OutgoingMsg
171 {
172 NodeMsgType type;
173 std::vector<uint8_t> raw_aad; // To be integrity-protected
174 std::vector<uint8_t> raw_plain; // To be encrypted
175
176 OutgoingMsg(
177 NodeMsgType msg_type,
178 std::span<const uint8_t> raw_aad_,
179 std::span<const uint8_t> raw_plain_) :
180 type(msg_type),
181 raw_aad(raw_aad_.begin(), raw_aad_.end()),
182 raw_plain(raw_plain_.begin(), raw_plain_.end())
183 {}
184 };
185
186 ccf::pal::Mutex lock;
187
188 NodeId self;
189 const ccf::crypto::Pem& service_cert;
191 const ccf::crypto::Pem& node_cert;
193 ccf::crypto::Pem peer_cert;
194
195 ringbuffer::WriterPtr to_host;
196 NodeId peer_id;
197
198 // Used for key exchange
201 std::chrono::system_clock::time_point last_initiation_time;
202 static constexpr size_t salt_len = 32;
203 static constexpr size_t shared_key_size = 32;
204 std::vector<uint8_t> hkdf_salt;
205 size_t message_limit;
206
207 // Used for AES GCM authentication/encryption
208 std::unique_ptr<ccf::crypto::KeyAesGcm> recv_key = nullptr;
209 std::unique_ptr<ccf::crypto::KeyAesGcm> send_key = nullptr;
210
211 // Incremented for each tagged/encrypted message
212 std::atomic<MsgNonce> send_nonce{1};
213
214 // Used to buffer at most one message sent on the channel before it is
215 // established
216 std::optional<OutgoingMsg> outgoing_consensus_msg;
217
218 // Used to buffer a small number of messages sent on the channel before it
219 // is established. If this queue fills, then additional send attempts while
220 // the channel is still being established will not be buffered, and the
221 // caller should react appropriately.
222 static constexpr size_t outgoing_forwarding_queue_size = 10;
223 std::vector<OutgoingMsg> outgoing_forwarding_msgs;
224
225 // Used to prevent replayed messages.
226 // Set to the latest successfully received nonce.
227 MsgNonce local_recv_nonce = {0};
228
229 void check_message_limit()
230 {
231 // At half message limit, trigger a new key exchange.
232 // At hard message limit, drop existing keys, ensuring no further
233 // communication until fresh keys have been exchanged
234 const auto lower_limit = message_limit / 2;
235 size_t num_messages = send_nonce + local_recv_nonce;
236 if (num_messages >= lower_limit && status.check(ESTABLISHED))
237 {
239 "Reached message limit ({}+{} >= {}), triggering new key exchange",
240 send_nonce,
241 local_recv_nonce,
242 lower_limit);
243 reset_key_exchange();
244 initiate();
245 }
246 else if (num_messages >= message_limit)
247 {
249 "Reached hard message limit ({}+{} >= {}), dropping previous keys",
250 send_nonce,
251 local_recv_nonce,
252 message_limit);
253
254 send_key = nullptr;
255 send_nonce = 0;
256 recv_key = nullptr;
257 local_recv_nonce = 0;
258 reset_key_exchange();
259 initiate();
260 }
261 }
262
263 bool decrypt(
264 const GcmHdr& header,
265 std::span<const uint8_t> aad,
266 std::span<const uint8_t> cipher,
267 std::vector<uint8_t>& plain)
268 {
269 if (recv_key == nullptr)
270 {
271 throw std::logic_error("Tried to decrypt, but have no receive key");
272 }
273
274 auto wire_nonce = get_wire_nonce(header);
275 auto recv_nonce = wire_nonce.nonce;
276
278 "decrypt({} bytes, {} bytes) (nonce={})",
279 aad.size(),
280 cipher.size(),
281 recv_nonce);
282
283 // Note: We must assume that some messages are dropped, i.e. we may not
284 // see every nonce/sequence number, but they must be increasing.
285
286 if (recv_nonce <= local_recv_nonce)
287 {
288 // If the nonce received has already been processed, return
289 // See https://github.com/microsoft/CCF/issues/2492 for more details on
290 // how this can happen around election time
292 "Received past nonce, received:{}, "
293 "last_seen:{}",
294 recv_nonce,
295 local_recv_nonce);
296 return false;
297 }
298
299 auto ret =
300 recv_key->decrypt(header.get_iv(), header.tag, cipher, aad, plain);
301 if (ret)
302 {
303 // Set local recv nonce to received nonce only if verification is
304 // successful
305 local_recv_nonce = recv_nonce;
306 }
307
308 check_message_limit();
309
310 return ret;
311 }
312
313 bool verify(const GcmHdr& header, std::span<const uint8_t> aad)
314 {
315 std::vector<uint8_t> empty_plaintext;
316 return decrypt(header, aad, {}, empty_plaintext);
317 }
318
319 void send_key_exchange_init()
320 {
321 std::vector<uint8_t> payload;
322 {
323 append_value(payload, ChannelMsg::key_exchange_init);
324 append_value(payload, protocol_version);
325 append_buffer(payload, kex_ctx.get_own_key_share());
326 auto signature = node_kp->sign(kex_ctx.get_own_key_share());
327 append_buffer(payload, signature);
328 append_buffer(
329 payload,
330 std::span<const uint8_t>(node_cert.data(), node_cert.size()));
331 append_buffer(payload, hkdf_salt);
332 }
333
335 "send_key_exchange_init: node serial: {}",
336 make_verifier(node_cert)->serial_number());
337
339 node_outbound,
340 to_host,
341 peer_id.value(),
343 self.value(),
344 payload);
345 }
346
347 void send_key_exchange_response()
348 {
349 std::vector<uint8_t> signature;
350 {
351 auto to_sign = kex_ctx.get_own_key_share();
352 const auto& peer_ks = kex_ctx.get_peer_key_share();
353 to_sign.insert(to_sign.end(), peer_ks.begin(), peer_ks.end());
354 signature = node_kp->sign(to_sign);
355 }
356
357 std::vector<uint8_t> payload;
358 {
359 append_value(payload, ChannelMsg::key_exchange_response);
360 append_value(payload, protocol_version);
361 append_buffer(payload, kex_ctx.get_own_key_share());
362 append_buffer(payload, signature);
363 append_buffer(
364 payload,
365 std::span<const uint8_t>(node_cert.data(), node_cert.size()));
366 }
367
369 "send_key_exchange_response: oks={}, serialised_signed_share={}",
370 ds::to_hex(kex_ctx.get_own_key_share()),
371 ds::to_hex(payload));
372
374 node_outbound,
375 to_host,
376 peer_id.value(),
378 self.value(),
379 payload);
380 }
381
382 void send_key_exchange_final()
383 {
384 std::vector<uint8_t> payload;
385 {
386 append_value(payload, ChannelMsg::key_exchange_final);
387 // append_value(payload, protocol_version); // Not sent by
388 // current protocol!
389 auto signature = node_kp->sign(kex_ctx.get_peer_key_share());
390 append_buffer(payload, signature);
391 }
392
394 "key_exchange_final: ks={}, serialised_signed_key_share={}",
395 ds::to_hex(kex_ctx.get_peer_key_share()),
396 ds::to_hex(payload));
397
399 node_outbound,
400 to_host,
401 peer_id.value(),
403 self.value(),
404 payload);
405 }
406
407 void advance_connection_attempt()
408 {
409 if (status.check(INACTIVE))
410 {
411 // We have no key and believe no key exchange is in process - start a
412 // new iteration of the key exchange protocol
413 initiate();
414 }
415 else if (status.check(INITIATED))
416 {
417 const auto time_since_initiated =
418 decltype(last_initiation_time)::clock::now() - last_initiation_time;
419 if (time_since_initiated >= min_gap_between_initiation_attempts())
420 {
421 // If this node attempts to initiate too early when the peer node
422 // starts up, they will never receive the init message (they drop it
423 // if it arrives too early in their state machine). The same state
424 // could also occur later, if the initiate message is lost in transit.
425 // So sometimes this node needs to re-initiate. However, if this node
426 // sends too fast before the channel is established, and each send
427 // generates a new handshake, it may constantly generate new handshake
428 // attempts and never succeed. Additionally, when talking to peers
429 // using the old channel behaviour, this node should try to avoid
430 // confusing them by sending multiple adjacent initiate requests -
431 // they will only process the first one they receive. To avoid these
432 // problems with initiation spam, we have a minimum delay between
433 // initiation attempts. This should be low enough to get reasonable
434 // liveness (re-attempt connections in the presence of dropped
435 // messages), but high enough to give successful roundtrips a chance
436 // to complete.
437 initiate();
438 }
439 }
440 }
441
442 bool recv_key_exchange_init(
443 const uint8_t* data, size_t size, bool they_have_priority = false)
444 {
446 "recv_key_exchange_init({} bytes, {})", size, they_have_priority);
447
448 // Parse fields from incoming message
449 size_t peer_version = serialized::read<size_t>(data, size);
450 if (peer_version != protocol_version)
451 {
453 "Protocol version mismatch (node={}, peer={})",
455 peer_version);
456 return false;
457 }
458
459 auto ks = extract_span(data, size);
460 if (ks.empty())
461 {
462 CHANNEL_RECV_FAIL("Empty keyshare");
463 return false;
464 }
465
466 auto sig = extract_span(data, size);
467 if (sig.empty())
468 {
469 CHANNEL_RECV_FAIL("Empty signature");
470 return false;
471 }
472
473 auto pc = extract_span(data, size);
474 if (pc.empty())
475 {
476 CHANNEL_RECV_FAIL("Empty cert");
477 return false;
478 }
479
480 auto salt = extract_span(data, size);
481 if (salt.empty())
482 {
483 CHANNEL_RECV_FAIL("Empty salt");
484 return false;
485 }
486
487 if (size != 0)
488 {
489 CHANNEL_RECV_FAIL("{} exccess bytes remaining", size);
490 return false;
491 }
492
493 // Validate cert and signature in message
494 ccf::crypto::Pem cert;
496 if (!verify_peer_certificate(pc, cert, verifier))
497 {
499 "Peer certificate verification failed - recv_key_exchange_init "
500 "failed to verify peer cert:\n{}\nUsing trusted service "
501 "certificate:\n{}",
502 cert.str(),
503 service_cert.str());
504 return false;
505 }
506
507 if (!verify_peer_signature(ks, sig, verifier))
508 {
509 return false;
510 }
511
512 // Both nodes tried to initiate the channel, the one with priority
513 // wins.
514 if (status.check(INITIATED) && !they_have_priority)
515 {
516 CHANNEL_RECV_TRACE("Ignoring lower priority key init");
517 return true;
518 }
519 else
520 {
521 // Whatever else we _were_ doing, we've received a valid init from them
522 // - reset to use it
523 if (status.check(ESTABLISHED))
524 {
525 kex_ctx.reset();
526 }
527 peer_cert = cert;
528 peer_cv = verifier;
529 }
530
532 "recv_key_exchange_init: version={} ks={} sig={} pc={} salt={}",
533 peer_version,
534 ds::to_hex(ks),
535 ds::to_hex(sig),
536 ds::to_hex(pc),
537 ds::to_hex(salt));
538
539 hkdf_salt = {salt.data(), salt.data() + salt.size()};
540
541 kex_ctx.load_peer_key_share(ks);
542
543 update_send_key();
544
546
547 // We are the responder and we return a signature over both public key
548 // shares back to the initiator
549 send_key_exchange_response();
550
551 flush_pending_outgoing();
552
553 return true;
554 }
555
556 bool recv_key_exchange_response(const uint8_t* data, size_t size)
557 {
558 CHANNEL_RECV_TRACE("recv_key_exchange_response({} bytes)", size);
559
560 if (status.value() != INITIATED)
561 {
562 CHANNEL_RECV_FAIL("Ignoring key exchange response - not expecting it");
563 return false;
564 }
565
566 // Parse fields from incoming message
567 size_t peer_version = serialized::read<size_t>(data, size);
568 if (peer_version != protocol_version)
569 {
571 "Protocol version mismatch (node={}, peer={})",
573 peer_version);
574 return false;
575 }
576
577 auto ks = extract_span(data, size);
578 if (ks.empty())
579 {
580 CHANNEL_RECV_FAIL("Empty keyshare");
581 return false;
582 }
583
584 auto sig = extract_span(data, size);
585 if (sig.empty())
586 {
587 CHANNEL_RECV_FAIL("Empty signature");
588 return false;
589 }
590
591 auto pc = extract_span(data, size);
592 if (pc.empty())
593 {
594 CHANNEL_RECV_FAIL("Empty cert");
595 return false;
596 }
597
598 if (size != 0)
599 {
600 CHANNEL_RECV_FAIL("{} exccess bytes remaining", size);
601 return false;
602 }
603
604 // Validate cert and signature in message
605 ccf::crypto::Pem cert;
607 if (!verify_peer_certificate(pc, cert, verifier))
608 {
610 "Peer certificate verification failed - recv_key_exchange_response "
611 "failed to verify peer cert:\n{}\nUsing trusted service "
612 "certificate:\n{}",
613 cert.str(),
614 service_cert.str());
615 return false;
616 }
617
618 {
619 // We are the initiator and expect a signature over both key shares
620 std::vector<uint8_t> signed_msg(ks.begin(), ks.end());
621 const auto& oks = kex_ctx.get_own_key_share();
622 signed_msg.insert(signed_msg.end(), oks.begin(), oks.end());
623
624 if (!verify_peer_signature(signed_msg, sig, verifier))
625 {
626 // This isn't a valid signature for this key exchange attempt.
628 "Peer certificate verification failed - recv_key_exchange_response "
629 "failed to verify signature from cert:\n{}",
630 cert.str());
631 return false;
632 }
633 }
634
635 peer_cert = cert;
636 peer_cv = verifier;
637
638 kex_ctx.load_peer_key_share(ks);
639
640 update_send_key();
641
642 send_key_exchange_final();
643
644 flush_pending_outgoing();
645
646 update_recv_key();
647
648 establish();
649
650 return true;
651 }
652
653 bool recv_key_exchange_final(const uint8_t* data, size_t size)
654 {
655 CHANNEL_RECV_TRACE("recv_key_exchange_final({} bytes)", size);
656
657 if (status.value() != WAITING_FOR_FINAL)
658 {
659 CHANNEL_RECV_FAIL("Ignoring key exchange final - not expecting it");
660 return false;
661 }
662
663 // Parse fields from incoming message
664 // size_t peer_version = serialized::read<size_t>(data, size);
665 // if (peer_version != protocol_version)
666 // {
667 // CHANNEL_RECV_FAIL(
668 // "Protocol version mismatch (node={}, peer={})",
669 // protocol_version,
670 // peer_version);
671 // return false;
672 // }
673
674 auto sig = extract_span(data, size);
675 if (sig.empty())
676 {
677 CHANNEL_RECV_FAIL("Empty signature");
678 return false;
679 }
680
681 if (!verify_peer_signature(kex_ctx.get_own_key_share(), sig, peer_cv))
682 {
684 "Peer certificate verification failed - recv_key_exchange_final "
685 "failed to verify signature from peer with serial number {}",
686 peer_cv->serial_number());
687 return false;
688 }
689
690 update_recv_key();
691
692 establish();
693
694 return true;
695 }
696
697 std::span<const uint8_t> extract_span(
698 const uint8_t*& data, size_t& size) const
699 {
700 if (size == 0)
701 {
702 return {};
703 }
704
705 auto sz = serialized::read<size_t>(data, size);
706 const uint8_t* data_start = data;
707
708 if (sz > size)
709 {
711 "Buffer header wants {} bytes, but only {} remain", sz, size);
712 return {};
713 }
714 else
715 {
716 data += sz;
717 size -= sz;
718 }
719
720 return std::span<const uint8_t>(data_start, sz);
721 }
722
723 bool verify_peer_certificate(
724 std::span<const uint8_t> pc,
725 ccf::crypto::Pem& cert,
726 ccf::crypto::VerifierPtr& verifier)
727 {
728 if (!pc.empty())
729 {
730 cert = ccf::crypto::Pem(pc);
731 verifier = ccf::crypto::make_verifier(cert);
732
733 // 'true' is `ignore_time` => These node-to-node channels do not care
734 // about certificate times, and should still pass even when given
735 // expired certs
736 if (!verifier->verify_certificate(
737 {&service_cert}, {}, true /* no validity expiration check */))
738 {
739 return false;
740 }
741
743 "New peer certificate: {}\n{}",
744 verifier->serial_number(),
745 cert.str());
746
747 return true;
748 }
749 else
750 {
751 return false;
752 }
753 }
754
755 bool verify_peer_signature(
756 std::span<const uint8_t> msg,
757 std::span<const uint8_t> sig,
759 {
761 "Verifying peer signature with peer certificate serial {}",
762 verifier ? verifier->serial_number() : "no peer_cv!");
763
764 if (!verifier || !verifier->verify(msg, sig))
765 {
766 return false;
767 }
768
769 return true;
770 }
771
772 void update_send_key()
773 {
774 const std::string label_to = self.value() + peer_id.value();
775 const std::span<const uint8_t> label(
776 reinterpret_cast<const uint8_t*>(label_to.c_str()), label_to.size());
777 const auto key_bytes = ccf::crypto::hkdf(
779 shared_key_size,
780 kex_ctx.get_shared_secret(),
781 hkdf_salt,
782 label);
783 send_key = ccf::crypto::make_key_aes_gcm(key_bytes);
784
785 send_nonce = 1;
786 }
787
788 void update_recv_key()
789 {
790 const std::string label_from = peer_id.value() + self.value();
791 const std::span<const uint8_t> label(
792 reinterpret_cast<const uint8_t*>(label_from.c_str()),
793 label_from.size());
794 const auto key_bytes = ccf::crypto::hkdf(
796 shared_key_size,
797 kex_ctx.get_shared_secret(),
798 hkdf_salt,
799 label);
800 recv_key = ccf::crypto::make_key_aes_gcm(key_bytes);
801
802 local_recv_nonce = 0;
803 }
804
805 void establish()
806 {
807 status.advance(ESTABLISHED);
808 LOG_INFO_FMT("Node channel with {} is now established.", peer_id);
809
810 kex_ctx.reset();
811
812 auto node_cv = make_verifier(node_cert);
814 "Node certificate serial numbers: node={} peer={}",
815 node_cv->serial_number(),
816 peer_cv->serial_number());
817 }
818
819 void flush_pending_outgoing()
820 {
821 if (outgoing_consensus_msg.has_value())
822 {
823 send_unsafe(
824 outgoing_consensus_msg->type,
825 outgoing_consensus_msg->raw_aad,
826 outgoing_consensus_msg->raw_plain);
827 outgoing_consensus_msg.reset();
828 }
829
830 for (auto& outgoing_msg : outgoing_forwarding_msgs)
831 {
832 send_unsafe(
833 outgoing_msg.type, outgoing_msg.raw_aad, outgoing_msg.raw_plain);
834 CHANNEL_SEND_TRACE("Flushing previously queued forwarding message");
835 }
836 outgoing_forwarding_msgs.clear();
837 }
838
839 void initiate()
840 {
841 LOG_INFO_FMT("Initiating node channel with {}.", peer_id);
842
843 // Begin with new key exchange
844 kex_ctx.reset();
845 peer_cert = {};
846 peer_cv.reset();
847
848 auto e = ccf::crypto::get_entropy();
849 hkdf_salt = e->random(salt_len);
850
851 // As a future simplification, we would like this to always be true
852 // (initiations must travel through reset/inactive), but it is not
853 // currently true
854 // status.expect(INACTIVE);
855 status.advance(INITIATED);
856
857 last_initiation_time = decltype(last_initiation_time)::clock::now();
858
859 send_key_exchange_init();
860 }
861
862 void reset_key_exchange()
863 {
864 LOG_INFO_FMT("Resetting channel with {}", peer_id);
865
866 status.advance(INACTIVE);
867 kex_ctx.reset();
868 peer_cert = {};
869 peer_cv.reset();
870
871 auto e = ccf::crypto::get_entropy();
872 hkdf_salt = e->random(salt_len);
873 }
874
875 bool send_unsafe(
876 NodeMsgType type,
877 std::span<const uint8_t> aad,
878 std::span<const uint8_t> plain)
879 {
880 if (send_key == nullptr)
881 {
882 advance_connection_attempt();
883 switch (type)
884 {
886 {
887 if (outgoing_consensus_msg.has_value())
888 {
890 "Dropping outgoing consensus message - replaced by new "
891 "consensus message");
892 }
893 outgoing_consensus_msg = OutgoingMsg(type, aad, plain);
894 return true;
895 }
896
898 {
899 if (
900 outgoing_forwarding_msgs.size() < outgoing_forwarding_queue_size)
901 {
902 outgoing_forwarding_msgs.emplace_back(type, aad, plain);
904 "Queueing outgoing forwarding message - the is the {}/{} "
905 "buffered message",
906 outgoing_forwarding_msgs.size(),
907 outgoing_forwarding_queue_size);
908 return true;
909 }
910 else
911 {
913 "Unable to queue outgoing forwarding message - already queued "
914 "maximum {} messages",
915 outgoing_forwarding_queue_size);
916 return false;
917 }
918 }
919
920 default:
921 {
923 "Unhandled message type {} on unestablished channel - ignoring",
924 type);
925 return false;
926 }
927 }
928 }
929
930 auto nonce = send_nonce.fetch_add(1);
931 WireNonce wire_nonce(nonce);
932
934 "send({}, {} bytes, {} bytes) (nonce={})",
935 (size_t)type,
936 aad.size(),
937 plain.size(),
938 nonce);
939
940 GcmHdr gcm_hdr;
941 gcm_hdr.set_iv((const uint8_t*)&wire_nonce, sizeof(wire_nonce));
942
943 std::vector<uint8_t> cipher;
944 assert(send_key);
945 send_key->encrypt(gcm_hdr.get_iv(), plain, aad, cipher, gcm_hdr.tag);
946
947 const auto gcm_hdr_serialised = gcm_hdr.serialise();
948
949 // Payload is concatenation of 3 things:
950 // 1) aad
951 // 2) gcm header
952 // 3) ciphertext
953 // NB: None of these are length-prefixed, so it is assumed that the
954 // receiver knows the fixed size of the aad and gcm header
955 const serializer::ByteRange payload[] = {
956 {aad.data(), static_cast<size_t>(aad.size())},
957 {gcm_hdr_serialised.data(),
958 static_cast<size_t>(gcm_hdr_serialised.size())},
959 {cipher.data(), static_cast<size_t>(cipher.size())}};
960
962 node_outbound, to_host, peer_id.value(), type, self.value(), payload);
963
964 check_message_limit();
965
966 return true;
967 }
968
969 public:
970 static constexpr size_t protocol_version = 1;
971
973 ringbuffer::AbstractWriterFactory& writer_factory,
974 const ccf::crypto::Pem& service_cert_,
976 const ccf::crypto::Pem& node_cert_,
977 const NodeId& self_,
978 const NodeId& peer_id_,
979 size_t message_limit_) :
980 self(self_),
981 service_cert(service_cert_),
982 node_kp(node_kp_),
983 node_cert(node_cert_),
984 to_host(writer_factory.create_writer_to_outside()),
985 peer_id(peer_id_),
986 status(fmt::format("Channel to {}", peer_id_), INACTIVE),
987 message_limit(message_limit_)
988 {
989 auto e = ccf::crypto::get_entropy();
990 hkdf_salt = e->random(salt_len);
991 }
992
994 {
995 std::lock_guard<ccf::pal::Mutex> guard(lock);
996 return recv_key != nullptr && send_key != nullptr;
997 }
998
999 // Protocol overview:
1000 //
1001 // initiate()
1002 // > key_exchange_init message
1003 // recv_key_exchange_init() [by responder]
1004 // < key_exchange_response message
1005 // recv_key_exchange_response() [by initiator]
1006 // > key_exchange_final message
1007 // recv_key_exchange_final() [by responder]
1008 // both reach status == ESTABLISHED
1009
1010 bool send(
1011 NodeMsgType type,
1012 std::span<const uint8_t> aad,
1013 std::span<const uint8_t> plain = {})
1014 {
1015 std::lock_guard<ccf::pal::Mutex> guard(lock);
1016
1017 return send_unsafe(type, aad, plain);
1018 }
1019
1021 std::span<const uint8_t> aad, const uint8_t*& data, size_t& size)
1022 {
1023 std::lock_guard<ccf::pal::Mutex> guard(lock);
1024
1025 // Receive authenticated message, modifying data to point to the start of
1026 // the non-authenticated plaintext payload
1027 if (recv_key == nullptr)
1028 {
1030 "Node channel with {} cannot receive authenticated message: not "
1031 "established a receive key, status={}",
1032 peer_id,
1033 status.value());
1034 advance_connection_attempt();
1035 return false;
1036 }
1037
1038 GcmHdr hdr;
1039 hdr.deserialise(data, size);
1040
1041 if (!verify(hdr, aad))
1042 {
1043 CHANNEL_RECV_FAIL("Failed to verify node");
1044 return false;
1045 }
1046
1047 return true;
1048 }
1049
1050 bool recv_authenticated_with_load(const uint8_t*& data, size_t& size)
1051 {
1052 std::lock_guard<ccf::pal::Mutex> guard(lock);
1053
1054 // Receive authenticated message, modifying data to point to the start of
1055 // the non-authenticated plaintext payload. data contains payload first,
1056 // then GCM header
1057
1058 if (recv_key == nullptr)
1059 {
1061 "Node channel with {} cannot receive authenticated message with "
1062 "payload: not established a receive key, status={}",
1063 peer_id,
1064 status.value());
1065 advance_connection_attempt();
1066 return false;
1067 }
1068
1069 const uint8_t* data_ = data;
1070 size_t size_ = size;
1071
1072 GcmHdr hdr;
1073 serialized::skip(data_, size_, (size_ - hdr.serialised_size()));
1074 hdr.deserialise(data_, size_);
1075 size -= hdr.serialised_size();
1076
1077 if (!verify(hdr, std::span<const uint8_t>(data, size)))
1078 {
1079 CHANNEL_RECV_FAIL("Failed to verify node message with payload");
1080 return false;
1081 }
1082
1083 return true;
1084 }
1085
1086 std::optional<std::vector<uint8_t>> recv_encrypted(
1087 std::span<const uint8_t> aad, const uint8_t*& data, size_t& size)
1088 {
1089 std::lock_guard<ccf::pal::Mutex> guard(lock);
1090
1091 // Receive encrypted message, returning the decrypted payload
1092 if (recv_key == nullptr)
1093 {
1095 "Node channel with {} cannot receive encrypted message: not "
1096 "established a receive key, status={}",
1097 peer_id,
1098 status.value());
1099 advance_connection_attempt();
1100 return std::nullopt;
1101 }
1102
1103 GcmHdr hdr;
1104 hdr.deserialise(data, size);
1105
1106 std::vector<uint8_t> plain;
1107 if (!decrypt(hdr, aad, std::span<const uint8_t>(data, size), plain))
1108 {
1109 CHANNEL_RECV_FAIL("Failed to decrypt node message");
1110 return std::nullopt;
1111 }
1112
1113 return plain;
1114 }
1115
1117 {
1118 std::lock_guard<ccf::pal::Mutex> guard(lock);
1119
1120 RINGBUFFER_WRITE_MESSAGE(close_node_outbound, to_host, peer_id.value());
1121 reset_key_exchange();
1122 outgoing_consensus_msg.reset();
1123
1124 recv_key.reset();
1125 send_key.reset();
1126 }
1127
1128 bool recv_key_exchange_message(const uint8_t* data, size_t size)
1129 {
1130 std::lock_guard<ccf::pal::Mutex> guard(lock);
1131
1132 try
1133 {
1134 auto chmsg = serialized::read<ChannelMsg>(data, size);
1135 switch (chmsg)
1136 {
1137 case key_exchange_init:
1138 {
1139 // In the case of concurrent key_exchange_init's from both nodes,
1140 // the one with the lower ID wins.
1141 return recv_key_exchange_init(data, size, self < peer_id);
1142 }
1143
1145 {
1146 return recv_key_exchange_response(data, size);
1147 }
1148
1149 case key_exchange_final:
1150 {
1151 return recv_key_exchange_final(data, size);
1152 }
1153
1154 default:
1155 {
1156 throw std::runtime_error(fmt::format(
1157 "Received message with initial bytes {} from {} - not recognised "
1158 "as a key exchange message",
1159 chmsg,
1160 peer_id));
1161 }
1162 }
1163 }
1164 catch (const std::exception& e)
1165 {
1166 LOG_FAIL_FMT("Exception in {}", __PRETTY_FUNCTION__);
1167 LOG_DEBUG_FMT("Error: {}", e.what());
1168 return false;
1169 }
1170 }
1171 };
1172}
1173
1174#undef CHANNEL_RECV_TRACE
1175#undef CHANNEL_SEND_TRACE
1176#undef CHANNEL_RECV_FAIL
1177
1178#pragma clang diagnostic pop
#define CHANNEL_SEND_TRACE(s,...)
Definition channels.h:31
#define CHANNEL_RECV_TRACE(s,...)
Definition channels.h:29
#define CHANNEL_SEND_FAIL(s,...)
Definition channels.h:36
#define CHANNEL_RECV_FAIL(s,...)
Definition channels.h:34
Definition channels.h:159
std::optional< std::vector< uint8_t > > recv_encrypted(std::span< const uint8_t > aad, const uint8_t *&data, size_t &size)
Definition channels.h:1086
static std::chrono::system_clock::duration & min_gap_between_initiation_attempts()
Definition channels.h:162
bool channel_open()
Definition channels.h:993
bool recv_authenticated(std::span< const uint8_t > aad, const uint8_t *&data, size_t &size)
Definition channels.h:1020
Channel(ringbuffer::AbstractWriterFactory &writer_factory, const ccf::crypto::Pem &service_cert_, ccf::crypto::KeyPairPtr node_kp_, const ccf::crypto::Pem &node_cert_, const NodeId &self_, const NodeId &peer_id_, size_t message_limit_)
Definition channels.h:972
bool recv_authenticated_with_load(const uint8_t *&data, size_t &size)
Definition channels.h:1050
bool recv_key_exchange_message(const uint8_t *data, size_t size)
Definition channels.h:1128
bool send(NodeMsgType type, std::span< const uint8_t > aad, std::span< const uint8_t > plain={})
Definition channels.h:1010
void close_channel()
Definition channels.h:1116
static constexpr size_t protocol_version
Definition channels.h:970
Definition pem.h:18
size_t size() const
Definition pem.h:61
const std::string & str() const
Definition pem.h:46
uint8_t * data()
Definition pem.h:51
Definition state_machine.h:14
T value() const
Definition state_machine.h:39
void advance(T state_)
Definition state_machine.h:44
bool check(T state_) const
Definition state_machine.h:34
Definition ring_buffer_types.h:153
Definition key_exchange.h:20
std::vector< uint8_t > get_peer_key_share() const
Definition key_exchange.h:64
void load_peer_key_share(std::span< const uint8_t > ks)
Definition key_exchange.h:84
const std::vector< uint8_t > & get_shared_secret()
Definition key_exchange.h:106
std::vector< uint8_t > get_own_key_share()
Definition key_exchange.h:48
void reset()
Definition key_exchange.h:76
#define LOG_INFO_FMT
Definition logger.h:362
#define LOG_DEBUG_FMT
Definition logger.h:357
#define LOG_FAIL_FMT
Definition logger.h:363
std::unique_ptr< KeyAesGcm > make_key_aes_gcm(std::span< const uint8_t > rawKey)
Free function implementation.
Definition symmetric_key.cpp:102
std::vector< uint8_t > hkdf(MDType md_type, size_t length, const std::span< const uint8_t > &ikm, const std::span< const uint8_t > &salt={}, const std::span< const uint8_t > &info={})
Definition hash.cpp:51
std::shared_ptr< KeyPair > KeyPairPtr
Definition key_pair.h:145
EntropyPtr get_entropy()
Definition entropy.cpp:10
std::shared_ptr< Verifier > VerifierPtr
Definition verifier.h:228
VerifierPtr make_verifier(const std::vector< uint8_t > &cert)
Definition verifier.cpp:18
std::mutex Mutex
Definition locking.h:12
Definition app_interface.h:14
EntityId< NodeIdFormatter > NodeId
Definition entity_id.h:155
uint64_t MsgNonce
Definition channels.h:95
@ key_exchange_init
Definition node_types.h:31
@ key_exchange_final
Definition node_types.h:33
@ key_exchange_response
Definition node_types.h:32
ccf::crypto::FixedSizeGcmHeader< sizeof(MsgNonce)> GcmHdr
Definition channels.h:96
NodeMsgType
Definition node_types.h:19
@ channel_msg
Definition node_types.h:20
@ consensus_msg
Definition node_types.h:21
@ forwarded_msg
Definition node_types.h:22
ChannelStatus
Definition channels.h:42
@ WAITING_FOR_FINAL
Definition channels.h:45
@ ESTABLISHED
Definition channels.h:46
@ INITIATED
Definition channels.h:44
@ INACTIVE
Definition channels.h:43
std::shared_ptr< AbstractWriter > WriterPtr
Definition ring_buffer_types.h:150
void write(uint8_t *&data, size_t &size, const T &v)
Definition serialized.h:106
void skip(const uint8_t *&data, size_t &size, size_t skip)
Definition serialized.h:166
#define RINGBUFFER_WRITE_MESSAGE(MSG,...)
Definition ring_buffer_types.h:255
Definition channels.h:103
uint64_t nonce
Definition channels.h:105
WireNonce(uint64_t nonce_)
Definition channels.h:107
uint64_t get_val() const
Definition channels.h:109
const uint8_t tid
Definition channels.h:104
Definition symmetric_key.h:37
static size_t serialised_size()
Definition symmetric_key.h:42
void deserialise(const std::vector< uint8_t > &ser)
Definition symmetric_key.cpp:56
constexpr auto parse(ParseContext &ctx)
Definition channels.h:55
auto format(const ccf::ChannelStatus &cs, FormatContext &ctx) const
Definition channels.h:61
Definition serializer.h:27
const uint8_t * data
Definition serializer.h:28